mirror of
https://github.com/versity/versitygw.git
synced 2026-09-23 00:14:15 +00:00
Review of the publication path found that ownership could change hands at the wrong moment and that records could disagree with both the wire response and the underlying operation. Successful transfers lost their completion record: the native completion calls fire the teardown callback synchronously, so the callback claimed the publication first and logged every completed transfer as an expiry, and committed PUTs produced no object-created events. The READY handler now reserves the publication before invoking any completion call; a reserved record is invisible to the callback, and the handler publishes the real outcome exactly once. The same race existed at creation: the PREPARE finalizer can reap an expired session and fire the callback before the session is registered, leaving an orphan entry whose only notification already happened. Registration now runs before the finalizing call, a notification that arrives first is parked and consumed by the registration, and a failed finalization drops the entry. Retained records referenced the request's pooled header buffer, so a later request could rewrite a tracked session's bucket and key; captured strings are cloned now. The synthesized publication path follows the same rule for the event senders, which serialize asynchronously. Operational sinks classify plain errors as 500 on their own, so a resource-limit rejection logged 500 while the client saw 429. The publication renders non-S3 errors through the route error mapping before the record reaches the sinks, and the expiry record carries a dedicated SessionExpired code instead of a generic one. Malformed PUT headers now preserve the operation in the record.