Last active
March 5, 2023 21:23
-
-
Save u12206050/8de4bc67b3fb5536e48ce00dffc32707 to your computer and use it in GitHub Desktop.
Debounces the execution of a function being called across containers utilising a shared cache
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// eslint-disable-next-line node/no-extraneous-import | |
import Keyv from 'keyv'; | |
/** | |
* Debounces the execution of a function that takes an ID parameter, ensuring that it only runs once per second | |
* for each ID across all containers/threads. Uses a combination of shared cache and a locking mechanism to achieve this. | |
* | |
* @param id - The ID parameter for the function being debounced | |
* @param cache - The Redis cache instance used for locking and storing timestamps | |
* @param fn - The function being debounced, which takes the ID parameter and returns a Promise | |
* @param delay - The delay in milliseconds between each execution of the function | |
*/ | |
export async function safeDebounce( | |
id: string | number, | |
cache: Keyv, | |
fn: (id: string | number) => Promise<any>, | |
delay = 1000, | |
_added = Date.now() | |
) { | |
const lockKey = `lock:${id}`; | |
const lastAddedKey = `added:${id}`; | |
// Get the timestamp of the last action for this ID | |
const latestAdded = await cache.get(lastAddedKey); | |
if (latestAdded && _added < latestAdded) { | |
// A newer action has been added, so we can ignore this one | |
return; | |
} | |
await cache.set(lastAddedKey, _added, delay); | |
// Check if the lock is already set for this ID | |
const isLocked = await cache.get(lockKey); | |
if (!isLocked) { | |
// Set the lock | |
await cache.set(lockKey, _added, delay); | |
try { | |
// Execute the function | |
return await fn(id); | |
} catch (e) { | |
console.error(e); | |
} | |
} else { | |
setTimeout(() => { | |
safeDebounce(id, cache, fn, delay, _added); | |
}, delay / 2); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Using with Directus? Any ItemsService has a cache property that currently is
Keyv
so you can pass that througheg.