feat: add navigator lock debugging to track down some rare issue (#39688)

* feat: add navigator lock debugging to track down some rare issue

* send exception to sentry
This commit is contained in:
Stojan Dimitrovski authored and GitHub committed 2025-10-21 11:40:33 +02:00
1 parent bda94ac187
commit 401d6fe892
3 files changed
+73 -3

No files matched your search

+6 -1
View File
@@ -1,6 +1,11 @@
import { gotrueClient } from 'common'
import * as Sentry from '@sentry/nextjs'
import { gotrueClient, setCaptureException } from 'common'
import { useEffect } from 'react'
setCaptureException((e: any) => {
Sentry.captureException(e)
})
export const auth = gotrueClient
export async function getAccessToken() {
+6 -1
View File
@@ -1,6 +1,11 @@
import * as Sentry from '@sentry/nextjs'
import type { JwtPayload } from '@supabase/supabase-js'
import { getAccessToken, type User } from 'common/auth'
import { gotrueClient } from 'common/gotrue'
import { gotrueClient, setCaptureException } from 'common/gotrue'
setCaptureException((e: any) => {
Sentry.captureException(e)
})
export const auth = gotrueClient
export { getAccessToken }
+61 -1
View File
@@ -115,12 +115,72 @@ const logIndexedDB = (message: string, ...args: any[]) => {
})()
}
let captureException: ((e: any) => any) | null = null
export function setCaptureException(fn: typeof captureException) {
captureException = fn
}
async function debuggableNavigatorLock<R>(
name: string,
acquireTimeout: number,
fn: () => Promise<R>
): Promise<R> {
let stackException: any
try {
throw new Error('Lock is being held for over 2s here')
} catch (e: any) {
stackException = e
}
const debugTimeout = setTimeout(() => {
;(async () => {
const bc = new BroadcastChannel('who-is-holding-the-lock')
try {
bc.postMessage({})
} finally {
bc.close()
}
console.error(
`Waited for over 2s to acquire an Auth client lock`,
await navigator.locks.query(),
stackException
)
})()
}, 2000)
try {
return await navigatorLock(name, acquireTimeout, async () => {
clearTimeout(debugTimeout)
const bc = new BroadcastChannel('who-is-holding-the-lock')
bc.addEventListener('message', () => {
console.error('Lock is held here', stackException)
if (captureException) {
captureException(stackException)
}
})
try {
return await fn()
} finally {
bc.close()
}
})
} finally {
clearTimeout(debugTimeout)
}
}
export const gotrueClient = new AuthClient({
url: process.env.NEXT_PUBLIC_GOTRUE_URL,
storageKey: STORAGE_KEY,
detectSessionInUrl: shouldDetectSessionInUrl,
debug: debug ? (persistedDebug ? logIndexedDB : true) : false,
lock: navigatorLockEnabled ? navigatorLock : undefined,
lock: navigatorLockEnabled ? debuggableNavigatorLock : undefined,
...('localStorage' in globalThis
? { storage: globalThis.localStorage, userStorage: globalThis.localStorage }