Skip to content

fix: ensure post() completes before shareHistoricalKeys()#15

Merged
ThomasHalwax merged 1 commit intomainfrom
fix/queue-ordering-key-share
Mar 24, 2026
Merged

fix: ensure post() completes before shareHistoricalKeys()#15
ThomasHalwax merged 1 commit intomainfrom
fix/queue-ordering-key-share

Conversation

@axel-krapotke
Copy link
Copy Markdown
Contributor

Problem

When sharing an E2EE layer, shareHistoricalKeys() found 0 Megolm session keys to share — even though content had just been posted. This meant new members joining the layer had no keys and couldn't decrypt content until the safety-net mechanism fired (requiring the sharing member to be online).

Root Cause

post() did not await its internal __post() call:

Project.prototype.post = async function (layerId, operations) {
  this.__post(layerId, operations, ODINv2_MESSAGE_TYPE)  // ← missing await!
}

So ODIN's share handler sequence:

await replicatedProject.post(id, operations)        // returned immediately!
await replicatedProject.shareHistoricalKeys(id)      // ran before posts were enqueued

The shareHistoricalKeys callback was enqueued in the command queue before the content chunks, ran first, and found no Megolm sessions yet.

Fix

  • post() now awaits __post()
  • __post() uses for..of instead of forEach to serialize chunk scheduling
  • shareHistoricalKeys() is now async, awaits schedule()
  • schedule() is now async, awaits enqueue() to guarantee FIFO insertion order

Testing

  • 68 unit tests passing
  • Manual testing: B shares layer → keys shared immediately → A joins (B offline) → content decrypted instantly ✅

post() did not await __post(), so it returned immediately while
chunks were still being enqueued in the background. When
shareHistoricalKeys() was called right after, its callback was
enqueued before the content chunks — and ran before any Megolm
session existed, finding 0 keys to share.

Additionally, schedule() now awaits enqueue() to guarantee that
FIFO insertion order matches call order (persistent DB entries
take longer to enqueue than in-memory callbacks).

Changes:
- project: post() now awaits __post()
- project: __post() uses for..of instead of forEach to serialize
  chunk scheduling
- project: shareHistoricalKeys() is now async, awaits schedule()
- command-api: schedule() is now async, awaits enqueue()
@ThomasHalwax ThomasHalwax merged commit b6ac9cd into main Mar 24, 2026
@ThomasHalwax ThomasHalwax deleted the fix/queue-ordering-key-share branch March 24, 2026 11:45
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.

2 participants