Skip to content

Commit febce39

Browse files
committed
fix: implement navigator lock with retry logic for Supabase client initialization
1 parent 48dd051 commit febce39

1 file changed

Lines changed: 60 additions & 1 deletion

File tree

src/app/services/supabase.service.ts

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Injectable } from '@angular/core';
2+
import { navigatorLock } from '@supabase/auth-js';
23
import { SupabaseClient, createClient } from '@supabase/supabase-js';
34
import type { Database, Json } from '../../db/database.types';
45
import { environment } from '../../environments/environment';
@@ -69,6 +70,45 @@ interface CreateAiFeedbackDto {
6970
suggestions: AiSuggestionItemDto[];
7071
}
7172

73+
type LockFunction = typeof navigatorLock;
74+
75+
interface LockRetryConfig {
76+
fallbackAcquireTimeoutMs: number;
77+
retryIntervalMs: number;
78+
maxAttempts: number;
79+
}
80+
81+
const createNavigatorLockWithRetry = (config: LockRetryConfig): LockFunction => {
82+
const { fallbackAcquireTimeoutMs, retryIntervalMs, maxAttempts } = config;
83+
84+
const delay = (ms: number): Promise<void> =>
85+
new Promise(resolve => {
86+
setTimeout(resolve, ms);
87+
});
88+
89+
const isAcquireTimeoutError = (error: unknown): boolean =>
90+
Boolean(error && typeof error === 'object' && 'isAcquireTimeout' in error);
91+
92+
return async (name, acquireTimeout, fn) => {
93+
let attempt = 0;
94+
95+
const effectiveAcquireTimeout =
96+
acquireTimeout === 0 ? fallbackAcquireTimeoutMs : acquireTimeout;
97+
98+
while (true) {
99+
try {
100+
return await navigatorLock(name, effectiveAcquireTimeout, fn);
101+
} catch (error) {
102+
if (!isAcquireTimeoutError(error) || attempt >= maxAttempts) {
103+
throw error;
104+
}
105+
attempt += 1;
106+
await delay(retryIntervalMs);
107+
}
108+
}
109+
};
110+
};
111+
72112
/**
73113
* Service for managing Supabase client and database operations.
74114
* Provides centralized access to Supabase functionality with proper typing.
@@ -94,7 +134,26 @@ export class SupabaseService {
94134
);
95135
}
96136

97-
this.client = createClient<Database>(supabaseUrl, supabaseKey);
137+
const supportsNavigatorLocks = typeof navigator !== 'undefined' && 'locks' in navigator;
138+
139+
const lockFunction = supportsNavigatorLocks
140+
? createNavigatorLockWithRetry({
141+
fallbackAcquireTimeoutMs: 5000,
142+
retryIntervalMs: 200,
143+
maxAttempts: 25,
144+
})
145+
: undefined;
146+
147+
this.client = createClient<Database>(supabaseUrl, supabaseKey, {
148+
auth: {
149+
// Keep sessions persisted and refreshed automatically
150+
persistSession: true,
151+
autoRefreshToken: true,
152+
detectSessionInUrl: true,
153+
// Configure navigator lock retries to avoid immediate acquire failures
154+
...(lockFunction ? { lock: lockFunction } : {}),
155+
},
156+
});
98157
}
99158

100159
/**

0 commit comments

Comments
 (0)