@@ -74,6 +74,13 @@ export type AgentAwarenessRegistrationStatus = "unknown" | "pending" | "register
7474let registrationStatus : AgentAwarenessRegistrationStatus = "unknown" ;
7575const registrationStatusListeners = new Set < ( ) => void > ( ) ;
7676
77+ // Registration runs both through the background queue and directly via
78+ // refreshAgentAwarenessRegistration, so attempts can overlap. Counting relay
79+ // acceptances lets a failing attempt detect that a concurrent attempt already
80+ // succeeded while it was in flight, so a stale failure cannot overwrite a
81+ // registration the relay accepted.
82+ let registrationSuccessCount = 0 ;
83+
7784function setRegistrationStatus ( next : AgentAwarenessRegistrationStatus ) : void {
7885 if ( registrationStatus === next ) {
7986 return ;
@@ -84,6 +91,18 @@ function setRegistrationStatus(next: AgentAwarenessRegistrationStatus): void {
8491 }
8592}
8693
94+ function markRegistrationSucceeded ( ) : void {
95+ registrationSuccessCount ++ ;
96+ setRegistrationStatus ( "registered" ) ;
97+ }
98+
99+ function markRegistrationFailed ( successCountAtAttemptStart : number ) : void {
100+ if ( registrationSuccessCount !== successCountAtAttemptStart ) {
101+ return ;
102+ }
103+ setRegistrationStatus ( "failed" ) ;
104+ }
105+
87106export function getAgentAwarenessRegistrationStatus ( ) : AgentAwarenessRegistrationStatus {
88107 return registrationStatus ;
89108}
@@ -316,7 +335,7 @@ function registerDeviceWithRelay(
316335 catch : ( cause ) => cause ,
317336 } ) . pipe ( Effect . orElseSucceed ( ( ) => null ) ) ;
318337 if ( persisted && persisted . identity === identity && persisted . signature === signature ) {
319- setRegistrationStatus ( "registered" ) ;
338+ markRegistrationSucceeded ( ) ;
320339 logRegistrationDebug ( "relay device registration skipped; already registered for account" , {
321340 expectedGeneration,
322341 } ) ;
@@ -331,7 +350,7 @@ function registerDeviceWithRelay(
331350 clerkToken : token ,
332351 payload : body ,
333352 } ) ;
334- setRegistrationStatus ( "registered" ) ;
353+ markRegistrationSucceeded ( ) ;
335354 yield * Effect . promise ( ( ) =>
336355 saveAgentAwarenessRegistrationRecord ( { identity, signature } ) . catch ( ( error : unknown ) => {
337356 logRegistrationError ( "persist registration record failed" , error ) ;
@@ -466,11 +485,12 @@ function startPendingDeviceRegistration(): void {
466485 } ;
467486 activeDeviceRegistration = registration ;
468487 registration . operation = ( async ( ) => {
488+ const successCountAtStart = registrationSuccessCount ;
469489 const result = await settleAsyncResult ( ( ) =>
470490 runtime . runPromiseExit ( registerDevice ( next . input , generation ) ) ,
471491 ) ;
472492 if ( result . _tag === "Failure" && ! isAtomCommandInterrupted ( result ) ) {
473- setRegistrationStatus ( "failed" ) ;
493+ markRegistrationFailed ( successCountAtStart ) ;
474494 logRegistrationError ( next . context , squashAtomCommandFailure ( result ) ) ;
475495 }
476496 logRegistrationDebug ( "device registration finished" , { generation } ) ;
@@ -675,14 +695,17 @@ export function refreshAgentAwarenessRegistration(): Effect.Effect<
675695 never ,
676696 ManagedRelay . ManagedRelayClient
677697> {
678- return registerDeviceForCurrentUser ( ) . pipe (
679- Effect . catch ( ( error ) =>
680- Effect . sync ( ( ) => {
681- setRegistrationStatus ( "failed" ) ;
682- logRegistrationError ( "device registration refresh failed" , error ) ;
683- } ) ,
684- ) ,
685- ) ;
698+ return Effect . suspend ( ( ) => {
699+ const successCountAtStart = registrationSuccessCount ;
700+ return registerDeviceForCurrentUser ( ) . pipe (
701+ Effect . catch ( ( error ) =>
702+ Effect . sync ( ( ) => {
703+ markRegistrationFailed ( successCountAtStart ) ;
704+ logRegistrationError ( "device registration refresh failed" , error ) ;
705+ } ) ,
706+ ) ,
707+ ) ;
708+ } ) ;
686709}
687710
688711export function __resetAgentAwarenessRemoteRegistrationForTest ( ) : void {
@@ -703,6 +726,7 @@ export function __resetAgentAwarenessRemoteRegistrationForTest(): void {
703726 activeDeviceRegistration = null ;
704727 pendingDeviceRegistration = null ;
705728 registrationStatus = "unknown" ;
729+ registrationSuccessCount = 0 ;
706730 registrationStatusListeners . clear ( ) ;
707731}
708732
0 commit comments