You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Extract the mutable state for one accepted connection into an explicit connection-local runtime, leaving PreparedApp immutable and shared.
This is the second application implementation slice for ADR 012 proposal #637. It follows #641 and can land before or after #642 depending on the most reviewable intermediate topology.
Problem
Connection handling currently lives as methods borrowing WireframeApp, while local variables and helper contexts separately carry:
the accepted and rewound stream;
framed codec state;
setup state C;
inbound frame pipeline;
deserialization failure count;
message assembly and fragmentation state;
timeout and memory-pressure bookkeeping;
protocol ConnectionContext and outbound actor state;
peer metadata and teardown decisions.
Because no type owns the full connection lifecycle, cleanup occurs as a clean-path tail call. #549 records the concrete bug: when stream processing returns an error after setup succeeds, teardown is skipped.
Proposed design
Introduce a crate-private ConnectionRuntime or a small family of focused connection-owned types. The exact generic parameter list should favour comprehensibility over mirroring every PreparedApp parameter.
The runtime should own or borrow with an unambiguous connection lifetime:
stream/framed codec state;
connection state C after setup succeeds;
peer and connection identifiers;
inbound pipeline, fragmentation, and message-assembly state;
per-connection protocol context and hook invocation state;
read timeout and effective budget state;
a finalization state that guarantees teardown at most once.
Immutable application configuration, route services, serializer/codec templates, application data, and callback definitions remain in PreparedApp.
Lifecycle contract
Once setup returns C, teardown must run exactly once for every terminal connection outcome where Rust unwinding permits cleanup:
clean EOF;
decode or protocol error;
transport read/write error;
timeout-driven termination;
shutdown/cancellation;
handler error;
panic caught at the connection-task supervision boundary, if the teardown future can still be invoked safely.
The implementation may use an explicit async finalization block, a state machine, or a guard plus awaited finalizer. Do not rely on Drop to execute async teardown.
This issue does not silently supersede #549. Either land #549 first and preserve its tests, or satisfy all of #549's acceptance criteria explicitly and close it from the implementing PR.
Ownership requirements
The runtime is not shared across connection tasks.
Mutable pipeline and connection state do not move into Arc<Mutex<_>>.
A connection task owns one runtime value and drives it to completion.
Values that must escape independently, such as PushHandle, remain cloneable handles.
Summary
Extract the mutable state for one accepted connection into an explicit connection-local runtime, leaving
PreparedAppimmutable and shared.This is the second application implementation slice for ADR 012 proposal #637. It follows #641 and can land before or after #642 depending on the most reviewable intermediate topology.
Problem
Connection handling currently lives as methods borrowing
WireframeApp, while local variables and helper contexts separately carry:C;ConnectionContextand outbound actor state;Because no type owns the full connection lifecycle, cleanup occurs as a clean-path tail call. #549 records the concrete bug: when stream processing returns an error after setup succeeds, teardown is skipped.
Proposed design
Introduce a crate-private
ConnectionRuntimeor a small family of focused connection-owned types. The exact generic parameter list should favour comprehensibility over mirroring everyPreparedAppparameter.The runtime should own or borrow with an unambiguous connection lifetime:
Cafter setup succeeds;Immutable application configuration, route services, serializer/codec templates, application data, and callback definitions remain in
PreparedApp.Lifecycle contract
Once setup returns
C, teardown must run exactly once for every terminal connection outcome where Rust unwinding permits cleanup:The implementation may use an explicit async finalization block, a state machine, or a guard plus awaited finalizer. Do not rely on
Dropto execute async teardown.This issue does not silently supersede #549. Either land #549 first and preserve its tests, or satisfy all of #549's acceptance criteria explicitly and close it from the implementing PR.
Ownership requirements
Arc<Mutex<_>>.PushHandle, remain cloneable handles.Fragmenterownership from Remove unambiguous local shared-ownership taxes from runtime hot paths #640 remains direct.Acceptance criteria
PreparedAppcontains no connection-specific mutable state.Chas one owner after creation.Tests
Add table-driven or fixture-based coverage for the lifecycle matrix:
Also assert that the exact
Cvalue produced by setup is moved into teardown and cannot be observed by two owners.Non-goals
Dropimplementation.Dependencies
References
src/app/inbound_handler.rssrc/server/connection_spawner.rssrc/connection/