Skip to content

Commit

Permalink
fix(sdk): fine-tune timeouts and enhance error handling for bridge re…
Browse files Browse the repository at this point in the history
…connection
  • Loading branch information
thekiba committed Jul 31, 2024
1 parent 84ce3df commit 6538103
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 11 deletions.
31 changes: 25 additions & 6 deletions packages/sdk/src/provider/bridge/bridge-gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,14 @@ export class BridgeGateway {
return response;
}

private async errorsHandler(eventSource: EventSource, e: Event): Promise<EventSource | void> {
private async errorsHandler(
eventSource: EventSource,
e: Event,
connectionEstablished: boolean
): Promise<EventSource | void> {
if (this.isConnecting) {
eventSource.close();
logDebug(`Bridge reconnecting, ${this.defaultReconnectDelay}ms delay`);
return await this.eventSource.recreate(this.defaultReconnectDelay);
throw new TonConnectError('Bridge error, failed to connect');
}

if (this.isReady) {
Expand All @@ -180,12 +183,17 @@ export class BridgeGateway {
return;
}

if (this.isClosed) {
if (this.isClosed && connectionEstablished) {
eventSource.close();
logDebug(`Bridge reconnecting, ${this.defaultReconnectDelay}ms delay`);
return await this.eventSource.recreate(this.defaultReconnectDelay);
}

if (this.isClosed && !connectionEstablished) {
eventSource.close();
throw new TonConnectError('Bridge error, failed to connect');
}

throw new TonConnectError('Bridge error, unknown state');
}

Expand Down Expand Up @@ -248,7 +256,11 @@ export type CreateEventSourceConfig = {
/**
* Error handler for the event source.
*/
errorHandler: (eventSource: EventSource, e: Event) => Promise<EventSource | void>;
errorHandler: (
eventSource: EventSource,
e: Event,
connectionEstablished: boolean
) => Promise<EventSource | void>;
/**
* Message handler for the event source.
*/
Expand Down Expand Up @@ -291,6 +303,8 @@ async function createEventSource(config: CreateEventSourceConfig): Promise<Event
return;
}

let connectionEstablished = false;

const eventSource = new EventSource(url.toString());

eventSource.onerror = async (reason: Event): Promise<void> => {
Expand All @@ -301,7 +315,11 @@ async function createEventSource(config: CreateEventSourceConfig): Promise<Event
}

try {
const newInstance = await config.errorHandler(eventSource, reason);
const newInstance = await config.errorHandler(
eventSource,
reason,
connectionEstablished
);
if (newInstance !== eventSource) {
eventSource.close();
}
Expand All @@ -315,6 +333,7 @@ async function createEventSource(config: CreateEventSourceConfig): Promise<Event
}
};
eventSource.onopen = (): void => {
connectionEstablished = true;
if (signal.aborted) {
eventSource.close();
reject(new TonConnectError('Bridge connection aborted'));
Expand Down
3 changes: 2 additions & 1 deletion packages/sdk/src/provider/bridge/bridge-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,8 @@ export class BridgeProvider implements HTTPProvider {
}

return bridge.registerSession({
openingDeadlineMS: options?.openingDeadlineMS,
openingDeadlineMS:
options?.openingDeadlineMS ?? this.defaultOpeningDeadlineMS,
signal: _options.signal
});
},
Expand Down
8 changes: 6 additions & 2 deletions packages/sdk/src/ton-connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ export class TonConnect implements ITonConnect {
};
abortController.signal.addEventListener('abort', onAbortRestore);

return await callForSuccess(
const restoreConnectionTask = callForSuccess(
async _options => {
await provider?.restoreConnection({
openingDeadlineMS: options?.openingDeadlineMS,
Expand All @@ -360,10 +360,14 @@ export class TonConnect implements ITonConnect {
},
{
attempts: Number.MAX_SAFE_INTEGER,
delayMs: 5_000,
delayMs: 2_000,
signal: options?.signal
}
);
const restoreConnectionTimeout = new Promise<void>(
resolve => setTimeout(() => resolve(), 12_000) // connection deadline
);
return Promise.race([restoreConnectionTask, restoreConnectionTimeout]);
}

/**
Expand Down
14 changes: 12 additions & 2 deletions packages/sdk/src/utils/timeout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function timeout<T>(fn: Deferrable<T>, options?: DeferOptions): Promise<T

const abortController = createAbortController(signal);

return new Promise((resolve, reject) => {
return new Promise(async (resolve, reject) => {
if (abortController.signal.aborted) {
reject(new TonConnectError('Operation aborted'));
return;
Expand All @@ -66,6 +66,16 @@ export function timeout<T>(fn: Deferrable<T>, options?: DeferOptions): Promise<T
);

const deferOptions = { timeout, abort: abortController.signal };
fn(resolve, reject, deferOptions).finally(() => clearTimeout(timeoutId));
await fn(
(...args) => {
clearTimeout(timeoutId);
resolve(...args);
},
() => {
clearTimeout(timeoutId);
reject();
},
deferOptions
);
});
}

0 comments on commit 6538103

Please sign in to comment.