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

Fix bug in coroutine scheduling. Add ByteStream implementation and simplify Python symbol visitor. #1633

Merged
merged 13 commits into from
Aug 19, 2022

Conversation

crisidev
Copy link
Contributor

@crisidev crisidev commented Aug 12, 2022

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:

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]

Checklist

  • I have updated CHANGELOG.next.toml if I made changes to the smithy-rs codegen or runtime crates
  • I have updated CHANGELOG.next.toml if I made changes to the AWS SDK, generated SDK code, or SDK runtime crates

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

…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]>
@crisidev crisidev added bug Something isn't working enhancement New feature or request server Rust server SDK labels Aug 12, 2022
@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@crisidev crisidev marked this pull request as ready for review August 15, 2022 11:26
@crisidev crisidev requested review from a team as code owners August 15, 2022 11:26
@crisidev crisidev changed the title [WIP] Fix bug in coroutine scheduling. Add ByteStream implementation and simplify Python symbol visitor. Fix bug in coroutine scheduling. Add ByteStream implementation and simplify Python symbol visitor. Aug 15, 2022
@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

* 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 {
Copy link
Collaborator

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?

Copy link
Contributor Author

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"] }
Copy link
Collaborator

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.

Copy link
Contributor Author

@crisidev crisidev Aug 18, 2022

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.

Copy link
Contributor Author

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.

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Copy link
Contributor

@weihanglo weihanglo left a 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!

Copy link
Contributor

@weihanglo weihanglo left a 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: 37153897596078
Total: 37153897896092

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@crisidev
Copy link
Contributor Author

@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 :(

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@crisidev crisidev merged commit 5455c4e into main Aug 19, 2022
@crisidev crisidev deleted the crisidev/oxypi-fix-asyncio-and-bytestreams branch August 19, 2022 18:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request server Rust server SDK
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants