Skip to content

fix(s3): treat any 2xx as success in store_request#430

Open
tpjg wants to merge 5 commits into
jamsocket:mainfrom
tpjg:fix-s3-204-success
Open

fix(s3): treat any 2xx as success in store_request#430
tpjg wants to merge 5 commits into
jamsocket:mainfrom
tpjg:fix-s3-204-success

Conversation

@tpjg

@tpjg tpjg commented Jun 3, 2026

Copy link
Copy Markdown

A successful S3 DELETE returns 204 No Content, not 200. The previous match only accepted StatusCode::OK, so every successful delete fell through to the catch-all arm and was misreported as a ConnectionError ("Received 204 No Content from S3-compatible API."). Accept any 2xx.

Timo Gatsonides added 5 commits June 3, 2026 09:49
A successful S3 DELETE returns 204 No Content, not 200. The previous
match only accepted StatusCode::OK, so every successful delete fell
through to the catch-all arm and was misreported as a ConnectionError
("Received 204 No Content from S3-compatible API."). Accept any 2xx.
…unded growth

Awareness::remove_state removed the client from `states` but
update_meta left a permanent entry in `meta`. On a long-lived
server-side Awareness (one per loaded document), this grows by one
entry for every client session that ever connected - a slow,
unbounded memory leak on documents that never go idle.

remove_state now also prunes meta entries that have no corresponding
state and were last touched more than 30s ago (the y-protocols
outdatedTimeout convention). The grace window preserves the clock
check that rejects stale updates from a just-disconnected client.

Uses time::OffsetDateTime rather than std::time::Instant because
y-sweet-worker compiles this crate to wasm32, where Instant::now
panics.
Every DocConnection subscribes to the shared Awareness, so an awareness
update applied from one connection was broadcast to all connections
including the one that sent it. The sender then absorbs the echo via the
logical-clock check, but it doubles awareness traffic per update and,
combined with clients that rebroadcast remote-origin updates (npm
@y-sweet/client <= 0.9.1 does), produces a sustained recv->send
ping-pong pattern between idle clients.

Tag awareness updates with a per-connection origin id
(Awareness::apply_update_from / Protocol::handle_awareness_update_from)
and skip the broadcast callback on the originating connection. Changes
with no connection origin (e.g. state removal on disconnect) still reach
every connection.
handleAwarenessUpdate re-broadcast every awareness update regardless of
origin (inherited from y-websocket), so every update received from the
server was immediately sent back to it. The server absorbs the duplicate
via the logical-clock check, but with two idle clients each received
awareness frame still triggered an outgoing frame - a continuous
recv->send ping-pong that doubles awareness traffic.

Skip broadcasting updates whose origin is the provider itself (i.e.
applied from a server message), except entries for our own clientID:
y-protocols bumps the local clock and keeps the state when a remote
update tries to remove it, and that re-assertion must reach the server.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant