Accept friend requests reactively via social RTA subscription - #13
Conversation
Friend sync accepted incoming friend requests only on the poll interval, so a new request waited up to one UpdateInterval to be accepted. Java MCXboxBroadcast accepts them immediately off an RTA social subscription (IncomingFriendRequestCountChanged -> acceptPendingFriendRequests). Subscribe to each account's go-xsapi/v2 social RTA feed and feed its events into the existing sync loop through a new FriendSyncer.Trigger channel, so an incoming friend request (or any relationship change) runs an immediate sync pass in the same goroutine that owns the rate-limit state. Events are coalesced (non-blocking send to a size-1 channel). The subscription is best-effort: the periodic syncer remains the backstop, the RTA connection re-subscribes after transient drops, and a nil Trigger keeps a syncer purely periodic. Closes #12.
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_10960a4f-131c-478d-bf55-13a9f8a8c6f7) |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (5)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe change adds independent sub-account sessions, relay-aware broadcaster lifecycle handling, and social RTA-triggered friend synchronization. Friend sync now supports immediate triggers, read backoff scheduling, and coordinated subscription cleanup. ChangesBroadcaster session lifecycle and reactive friend sync
Priority: ➖ Normal Estimated code review effort: 4 (Complex) | ~60 minutes Change: Feature Sequence Diagram(s)sequenceDiagram
participant SocialRTA
participant Broadcaster
participant FriendSyncer
participant XboxSocialAPI
SocialRTA->>Broadcaster: deliver friend event
Broadcaster->>FriendSyncer: signal Trigger
FriendSyncer->>XboxSocialAPI: run immediate friend sync
Broadcaster->>SocialRTA: clean up subscription on shutdown
Merge Risk: ⚪ Minimal · up to Reactive friend synchronization retains polling fallback, respects read backoff, and cleans up registrations without disrupting shared social clients. No unresolved merge-blocking risk was identified. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 18 functions across 6 files. (1 skipped: 1 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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. Comment |
The social subscription created for reactive friend sync was never released. b.ctx only scopes the subscribe handshake; once subscribed, go-xsapi keeps the subscription active and appends a handler on each later Subscribe. A library caller that reuses an external xsapi.Client across broadcaster restarts would accumulate stale handlers, and events would keep dispatching after the syncer stopped (Close only closes clients the broadcaster created itself). Bind each subscription's lifetime to the broadcaster: a dedicated goroutine unsubscribes once b.ctx is canceled, and Close waits on socialWg so the subscriptions are undone before it returns. A reused client is left clean, so a subsequent broadcaster re-subscribes without duplicating handlers.
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_caa1aad2-6d61-4f4a-b7d8-465aa061634b) |
A closed Trigger would receive forever, spinning Run through runSync and bypassing UpdateInterval. Use a two-value receive and nil the channel out when it is closed so the case stops firing.
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_26fb78ff-a3f5-48bc-97ba-ecc8731d1370) |
|
@coderabbitai review |
✅ Action performedReview finished.
|
Closing one broadcaster called social CloseContext, which unsubscribes the shared RTA subscription and clears every handler on the client. That could disable other Social().Subscribe users on a shared xsapi.Client. Use the new go-xsapi social Client.Unsubscribe(ctx, handler) to remove only the broadcaster's own handler; the RTA subscription is torn down only when its last handler is gone. Bumps the go-xsapi replace to the commit that adds Unsubscribe. Depends on HashimTheArab/go-xsapi#20; the replace pins that branch commit and should be re-pinned to lunar once it merges.
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_5c691dae-ff5c-4292-a0d0-423cdc2e51d3) |
|
cursor review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c907b9e. Configure here.

Friend requests currently wait for the polling interval. Subscribe to each enabled account's Social RTA events so changes can request an earlier sync using the Xbox client's existing WebSocket.
All sync passes share a schedule with at least 20 seconds between completed passes. Events during that gap stay pending and coalesce into one pass. Polling and expiry use the same schedule, so they cannot cause back-to-back scans. A completed scan also resets the polling deadline.
Friend-list reads honor
Retry-After, including failures while fetching pending requests. A throttled pending-list read stops the remaining reads in that pass. Throttled reads retry when the delay expires, even without another event. HTTP 429 responses without a usable delay fall back to 20 seconds. Follow and unfollow keep their separate backoff.Subscription setup stays off the startup path and has a 15-second timeout, so a missing RTA acknowledgment cannot hold the shared subscription lock indefinitely. Polling continues if setup fails. Shutdown waits for removal of only the broadcaster's own registration, preserving other subscribers sharing the Xbox client.
This builds on merged #28 and pins merged go-xsapi
lunarcommit5e753424fe8d, which supplies the registration cleanup function.Validation:
go test -race ./... -count=1andgo vet ./...pass.codex review --base origin/mainwithgpt-6-astraathighfound an unbounded setup handshake. That finding is fixed; the second full review of5b3e079reports no actionable regressions and passed its full and focused test runs.No live Xbox testing was performed.
Summary by CodeRabbit
New Features
Bug Fixes
Tests