From 6fdeb362f53e9123086c391b25e85a7ca38e9468 Mon Sep 17 00:00:00 2001 From: Ry Anderson <60347977+Omnicpie@users.noreply.github.com> Date: Tue, 11 Mar 2025 15:36:54 +0000 Subject: [PATCH 1/3] Fix uploadData always calling fetchCredentials when token has not expired --- .../src/client/sync/stream/AbstractRemote.ts | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/packages/common/src/client/sync/stream/AbstractRemote.ts b/packages/common/src/client/sync/stream/AbstractRemote.ts index d0b6ab61..93adad8f 100644 --- a/packages/common/src/client/sync/stream/AbstractRemote.ts +++ b/packages/common/src/client/sync/stream/AbstractRemote.ts @@ -123,9 +123,20 @@ export abstract class AbstractRemote { async getCredentials(): Promise { const { expiresAt } = this.credentials ?? {}; - if (expiresAt && expiresAt > new Date(new Date().valueOf() + REFRESH_CREDENTIALS_SAFETY_PERIOD_MS)) { + const currentTime = new Date(new Date().valueOf() + REFRESH_CREDENTIALS_SAFETY_PERIOD_MS) + if (expiresAt && expiresAt > currentTime) { return this.credentials!; } + + // Check if existing stored token is still valid + if(this.credentials?.token) { + const {exp} = this.parseToken(this.credentials?.token) ?? {}; + + if(exp && new Date(Number(exp) * 1000) > currentTime) { + return this.credentials!; + } + } + this.credentials = await this.connector.fetchCredentials(); if (this.credentials?.endpoint.match(POWERSYNC_TRAILING_SLASH_MATCH)) { throw new Error( @@ -139,6 +150,15 @@ export abstract class AbstractRemote { return `powersync-js/${POWERSYNC_JS_VERSION}`; } + private parseToken(token: string){ + try{ + return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()); + } + catch(_){ + return null; + } + } + protected async buildRequest(path: string) { const credentials = await this.getCredentials(); if (credentials != null && (credentials.endpoint == null || credentials.endpoint == '')) { From ebd24bdf0bb205920c7974040c3dc8fc292703f2 Mon Sep 17 00:00:00 2001 From: Ry Anderson <60347977+Omnicpie@users.noreply.github.com> Date: Wed, 12 Mar 2025 09:57:19 +0000 Subject: [PATCH 2/3] Lint token check changes --- .../src/client/sync/stream/AbstractRemote.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/common/src/client/sync/stream/AbstractRemote.ts b/packages/common/src/client/sync/stream/AbstractRemote.ts index 93adad8f..a08bd35e 100644 --- a/packages/common/src/client/sync/stream/AbstractRemote.ts +++ b/packages/common/src/client/sync/stream/AbstractRemote.ts @@ -123,20 +123,20 @@ export abstract class AbstractRemote { async getCredentials(): Promise { const { expiresAt } = this.credentials ?? {}; - const currentTime = new Date(new Date().valueOf() + REFRESH_CREDENTIALS_SAFETY_PERIOD_MS) + const currentTime = new Date(new Date().valueOf() + REFRESH_CREDENTIALS_SAFETY_PERIOD_MS); if (expiresAt && expiresAt > currentTime) { return this.credentials!; } // Check if existing stored token is still valid - if(this.credentials?.token) { - const {exp} = this.parseToken(this.credentials?.token) ?? {}; - - if(exp && new Date(Number(exp) * 1000) > currentTime) { + if (this.credentials?.token) { + const { exp } = this.parseToken(this.credentials?.token) ?? {}; + + if (exp && new Date(Number(exp) * 1000) > currentTime) { return this.credentials!; } } - + this.credentials = await this.connector.fetchCredentials(); if (this.credentials?.endpoint.match(POWERSYNC_TRAILING_SLASH_MATCH)) { throw new Error( @@ -150,11 +150,10 @@ export abstract class AbstractRemote { return `powersync-js/${POWERSYNC_JS_VERSION}`; } - private parseToken(token: string){ - try{ + private parseToken(token: string) { + try { return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()); - } - catch(_){ + } catch (_) { return null; } } From 9a5b18acfe15888081edd0e7f46d2e09f84e4983 Mon Sep 17 00:00:00 2001 From: Ry Anderson Date: Tue, 25 Mar 2025 23:13:43 +0000 Subject: [PATCH 3/3] Assume stored credentials are always valid when present --- .../src/client/sync/stream/AbstractRemote.ts | 24 ++----------------- .../AbstractStreamingSyncImplementation.ts | 1 + 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/packages/common/src/client/sync/stream/AbstractRemote.ts b/packages/common/src/client/sync/stream/AbstractRemote.ts index a08bd35e..094c94c0 100644 --- a/packages/common/src/client/sync/stream/AbstractRemote.ts +++ b/packages/common/src/client/sync/stream/AbstractRemote.ts @@ -20,8 +20,6 @@ export type RemoteConnector = { const POWERSYNC_TRAILING_SLASH_MATCH = /\/+$/; const POWERSYNC_JS_VERSION = PACKAGE.version; -// Refresh at least 30 sec before it expires -const REFRESH_CREDENTIALS_SAFETY_PERIOD_MS = 30_000; const SYNC_QUEUE_REQUEST_LOW_WATER = 5; // Keep alive message is sent every period @@ -122,21 +120,11 @@ export abstract class AbstractRemote { } async getCredentials(): Promise { - const { expiresAt } = this.credentials ?? {}; - const currentTime = new Date(new Date().valueOf() + REFRESH_CREDENTIALS_SAFETY_PERIOD_MS); - if (expiresAt && expiresAt > currentTime) { + // If we have credentials stored, return them. + if (this.credentials) { return this.credentials!; } - // Check if existing stored token is still valid - if (this.credentials?.token) { - const { exp } = this.parseToken(this.credentials?.token) ?? {}; - - if (exp && new Date(Number(exp) * 1000) > currentTime) { - return this.credentials!; - } - } - this.credentials = await this.connector.fetchCredentials(); if (this.credentials?.endpoint.match(POWERSYNC_TRAILING_SLASH_MATCH)) { throw new Error( @@ -150,14 +138,6 @@ export abstract class AbstractRemote { return `powersync-js/${POWERSYNC_JS_VERSION}`; } - private parseToken(token: string) { - try { - return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()); - } catch (_) { - return null; - } - } - protected async buildRequest(path: string) { const credentials = await this.getCredentials(); if (credentials != null && (credentials.endpoint == null || credentials.endpoint == '')) { diff --git a/packages/common/src/client/sync/stream/AbstractStreamingSyncImplementation.ts b/packages/common/src/client/sync/stream/AbstractStreamingSyncImplementation.ts index 6522497f..bc4c7116 100644 --- a/packages/common/src/client/sync/stream/AbstractStreamingSyncImplementation.ts +++ b/packages/common/src/client/sync/stream/AbstractStreamingSyncImplementation.ts @@ -296,6 +296,7 @@ The next upload iteration will be delayed.`); break; } } catch (ex) { + // TODO: Handle 401s to invalidate cached credentials checkedCrudItem = undefined; this.updateSyncStatus({ dataFlow: {