Skip to content

Commit

Permalink
chore: Add retry logic for failed API requests
Browse files Browse the repository at this point in the history
  • Loading branch information
KieraDOG committed Aug 1, 2024
1 parent e424f3f commit d5ad1ab
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 21 deletions.
54 changes: 33 additions & 21 deletions src/CGDGarageDoor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Logging } from 'homebridge';
import retry from './retry';

interface Status {
lamp: 'on' | 'off';
Expand Down Expand Up @@ -37,28 +38,39 @@ export class CGDGarageDoor {
}

private run = async ({ cmd, value, softValue = value }) => {
this.log.debug(`Running command: ${cmd}=${value}`);

const { deviceHostname, deviceLocalKey } = this.config;
const response = await fetch(`http://${deviceHostname}/api?key=${deviceLocalKey}&${cmd}=${value}`);

const data = await response.json();

this.log.debug(response.status.toString());
this.log.debug(JSON.stringify(data));

if (!response.ok) {
this.log.error(`Failed to run command: ${cmd}=${value}`);

return;
}

if (this.status?.[cmd]) {
this.log.debug(`Setting ${cmd} to ${softValue}`);
this.status[cmd] = softValue;
}

return data;
return retry(async () => {
const response = await fetch(`http://${deviceHostname}/api?key=${deviceLocalKey}&${cmd}=${value}`);
const data = await response.json();

this.log.debug(`Running command: ${cmd}=${value}`);

const level = response.ok ? 'debug' : 'error';
this.log[level](response.status.toString());
this.log[level](JSON.stringify(data));

if (!response.ok) {
throw new Error(`Fetch failed with status ${response.status}, ${JSON.stringify(data)}`);
}

if (this.status?.[cmd]) {
this.log.debug(`Setting ${cmd} to ${softValue}`);
this.status[cmd] = softValue;
}

return data;
}, {
retries: 3,
onRetry: (error, retries) => {
this.log.warn(`Failed to run command[Retrying ${retries}]: ${cmd}=${value}`);
this.log.warn(JSON.stringify(error));
},
onFail: (error) => {
this.log.error(`Failed to run command: ${cmd}=${value}`);
this.log.error(JSON.stringify(error));
},
});
};

private refreshStatus = async () => {
Expand All @@ -72,7 +84,7 @@ export class CGDGarageDoor {
return;
}

this.status = data;
this.status = data as Status;
};

private getDoorState = (): DoorState => {
Expand Down
30 changes: 30 additions & 0 deletions src/retry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
interface Config {
retries: number;
onRetry: (error: unknown, retries: number) => void;
onFail: (error: unknown) => void;
}

const retry = async (fn: () => Promise<unknown>, config: Config) => {
const {
retries = 3,
onRetry,
onFail,
} = config;

try {
return await fn();
} catch (error) {
if (retries === 0) {
return onFail(error);
}

onRetry(error, retries);

return retry(fn, {
...config,
retries: retries - 1,
});
}
};

export default retry;

0 comments on commit d5ad1ab

Please sign in to comment.