Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] netty-cats: support multipart requests #3933

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

kciesielski
Copy link
Member

@kciesielski kciesielski commented Jul 15, 2024

Partially addresses #499 - adds support for multipart requests. Responses will be implemented in a separate PR.

  1. No changes to NettyServerHandler, a multipart request is just a StreamedHttpRequest passed to NettyRequestBody
  2. NettyRequestBody delegates processing of such a request to backend-specific implementation of publisherToMultipart
  3. For netty-cats, publisherToMultipart processes converts the reactive Publisher to a fs2 Stream of elements of type HttpContent. Then these elements are passed to a stateful io.netty.handler.codec.http.multipart.HttpPostRequestDecoder, which, after collecting enough of them, can produce full parts.
  4. Parts are converter to tapir Parts using NettyRequestBody.toRawPart - intended to be common for all backends.
  • needs more tests (body types, chunked HTTP requests)
  • documentation
  • refactoring

@kciesielski kciesielski added enhancement New feature or request Netty labels Jul 15, 2024
@kciesielski kciesielski requested a review from adamw July 15, 2024 12:23
monad
.blocking {
// this operation is the one that does potential I/O (writing files)
// TODO not thread-safe? (visibility of internal state changes?)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: This is the part that concerns me. The decoder is stateful, so it has an internal state changed with every call to offer. Each time a new HttpContent flows through the stream, the monad.blocking call gets a thread from the blocking pool, where it calls offer. There are no race conditions, but aren't internals of the decoder risking visibility issues because of such circumstances?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine as long as there's some memory barrier along the way (see e.g. https://stackoverflow.com/questions/12438464/volatile-variables-and-other-variables). There should be a couple of those along the way, I suspect putting back/obtaining a thread to execute blocking ops itself imposes at least one such barrier.

file <- createFile(serverRequest)
_ <- writeBytesToFile(httpData.get(), file)
} yield file)
else monad.unit(httpData.getFile())
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: Netty decoder creates the file (if it's > 16KB), so we can just get its handle here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Netty
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants