Repository navigation
docs: explain that Litestar closes the request container before a stream body runs - #710
Merged
Merged
Conversation
There was a problem hiding this comment.
Benchmark
Details
| Benchmark suite | Current: 254d0f6 | Previous: 6a53052 | Ratio |
|---|---|---|---|
benchmarks/test_guard_by_type.py::test_g16_resolve_by_type |
5132419.502616191 iter/sec (stddev: 7.67501088587994e-9) |
3344547.4895807165 iter/sec (stddev: 1.0870968546091025e-8) |
0.65 |
benchmarks/test_guard_by_type.py::test_g17_resolve_by_type_large_registry |
5134562.506515359 iter/sec (stddev: 7.221167444517781e-9) |
3286913.2436675453 iter/sec (stddev: 2.013901363759457e-8) |
0.64 |
benchmarks/test_guard_cold.py::test_g8_cold_first_resolve |
23504.02948561845 iter/sec (stddev: 0.00003968158606298378) |
15583.560938229652 iter/sec (stddev: 0.00005589262781052146) |
0.66 |
benchmarks/test_guard_cold.py::test_g8b_cold_first_resolve_cached |
18671.26927616026 iter/sec (stddev: 0.000127336494181869) |
12100.100648398899 iter/sec (stddev: 0.0001730919170493535) |
0.65 |
benchmarks/test_guard_concurrency.py::test_g14_concurrent_cached_hit[1] |
665.0660898460719 iter/sec (stddev: 0.00006898430678332252) |
476.83130255084984 iter/sec (stddev: 0.00010632423506027354) |
0.72 |
benchmarks/test_guard_concurrency.py::test_g14_concurrent_cached_hit[2] |
655.5714495211673 iter/sec (stddev: 0.000016949703549031357) |
467.6270143742508 iter/sec (stddev: 0.00004875162860410878) |
0.71 |
benchmarks/test_guard_concurrency.py::test_g14_concurrent_cached_hit[4] |
622.6571342825177 iter/sec (stddev: 0.00003092679358617282) |
435.9540204410922 iter/sec (stddev: 0.00012794436313057943) |
0.70 |
benchmarks/test_guard_concurrency.py::test_g15_concurrent_first_resolve[1] |
20051.539139400258 iter/sec (stddev: 0.000006748585080532474) |
13159.210658012596 iter/sec (stddev: 0.000009360155545735502) |
0.66 |
benchmarks/test_guard_concurrency.py::test_g15_concurrent_first_resolve[2] |
10187.254471243265 iter/sec (stddev: 0.000015732430592774775) |
6507.355046483238 iter/sec (stddev: 0.000024518660851694014) |
0.64 |
benchmarks/test_guard_concurrency.py::test_g15_concurrent_first_resolve[4] |
4935.6938728169725 iter/sec (stddev: 0.000025374712786500923) |
3250.3015805847417 iter/sec (stddev: 0.00006717328500240406) |
0.66 |
benchmarks/test_guard_concurrency.py::test_g15b_concurrent_first_resolve_sibling_children[1] |
15050.892712293216 iter/sec (stddev: 0.00000769301414293898) |
7913.7564102246715 iter/sec (stddev: 0.000024317565710078463) |
0.53 |
benchmarks/test_guard_concurrency.py::test_g15b_concurrent_first_resolve_sibling_children[2] |
6253.911626293615 iter/sec (stddev: 0.000028423941658151908) |
4339.452829715919 iter/sec (stddev: 0.00002768221050812109) |
0.69 |
benchmarks/test_guard_concurrency.py::test_g15b_concurrent_first_resolve_sibling_children[4] |
2983.61095046204 iter/sec (stddev: 0.0000253519066247147) |
1760.8092374067414 iter/sec (stddev: 0.00020176978829819614) |
0.59 |
benchmarks/test_guard_concurrency.py::test_g15c_worker_pool_floor_control[1] |
51851.71102160885 iter/sec (stddev: 0.000002341077981011172) |
41207.2346166668 iter/sec (stddev: 0.000004021744808405116) |
0.79 |
benchmarks/test_guard_concurrency.py::test_g15c_worker_pool_floor_control[2] |
19348.179191230836 iter/sec (stddev: 0.000010129486393952364) |
13054.760695882296 iter/sec (stddev: 0.00001502767377752435) |
0.67 |
benchmarks/test_guard_concurrency.py::test_g15c_worker_pool_floor_control[4] |
8487.884746969681 iter/sec (stddev: 0.00002362266721104138) |
4482.600673431932 iter/sec (stddev: 0.00024437065037094226) |
0.53 |
benchmarks/test_guard_lifecycle.py::test_g6_build_child_container |
2142239.7952493345 iter/sec (stddev: 1.9391568934619136e-8) |
1545345.33870841 iter/sec (stddev: 1.0247001917072238e-7) |
0.72 |
benchmarks/test_guard_lifecycle.py::test_g6b_build_child_container_auto_scope |
2345035.097555192 iter/sec (stddev: 3.525753184315508e-8) |
1675301.379386119 iter/sec (stddev: 2.659498828881931e-8) |
0.71 |
benchmarks/test_guard_lifecycle.py::test_g7_request_lifecycle_batch |
4225.667026267729 iter/sec (stddev: 0.000009359315851851865) |
3055.630518743245 iter/sec (stddev: 0.000016647056391313933) |
0.72 |
benchmarks/test_guard_lifecycle.py::test_g7c_event_loop_floor_control |
74986.32854227745 iter/sec (stddev: 0.0000010295775052242614) |
58397.77008535097 iter/sec (stddev: 0.0000020675509459501996) |
0.78 |
benchmarks/test_guard_lifecycle.py::test_g7b_request_cycle_sync |
570984.3619090661 iter/sec (stddev: 8.510901962037905e-8) |
420635.01627977827 iter/sec (stddev: 8.226526259246025e-8) |
0.74 |
benchmarks/test_guard_lifecycle.py::test_g13_teardown_at_scale |
90815.74856863629 iter/sec (stddev: 0.0000010261939382970725) |
65491.09743504281 iter/sec (stddev: 0.0000017185360029134222) |
0.72 |
benchmarks/test_guard_lifecycle.py::test_g13b_teardown_at_scale_async_no_finalizers |
840.6606421742341 iter/sec (stddev: 0.0008649221635591658) |
596.4248751282753 iter/sec (stddev: 0.0008959028010212933) |
0.71 |
benchmarks/test_guard_resolve.py::test_g1_transient_resolve |
2961259.6902627666 iter/sec (stddev: 2.4820650212542287e-8) |
2162029.5187302334 iter/sec (stddev: 3.466425150134868e-8) |
0.73 |
benchmarks/test_guard_resolve.py::test_g2_cached_resolve |
5025979.539544054 iter/sec (stddev: 4.979058201015785e-9) |
3692378.767749514 iter/sec (stddev: 8.219648124299563e-9) |
0.73 |
benchmarks/test_guard_resolve.py::test_g3_deep_chain |
1163000.6125255304 iter/sec (stddev: 2.9994145371197816e-8) |
742119.3511222858 iter/sec (stddev: 1.6980225347240625e-7) |
0.64 |
benchmarks/test_guard_resolve.py::test_g4_wide_resolve |
627872.9504098769 iter/sec (stddev: 3.3230728462983807e-7) |
474631.2785390143 iter/sec (stddev: 4.1950679955608254e-7) |
0.76 |
benchmarks/test_guard_resolve.py::test_g5_cross_scope |
2719844.892679623 iter/sec (stddev: 2.3298274465621177e-8) |
1999587.6850176 iter/sec (stddev: 2.4759969215001987e-8) |
0.74 |
benchmarks/test_guard_resolve.py::test_g9_context_resolve |
2074364.5158457402 iter/sec (stddev: 1.2599748948578426e-7) |
1367324.472797383 iter/sec (stddev: 1.4520775370835358e-7) |
0.66 |
benchmarks/test_guard_resolve.py::test_g12_override_active_resolve |
1196684.2750771658 iter/sec (stddev: 2.7888897842068113e-8) |
840914.775683592 iter/sec (stddev: 5.011210136758502e-8) |
0.70 |
benchmarks/test_guard_resolve.py::test_g18_alias_hop |
5004567.418467996 iter/sec (stddev: 5.431670102295949e-9) |
3521490.5652616406 iter/sec (stddev: 2.0083148671261934e-8) |
0.70 |
benchmarks/test_guard_validate.py::test_g10_validate_deep_chain |
53014.04364994183 iter/sec (stddev: 0.000014960723607901764) |
29494.93115836232 iter/sec (stddev: 0.0002111487546893482) |
0.56 |
benchmarks/test_guard_validate.py::test_g11_validate_wide |
31109.16040545038 iter/sec (stddev: 0.00001813703380700472) |
20084.07004272152 iter/sec (stddev: 0.00002804624717005632) |
0.65 |
This comment was automatically generated by workflow using github-action-benchmark.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Litestar runs dependency cleanup when the handler returns and before it sends the response (
litestar/routes/http.py, theAsyncExitStackaround the handler call). The per-connection child container is a yield dependency, so it closes at that point. AStreamorServerSentEventbody therefore runs after REQUEST-scoped instances have been finalized.To reproduce: a REQUEST-scoped cached factory with a finalizer, injected with
FromDIand read inside aStreamgenerator, reportsclosed=True. The same setup on modern-di-starlette reportsFalse, because its middleware keeps the child open until the response is sent.This adds a "Streaming responses" section to the Litestar page with the workaround: open a REQUEST child of the root container inside the generator. The example runs under
test-docs-integrations.Changing the plugin to keep the container open through the stream was considered and rejected. It would need ASGI middleware, which costs about 1.5 us on every request, and finalizers would run after the client already has the response. A session that commits in its finalizer could then send a 200 for a commit that later fails.