Skip to content

fix: replace in-flight presence sync sequences#2261

Open
w3lld1 wants to merge 3 commits into
ably:mainfrom
w3lld1:fix/rtp18a-presence-sync
Open

fix: replace in-flight presence sync sequences#2261
w3lld1 wants to merge 3 commits into
ably:mainfrom
w3lld1:fix/rtp18a-presence-sync

Conversation

@w3lld1

@w3lld1 w3lld1 commented Jul 12, 2026

Copy link
Copy Markdown

Summary

  • reset residual presence members when a new sync sequence replaces one already in progress
  • track the sync sequence ID so pages from the same multi-message sync continue accumulating normally
  • enable the RTP18a UTS regression test as a conforming test

Validation

  • npm run test:uts:unit (1,052 passing, 55 pending)
  • npx mocha --no-config --require tsx/cjs test/uts/realtime/unit/presence/presence_sync.test.ts (14 passing)
  • npx eslint src/common/lib/client/presencemap.ts src/common/lib/client/realtimepresence.ts
  • npx prettier --check src/common/lib/client/presencemap.ts src/common/lib/client/realtimepresence.ts test/uts/realtime/unit/presence/presence_sync.test.ts
  • git diff --check

Fixes #2215

Summary by CodeRabbit

  • Bug Fixes
    • Improved realtime presence synchronization so starting a sync while another is active correctly resets and rebuilds the residual membership state from the latest data.
    • Updated residual handling to ignore entries marked as absent and to consistently mark sync as in progress for each new start.
    • Prevented duplicate or incorrect member-sync initialization by validating sync sequences via identifiers.
  • Tests
    • Updated realtime presence sync tests and comments to reflect the new sync start behavior during in-progress syncing.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ccee151c-ec5a-4b8c-afae-5c52e286ddee

📥 Commits

Reviewing files that changed from the base of the PR and between 7786425 and 2359d36.

📒 Files selected for processing (1)
  • src/common/lib/client/presencemap.ts

Walkthrough

Presence synchronization now resets residual membership state for every new sync and tracks sync identifiers to distinguish duplicate updates from new sequences. The RTP18a test is enabled unconditionally and its comments reflect the updated behavior.

Changes

Presence sync lifecycle

Layer / File(s) Summary
Reset in-flight sync state
src/common/lib/client/presencemap.ts, test/uts/realtime/unit/presence/presence_sync.test.ts
PresenceMap.startSync() always rebuilds residual membership from the current map, excluding absent entries, and marks synchronization active; the RTP18a test now runs without a deviation guard.
Track sync sequence identifiers
src/common/lib/client/realtimepresence.ts
RealtimePresence parses and stores sync identifiers, starts synchronization only for new sequences, and clears the identifier when synchronization ends.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PresenceUpdate
  participant RealtimePresence
  participant PresenceMap
  PresenceUpdate->>RealtimePresence: deliver syncChannelSerial
  RealtimePresence->>PresenceMap: startSync for a new syncId
  PresenceMap->>PresenceMap: rebuild residualMembers
  PresenceUpdate->>RealtimePresence: deliver sync end
  RealtimePresence->>PresenceMap: endSync and clear syncId
Loading

Suggested reviewers: lawrence-forooghian, ttypic

Poem

A rabbit hops through syncs anew,
Resetting maps with every cue.
IDs keep each sequence bright,
Old flows fade into the night.
Tests now run to guard the view—
Hop, hop, done! 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: replacing in-flight presence sync sequences.
Linked Issues check ✅ Passed The changes reset residual members on new syncs and discard prior in-flight sequences, matching RTP18a and its regression test.
Out of Scope Changes check ✅ Passed The code and test changes stay focused on presence sync replacement behavior and related regression coverage.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/common/lib/client/realtimepresence.ts (1)

307-309: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

onAttached starts a sync without setting _syncId, causing a redundant startSync() on first setPresence.

onAttached() (line 358) calls this.members.startSync() but never sets this._syncId. When the first setPresence arrives with a real syncId, the condition syncId !== this._syncId (string !== undefined) is true, triggering a second startSync() that resets residualMembers again. This is currently harmless because no members are processed between the two calls, but it's an inconsistency that could become a bug if the flow changes.

Consider setting _syncId in onAttached or documenting that the redundant call is expected.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/common/lib/client/realtimepresence.ts` around lines 307 - 309, Update
onAttached to assign the active sync identifier to _syncId when it calls
members.startSync(), so the first setPresence does not trigger a redundant
startSync through the syncId !== this._syncId check. Preserve the existing
synchronization behavior for subsequent sync ID changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/common/lib/client/presencemap.ts`:
- Around line 140-142: Update startSync() when assigning residualMembers so the
copied map excludes entries whose action is 'absent'. Preserve all non-absent
entries and the existing sync replacement and setInProgress behavior.

---

Nitpick comments:
In `@src/common/lib/client/realtimepresence.ts`:
- Around line 307-309: Update onAttached to assign the active sync identifier to
_syncId when it calls members.startSync(), so the first setPresence does not
trigger a redundant startSync through the syncId !== this._syncId check.
Preserve the existing synchronization behavior for subsequent sync ID changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8492ebe0-9a14-49da-8f9c-55c0e5521923

📥 Commits

Reviewing files that changed from the base of the PR and between 2ed28c7 and 0645dff.

📒 Files selected for processing (3)
  • src/common/lib/client/presencemap.ts
  • src/common/lib/client/realtimepresence.ts
  • test/uts/realtime/unit/presence/presence_sync.test.ts

Comment thread src/common/lib/client/presencemap.ts Outdated
@w3lld1

w3lld1 commented Jul 12, 2026

Copy link
Copy Markdown
Author

Addressed the tombstone edge case in 77864256: replacement syncs now exclude absent entries from residualMembers, preventing a second synthesized leave for members already removed during the previous sync.

Validation:

  • pnpm exec prettier --check src/common/lib/client/presencemap.ts
  • pnpm exec eslint src/common/lib/client/presencemap.ts
  • focused presence sync suite: 14 passing

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/common/lib/client/presencemap.ts`:
- Around line 140-148: Initialize residualMembers in the sync replacement logic
with Object.create(null) instead of a regular object, preserving the existing
filtering and assignments in the surrounding loop to prevent prototype-based
keys from affecting Object.prototype.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b161bb93-b527-4888-945e-e50357cccb03

📥 Commits

Reviewing files that changed from the base of the PR and between 0645dff and 7786425.

📒 Files selected for processing (1)
  • src/common/lib/client/presencemap.ts

Comment thread src/common/lib/client/presencemap.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

New presence sync does not discard previous in-flight sync (RTP18a)

1 participant