social: return registration cleanup from Subscribe - #20
Conversation
Client.CloseContext unsubscribes the shared RTA subscription and clears every registered handler, so a caller that only wants to remove its own handler (for example on shutdown) also disables any other Subscribe users on the same client. Add Client.Unsubscribe(ctx, handler), which removes a single handler by identity and tears the RTA subscription down only once the last handler is gone. Handlers must be comparable to be removed; a non-comparable handler returns an error rather than panicking, preserving support for non-comparable handlers in Subscribe/dispatch.
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_088cb957-ff83-48a1-a3ee-5b4105ec807d) |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 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 |
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.
* Accept friend requests reactively via social RTA subscription 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. * Undo social RTA subscription on broadcaster close 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. * Guard against a closed friend-sync Trigger channel 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. * Release the social subscription per-handler instead of client-wide 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. * Use xsapi-owned social and presence clients * Pin merged xsapi social subscription cleanup * Bound reactive friend scans and honor read backoff * Bound social RTA subscription setup
social.Client.CloseContextclears every handler sharing its RTA subscription. A broadcaster shutting down needs to release its own registration while other users of the Xbox client keep receiving events.Change
Subscribe(ctx, handler)to return(func(context.Context) error, error). Each successful call returns its own cleanup function, backed by a unique registration. This removes the proposed handler-basedUnsubscribemethod, reflection, comparability restrictions, and ambiguous matching of duplicate handler values.Repeated or concurrent cleanup is safe. Only final-registration cleanup tears down the shared RTA subscription; failed teardown can be retried. Cleanup from before a client reset cannot remove a new registration. Callbacks already queued may still finish.
This changes the Go method signature. The repository's caller and dependent broadcaster PR HashimTheArab/go-mcxboxbroadcast#13 are updated together; no compatibility wrapper or network-format change is introduced.
Validation:
go test ./... -count=1,go test -race ./social ./rta -count=1, andgit diff --checkpass. Real local WebSocket tests cover selective delivery, duplicate and non-comparable handlers, cleanup retry, client reuse, and concurrent cleanup. Independent review found no actionable issues. No live Xbox calls are used.