Skip to content

Commit 59517fd

Browse files
committed
Fix live activity replay expiry and same-identity registration retry
- Skip replay delivery when the aggregate is null but non-terminal rows remain: an all-expired row set is ambiguous (dead environment vs. a healthy long-running agent whose meaningful state has not changed), so ending the Live Activity on foreground could kill a healthy activity. - Only skip device re-registration for an unchanged identity when the previous attempt actually registered with the relay, so failed or stalled registrations retry when the auth effect re-runs.
1 parent 5086c14 commit 59517fd

2 files changed

Lines changed: 15 additions & 1 deletion

File tree

apps/mobile/src/features/agent-awareness/remoteRegistration.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,11 @@ export function setAgentAwarenessRelayTokenProvider(
186186
refreshActiveLiveActivityRemoteRegistration(),
187187
"active live activity registration after cloud sign-in failed",
188188
);
189-
if (isExistingIdentity) {
189+
// An unchanged identity only skips re-registration when the previous attempt
190+
// actually reached the relay; a failed or stalled attempt must retry the next
191+
// time the auth effect re-runs, or the device stays unregistered until an
192+
// unrelated event (token rotation, environment link) happens to enqueue one.
193+
if (isExistingIdentity && registrationStatus === "registered") {
190194
return;
191195
}
192196
enqueueDeviceRegistration({}, "device registration after cloud sign-in failed");

infra/relay/src/agentActivity/AgentActivityPublisher.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,16 @@ export const make = Effect.gen(function* () {
119119
terminalState: null,
120120
nowMs: now.epochMilliseconds,
121121
});
122+
// A null aggregate is ambiguous while non-terminal rows still exist:
123+
// they may belong to a dead environment, or to a healthy long-running
124+
// agent whose meaningful state (and therefore updatedAt) has not changed
125+
// within the TTL. Sending in that case would end a possibly-healthy Live
126+
// Activity on every foreground, so replay only delivers when live rows
127+
// remain or the rows are truly gone (the thread ended and its end push
128+
// may have been lost).
129+
if (aggregate === null && activeStates.some((state) => !isTerminalPhase(state))) {
130+
return null;
131+
}
122132
return yield* apnsDeliveries.sendForTarget({
123133
target,
124134
aggregate,

0 commit comments

Comments
 (0)