Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Update setTimeout to setInterval #18

Merged
merged 5 commits into from
Sep 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,24 +80,34 @@ RunCache.onExpiry((cache: EventParam) => {

// Event of a specific key expiry
RunCache.onKeyExpiry('Key', (cache: EventParam) => {
console.log(`Cache of key '${cache.key}' has been expired`);
console.log(`Specific key has been expired`);
})

await RunCache.set({
key: "Key",
ttl: 10000
})

// Event of all refetches
// Event of any key refetches
RunCache.onRefetch((cache: EventParam) => {
console.log(`Cache of key '${cache.key}' has been refetched`);
})

// Event of a specific key refetch
RunCache.onKeyRefetch('Key', (cache: EventParam) => {
console.log(`Specific key has been refetched`);
})

helloscoopa marked this conversation as resolved.
Show resolved Hide resolved
// Event of a key refetch failure
RunCache.onRefetchFailure((cache: EventParam) => {
console.log(`Cache of key '${cache.key}' has been refetched`);
})

helloscoopa marked this conversation as resolved.
Show resolved Hide resolved
// Event of a specific key refetch failure
RunCache.onKeyRefetchFailure('Key', (cache: EventParam) => {
console.log(`Specific key has been failed to refetch`);
})

helloscoopa marked this conversation as resolved.
Show resolved Hide resolved
await RunCache.set({
key: "Key",
ttl: 10000,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "run-cache",
"version": "1.4.0",
"version": "1.4.1",
"description": "RunCache is a dependency-free, light-weight in-memory caching library for JavaScript and TypeScript that allows you to cache `string` values with optional time-to-live (TTL) settings. It also supports caching values generated from asynchronous functions and provides methods to refetch them on demand.",
"main": "dist/run-cache.js",
"types": "dist/run-cache.d.ts",
Expand Down
10 changes: 9 additions & 1 deletion src/run-cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,15 @@ describe("RunCache", () => {
});
await expect(RunCache.get(key)).resolves.toStrictEqual(value);

expect(sourceFn).toHaveBeenCalledTimes(1);
jest.advanceTimersByTime(100);
await Promise.resolve();

expect(sourceFn).toHaveBeenCalledTimes(2);

jest.advanceTimersByTime(100);
await Promise.resolve();

expect(sourceFn).toHaveBeenCalledTimes(3);
});

it("should return true if the cache value set successfully", async () => {
Expand Down
47 changes: 30 additions & 17 deletions src/run-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type CacheState = {
autoRefetch?: boolean;
fetching?: boolean;
sourceFn?: SourceFn;
timeout?: ReturnType<typeof setTimeout>;
interval?: ReturnType<typeof setInterval>;
};

export type EventParam = {
Expand Down Expand Up @@ -87,18 +87,18 @@ class RunCache {

const time = Date.now();

// Clear existing timeout if the key already exists
// Clear existing interval if the key already exists
const existingCache = RunCache.cache.get(key);
if (existingCache?.timeout) {
clearTimeout(existingCache.timeout);
if (existingCache?.interval) {
clearInterval(existingCache.interval);
}

let timeout: ReturnType<typeof setTimeout> | null = null;
let interval: ReturnType<typeof setInterval> | null = null;

if (ttl !== undefined) {
if (ttl < 0) throw new Error("Value `ttl` cannot be negative");

timeout = setTimeout(() => {
interval = setInterval(() => {
RunCache.emitEvent(EVENT.EXPIRE, {
key,
value: value ?? "undefined",
Expand Down Expand Up @@ -126,11 +126,11 @@ class RunCache {
}

RunCache.cache.set(key, {
value: cacheValue ?? 'undefined',
value: cacheValue ?? "undefined",
ttl,
sourceFn,
autoRefetch,
timeout: timeout ?? undefined,
interval: interval || undefined,
createAt: time,
updateAt: time,
});
Expand Down Expand Up @@ -246,7 +246,7 @@ class RunCache {
}

/**
* Deletes a cache entry by its key. If the entry has an active timeout (for TTL), it clears the timeout.
* Deletes a cache entry by its key. If the entry has an active interval (for TTL), it clears the interval.
*
* @param {string} key - The key of the cache entry to delete. Must be a non-empty string.
*
Expand All @@ -256,25 +256,25 @@ class RunCache {
const cache = RunCache.cache.get(key);
if (!cache) return false;

if (cache.timeout) {
clearTimeout(cache.timeout);
if (cache.interval) {
clearInterval(cache.interval);
}

return RunCache.cache.delete(key);
}

/**
* Deletes all cache entries and clears any active timeouts for TTL.
* This method iterates over all cache entries, clears any associated timeouts, and then clears the entire cache.
* Deletes all cache entries and clears any active intervals for TTL.
* This method iterates over all cache entries, clears any associated intervals, and then clears the entire cache.
*
* @returns {void}
*/
static flush(): void {
const values = Array.from(RunCache.cache.values());

values.forEach(({ timeout }) => {
if (timeout) {
clearTimeout(timeout);
values.forEach(({ interval }) => {
if (interval) {
clearInterval(interval);
}
});

Expand Down Expand Up @@ -332,7 +332,7 @@ class RunCache {
* @returns {void}
*/
static onExpiry(callback: EventFn): void {
RunCache.emitter.on(`expire`, callback);
RunCache.emitter.on(EVENT.EXPIRE, callback);
}

/**
Expand Down Expand Up @@ -378,10 +378,23 @@ class RunCache {
RunCache.emitter.on(`${EVENT.REFETCH}-${key}`, callback);
}

/**
* Registers a callback to be called when a refetch failure occurs for any key.
*
* @param {EventFn} callback - The function to be executed when a refetch failure event occurs.
*/
static onRefetchFailure(callback: EventFn): void {
RunCache.emitter.on(`${EVENT.REFETCH_FAILURE}`, callback);
}

/**
* Registers a callback to be called when a refetch failure occurs for a specific key.
*
* @param {string} key - The key for which to listen for refetch failures.
* @param {EventFn} callback - The function to be executed when a refetch failure event occurs for the specified key.
*
* @throws {Error} Throws an error if the key is empty.
*/
static onKeyRefetchFailure(key: string, callback: EventFn): void {
if (!key) throw Error("Empty key");

Expand Down
Loading