chore: cache heartbeats request when they fail or users are offline
This commit is contained in:
@@ -37,6 +37,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
plugins: ['react', '@typescript-eslint', 'typescript-sort-keys', 'sort-keys-fix'],
|
plugins: ['react', '@typescript-eslint', 'typescript-sort-keys', 'sort-keys-fix'],
|
||||||
rules: {
|
rules: {
|
||||||
|
'no-await-in-loop': 'off',
|
||||||
'prettier/prettier': 'error',
|
'prettier/prettier': 'error',
|
||||||
'sort-keys-fix/sort-keys-fix': 'error',
|
'sort-keys-fix/sort-keys-fix': 'error',
|
||||||
'testing-library/no-debug': 'off',
|
'testing-library/no-debug': 'off',
|
||||||
|
|||||||
@@ -1,6 +1,27 @@
|
|||||||
import browser from 'webextension-polyfill';
|
import browser from 'webextension-polyfill';
|
||||||
import WakaTimeCore from './core/WakaTimeCore';
|
import WakaTimeCore from './core/WakaTimeCore';
|
||||||
|
|
||||||
|
// Add a listener to resolve alarms
|
||||||
|
browser.alarms.onAlarm.addListener(async (alarm) => {
|
||||||
|
// |alarm| can be undefined because onAlarm also gets called from
|
||||||
|
// window.setTimeout on old chrome versions.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
|
if (alarm && alarm.name == 'heartbeatAlarm') {
|
||||||
|
// Checks if the user is online and if there are cached heartbeats requests,
|
||||||
|
// if so then procedd to send these payload to wakatime api
|
||||||
|
if (navigator.onLine) {
|
||||||
|
const { cachedHeartbeats } = await browser.storage.sync.get({
|
||||||
|
cachedHeartbeats: [],
|
||||||
|
});
|
||||||
|
await browser.storage.sync.set({ cachedHeartbeats: [] });
|
||||||
|
await WakaTimeCore.sendCachedHeartbeatsRequest(cachedHeartbeats as Record<string, unknown>[]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a new alarm for sending cached heartbeats.
|
||||||
|
browser.alarms.create('heartbeatAlarm', { periodInMinutes: 2 });
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whenever a active tab is changed it records a heartbeat with that tab url.
|
* Whenever a active tab is changed it records a heartbeat with that tab url.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -262,9 +262,44 @@ class WakaTimeCore {
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data;
|
return data;
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
|
// Stores the payload of the request to be send later
|
||||||
|
const { cachedHeartbeats } = await browser.storage.sync.get({
|
||||||
|
cachedHeartbeats: [],
|
||||||
|
});
|
||||||
|
cachedHeartbeats.push(payload);
|
||||||
|
await browser.storage.sync.set({ cachedHeartbeats });
|
||||||
await changeExtensionState('notSignedIn');
|
await changeExtensionState('notSignedIn');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends cached heartbeats request to wakatime api
|
||||||
|
* @param requests
|
||||||
|
*/
|
||||||
|
async sendCachedHeartbeatsRequest(requests: Record<string, unknown>[]): Promise<void> {
|
||||||
|
const apiKey = await this.getApiKey();
|
||||||
|
if (!apiKey) {
|
||||||
|
return changeExtensionState('notLogging');
|
||||||
|
}
|
||||||
|
const chunkSize = 50; // Create batches of max 50 request
|
||||||
|
for (let i = 0; i < requests.length; i += chunkSize) {
|
||||||
|
const chunk = requests.slice(i, i + chunkSize);
|
||||||
|
const requestsPromises: Promise<Response>[] = [];
|
||||||
|
chunk.forEach((request) =>
|
||||||
|
requestsPromises.push(
|
||||||
|
fetch(`${config.heartbeatApiUrl}?api_key=${apiKey}`, {
|
||||||
|
body: JSON.stringify(request),
|
||||||
|
method: 'POST',
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
await Promise.all(requestsPromises);
|
||||||
|
} catch (error: unknown) {
|
||||||
|
console.log('Error sending heartbeats');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new WakaTimeCore();
|
export default new WakaTimeCore();
|
||||||
|
|||||||
Reference in New Issue
Block a user