From d6b75fb687c7c8943e837811cc5743a83cb543b2 Mon Sep 17 00:00:00 2001 From: Jay Meistrich Date: Sat, 24 Aug 2024 17:20:56 -0700 Subject: [PATCH] Refactor retry error handling --- src/sync-plugins/keel.ts | 9 ++++++--- src/sync/retry.ts | 2 +- src/sync/syncObservable.ts | 21 ++++++++++++++------- src/sync/syncTypes.ts | 12 ++++++++++-- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/sync-plugins/keel.ts b/src/sync-plugins/keel.ts index facbc222..e3e07b7b 100644 --- a/src/sync-plugins/keel.ts +++ b/src/sync-plugins/keel.ts @@ -82,7 +82,10 @@ export interface SyncedKeelConfiguration | 'generateId' > { client: { - auth: { refresh: () => Promise; isAuthenticated: () => Promise }; + auth: { + refresh: () => Promise>; + isAuthenticated: () => Promise>; + }; api: { queries: Record Promise> }; }; realtimePlugin?: KeelRealtimePlugin; @@ -454,11 +457,11 @@ export function syncedKeel< params.cancelRetry = true; } - throw new Error(error.message); + throw new Error(error.message, { cause: { input } }); } else { await handleApiError(error); - throw new Error(error.message); + throw new Error(error.message, { cause: { input } }); } }; diff --git a/src/sync/retry.ts b/src/sync/retry.ts index 77afe311..cb3faa86 100644 --- a/src/sync/retry.ts +++ b/src/sync/retry.ts @@ -57,7 +57,7 @@ export function runWithRetry( if (timeout === false) { state.cancelRetry = true; - reject(); + reject(error); } else { mapRetryTimeouts.set(state.node, timeout); timeoutRetry = timeout; diff --git a/src/sync/syncObservable.ts b/src/sync/syncObservable.ts index 29cba631..2f89eda0 100644 --- a/src/sync/syncObservable.ts +++ b/src/sync/syncObservable.ts @@ -42,9 +42,11 @@ import type { SyncTransform, SyncTransformMethod, Synced, + SyncedErrorParams, SyncedGetParams, SyncedOptions, SyncedSetParams, + SyncedSubscribeParams, } from './syncTypes'; import { runWithRetry } from './retry'; @@ -629,7 +631,11 @@ async function doChangeRemote(changeInfo: PreppedChangeRemote | undefined) { const onError = (error: Error) => { state$.error.set(error); - syncOptions.onSetError?.(error, setParams as SyncedSetParams); + syncOptions.onSetError?.(error, { + setParams: setParams as SyncedSetParams, + source: 'set', + value$: obs$, + }); }; const setParams: SyncedSetParams = { @@ -906,9 +912,9 @@ export function syncObservable( allSyncStates.set(syncState$, node); syncStateValue.getPendingChanges = () => localState.pendingChanges; - const onGetError = (error: Error, getParams: SyncedGetParams | undefined, source: 'get' | 'subscribe') => { + const onGetError = (error: Error, params: Omit) => { syncState$.error.set(error); - syncOptions.onGetError?.(error, getParams, source); + syncOptions.onGetError?.(error, { ...params, value$: obs$ }); }; loadLocal(obs$, syncOptions, syncState$, localState); @@ -1076,7 +1082,7 @@ export function syncObservable( const subscribe = syncOptions.subscribe; isSubscribed = true; const doSubscribe = () => { - unsubscribe = subscribe({ + const subscribeParams: SyncedSubscribeParams = { node, value$: obs$, lastSync, @@ -1089,8 +1095,9 @@ export function syncObservable( }); }, refresh: () => when(syncState$.isLoaded, sync), - onError: (error) => onGetError(error, undefined, 'subscribe'), - }); + onError: (error: Error) => onGetError(error, { source: 'subscribe', subscribeParams }), + }; + unsubscribe = subscribe(subscribeParams); }; if (waitFor) { @@ -1101,7 +1108,7 @@ export function syncObservable( } const existingValue = getNodeValue(node); - const onError = (error: Error) => onGetError(error, getParams as SyncedGetParams, 'get'); + const onError = (error: Error) => onGetError(error, { getParams, source: 'get' }); const getParams: SyncedGetParams = { node, diff --git a/src/sync/syncTypes.ts b/src/sync/syncTypes.ts index 36e4732c..5ce0d495 100644 --- a/src/sync/syncTypes.ts +++ b/src/sync/syncTypes.ts @@ -66,6 +66,14 @@ export interface SyncedSubscribeParams extends SyncedGetSetSubscribeBas onError: (error: Error) => void; } +export interface SyncedErrorParams { + getParams?: SyncedGetParams; + setParams?: SyncedSetParams; + subscribeParams?: SyncedSubscribeParams; + source: 'get' | 'set' | 'subscribe'; + value$: ObservableParam; +} + export interface SyncedOptions extends Omit, 'get' | 'set'> { get?: (params: SyncedGetParams) => Promise | TRemote; set?: (params: SyncedSetParams) => void | Promise; @@ -76,8 +84,8 @@ export interface SyncedOptions extends Omit; - onGetError?: (error: Error, getParams: SyncedGetParams | undefined, source: 'get' | 'subscribe') => void; - onSetError?: (error: Error, setParams: SyncedSetParams) => void; + onGetError?: (error: Error, params: SyncedErrorParams) => void; + onSetError?: (error: Error, params: SyncedErrorParams) => void; onBeforeGet?: (params: { value: TRemote; lastSync: number | undefined;