-
Notifications
You must be signed in to change notification settings - Fork 198
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
Fix bug in coroutine scheduling. Add ByteStream implementation and simplify Python symbol visitor. #1633
Conversation
…mplify Python symbol visitor. * Bug in coroutine scheduling: In the previous iteration, the runtime crate aws-smithy-http-server-python was exposing the python application implementation as a struct, which was wrapped by the codegenerated App to allow to dynamically building the router. This caused scheduling of coroutines (handlers prefixed with async def) to block becuse we were passing the Python eventloop of the parent process that was stored pre-fork(). This commit changes the runtime PyApp to become a trait, allowing us to dynamically build the router post-fork() and with the right event loop. This change also allowed us to remove a bunch of unnecessary Arc(s). * Add ByteStream implementation Implementation of a ByteStream type for Python that can be roughly used like this: let b = await ByteStream.from_path("file.txt") async for chunk in b: print(chunk) Implement futures_core::stream::Stream for Python ByteStream wrapper. The BytesStream implementation in python can now use a sync Mutex from parking_lot because we are now using pyo3_asyncio::tokio::local_future_into_py() to read a chunk, which supports !Send futures. This allows to simply forward the implementation of Stream (poll_next() and size_hint()) directly to our inner SDK ByteStream. * Simplify Python symbol visitor Inherit from Symbol visitor and override just what is needed to swap Python complex types. Signed-off-by: Bigo <[email protected]>
A new generated diff is ready to view.
A new doc preview is ready to view. |
A new generated diff is ready to view.
A new doc preview is ready to view. |
A new generated diff is ready to view.
A new doc preview is ready to view. |
...in/software/amazon/smithy/rust/codegen/smithy/protocols/HttpBoundProtocolPayloadGenerator.kt
Show resolved
Hide resolved
codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/util/TypeConversionGenerator.kt
Outdated
Show resolved
Hide resolved
codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/util/TypeConversionGenerator.kt
Outdated
Show resolved
Hide resolved
codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/util/TypeConversionGenerator.kt
Outdated
Show resolved
Hide resolved
codegen/src/main/kotlin/software/amazon/smithy/rust/codegen/util/TypeConversionGenerator.kt
Outdated
Show resolved
Hide resolved
* with wrappers compatible with Python, without touching the original implementation coming from `aws-smithy-types`. | ||
*/ | ||
class TypeConversionGenerator(private val model: Model, private val symbolProvider: RustSymbolProvider, private val runtimeConfig: RuntimeConfig) { | ||
private fun findOldSymbol(shape: Shape): Symbol { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like this is making assumptions about what the differences will be between the default symbol provider and the language bindings code generator's symbol provider. Is there a way to make this more future proof?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. TBH I don't know how to make this more future proof as we are learning as we go here :)
tracing = "0.1.35" | ||
tracing-subscriber = { version = "0.3.11", features = ["env-filter"] } | ||
tracing = "0.1.36" | ||
tracing-subscriber = { version = "0.3.15", features = ["env-filter"] } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this dependency on tracing-subscriber
intentional? My understanding is that libraries should depend on tracing
, and applications should depend on tracing-subscriber
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This dependency is needed here as this crate exposes a functionality used by the codegenerator to setup the subscriber to allow logging to flow through tracing
for both Python and Rust.
The user of the Python version does not have easy access to Rust functionalities such has tracing, so the logging.rs
file is handling it for them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In short this runtime crate provide most of the application for the Python server. The rest is code-generated.
A new generated diff is ready to view.
A new doc preview is ready to view. |
A new generated diff is ready to view.
A new doc preview is ready to view. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing patch! Especially the refactor of PyApp
trait becomes footgun-proof. Thank you for working on this huge change!
...otlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonServerSymbolProvider.kt
Outdated
Show resolved
Hide resolved
...otlin/software/amazon/smithy/rust/codegen/server/python/smithy/PythonServerSymbolProvider.kt
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just did a simple load testing against the streaming endpoint /radio
of pokemon server with 10 workers. It didn't crash and the response time seems reasonable (at least not blocked). I am going to approve this.
Server Software: | |||
---|---|---|---|
Server Hostname: | 127.0.0.1 | ||
Server Port: | 13734 | ||
Document Path: | /radio | ||
Document Length: | Variable | ||
Concurrency Level: | 100 | ||
Time taken for tests: | 421.215 seconds | ||
Complete requests: | 1000 | ||
Failed requests: | 0 | ||
Total transferred: | 3023157030 bytes | ||
HTML transferred: | 3023061030 bytes | ||
Requests per second: | 2.37 | ||
Transfer rate: | 7009.01 kb/s received | ||
Connection Times (ms) | |||
min | avg | max | |
Connect: | 0 | 3 | 14 |
Processing: | 3715 | 38975 | 96078 |
Total: | 3715 | 38978 | 96092 |
A new generated diff is ready to view.
A new doc preview is ready to view. |
@jdisanti I have fixed all the comments apart from the one about making the TypeConversionGenerator more future-proof, since I don't have a good answer :( |
A new generated diff is ready to view.
A new doc preview is ready to view. |
Description
Bug in coroutine scheduling:
In the previous iteration, the runtime crate aws-smithy-http-server-python
was exposing the python application implementation as a struct, which
was wrapped by the codegenerated App to allow to dynamically building
the router.
This caused scheduling of coroutines (handlers prefixed with async def)
to block becuse we were passing the Python eventloop of the parent
process that was stored pre-fork().
This commit changes the runtime PyApp to become a trait, allowing us to
dynamically build the router post-fork() and with the right event loop.
This change also allowed us to remove a bunch of unnecessary Arc(s).
Add ByteStream implementation
Implementation of a ByteStream type for Python that can be roughly used like this:
Implement futures_core::stream::Stream for Python ByteStream wrapper.
The BytesStream implementation in python can now use a sync Mutex from
parking_lot because we are now using pyo3_asyncio::tokio::local_future_into_py()
to read a chunk, which supports !Send futures.
This allows to simply forward the implementation of Stream (poll_next()
and size_hint()) directly to our inner SDK ByteStream.
Simplify Python symbol visitor
Inherit from Symbol visitor and override just what is needed to swap Python complex
types.
Signed-off-by: Bigo [email protected]
Checklist
CHANGELOG.next.toml
if I made changes to the smithy-rs codegen or runtime cratesCHANGELOG.next.toml
if I made changes to the AWS SDK, generated SDK code, or SDK runtime cratesBy submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.