api: exponential backoff when resubscribing

Use the new `lib/retry` to attempt to reconnect when clogged. If unsucessful after 5 attempts, stop retrying and log an error.
This commit is contained in:
tomholford 2022-03-10 22:54:30 -06:00
parent 200b504c4e
commit bf0f4e97c9
3 changed files with 51 additions and 5 deletions

View File

@ -14,6 +14,7 @@ import { Box, Col } from '@tlon/indigo-react';
import { makeTheme } from './lib/theme';
import { showBlit, csi } from './lib/blit';
import { DEFAULT_SESSION } from './constants';
import { retry } from './lib/retry';
const termConfig: ITerminalOptions = {
logLevel: 'warn',
@ -191,10 +192,16 @@ export default function Buffer({ name, selected, dark }: BufferProps) {
},
quit: async () => { // quit
console.error('oops quit, reconnecting...');
const newSubscriptionId = await initSubscription();
useTermState.getState().set((state) => {
state.sessions[name].subscriptionId = newSubscriptionId;
});
try {
const newSubscriptionId = await retry(initSubscription, () => {
console.log('attempting to reconnect ...');
}, 5);
useTermState.getState().set((state) => {
state.sessions[name].subscriptionId = newSubscriptionId;
});
} catch (error) {
console.log('unable to reconnect', error);
}
}
});

View File

@ -11,7 +11,7 @@ export const DEFAULT_SESSION = '';
export const SESSION_ID_REGEX = /(^[a-z]{1}[a-z\d-]*[a-z\d]{1}$)|(^[a-z]{1}$)/;
/**
* Open a session with a given agent using `[agent]![session_name]
* Open a session with a given agent using `[agent]![session_name]`
*
* For example:
* ```

View File

@ -0,0 +1,39 @@
/**
* Wait for the given milliseconds
* @param {number} milliseconds The given time to wait
* @returns {Promise} A fulfiled promise after the given time has passed
*/
function waitFor(milliseconds) {
return new Promise(resolve => setTimeout(resolve, milliseconds));
}
/**
* Execute a promise and retry with exponential backoff
* based on the maximum retry attempts it can perform
* @param {Promise} promise promise to be executed
* @param {function} onRetry callback executed on every retry
* @param {number} maxRetries The maximum number of retries to be attempted
* @returns {Promise} The result of the given promise passed in
*/
export function retry(promise, onRetry, maxRetries) {
async function retryWithBackoff(retries) {
try {
if (retries > 0) {
const timeToWait = 2 ** retries * 100;
console.log(`waiting for ${timeToWait}ms...`);
await waitFor(timeToWait);
}
return await promise();
} catch (e) {
if (retries < maxRetries) {
onRetry();
return retryWithBackoff(retries + 1);
} else {
console.warn('Max retries reached. Bubbling the error up');
throw e;
}
}
}
return retryWithBackoff(0);
}