UNPKG

@flowcore/generator-library-template

Version:

A Yeoman generator for adding flowcore library components to a typescript service or application

173 lines (151 loc) 5.55 kB
import type { TransformerSuccessHandler, WebhookPredicate } from "@flowcore/sdk-transformer-core" const DEFAULT_TTL_MS = 60000 // 1 minute let inMemoryCache: TTLMap /** * Options for the in-memory predicate. * @property ttlMs - The time-to-live for cache entries in milliseconds. If not specified, the default TTL is used, which is 1 minute. */ export type PredicateInMemoryOptions = { ttlMs?: number } /** * Creates a webhook predicate checker that checks if an event ID exists in the in-memory cache. * * This function initializes the in-memory cache if it's not already initialized. It then returns a webhook predicate function that checks the existence of the event ID in the cache. * * @returns A webhook predicate function that checks the existence of the event ID in the cache. */ export function createPredicateInMemoryChecker(): WebhookPredicate { if (!inMemoryCache) { inMemoryCache = new TTLMap() } return async (eventId: string) => inMemoryCache.has(eventId) } /** * Creates a webhook predicate notifier that sets an event ID in the in-memory cache. * * This function initializes the in-memory cache if it's not already initialized. It then returns a webhook predicate function that sets the event ID in the cache with an optional TTL. * * @param options - The options for the in-memory predicate. * @returns A webhook predicate function that sets the event ID in the cache. */ export function createPredicateInMemoryNotifier(options?: PredicateInMemoryOptions): TransformerSuccessHandler { if (!inMemoryCache) { inMemoryCache = new TTLMap() } return async (payload: { eventId: string }) => { inMemoryCache.set(payload.eventId, "1", options?.ttlMs ?? DEFAULT_TTL_MS) } } /** * Factory function for creating an in-memory predicate checker and notifier. * * This function returns an object with two methods: check and notify. The check method is a webhook predicate function that checks the existence of an event ID in the cache. The notify method is a webhook predicate function that sets an event ID in the cache. * * @param options - The options for the in-memory predicate. * @returns An object with check and notify methods. */ export function predicateinMemoryFactory(options?: PredicateInMemoryOptions) { return { check: createPredicateInMemoryChecker(), notify: createPredicateInMemoryNotifier(options), } } /** * A map that stores key-value pairs with a time-to-live (TTL) for each entry. * * This class provides a way to store data with a limited lifetime. Each entry in the map * can be set to expire after a specified amount of time. The map automatically removes * expired entries. * * Inspired by: https://gist.github.com/maman/557aa2b3b55bc971cf415c0c8369c874 */ export class TTLMap { private timeoutData: Record<string, Timer> private data: Map<string, string> constructor() { this.timeoutData = {} this.data = new Map() } private clearInstancedTimeout(key: string) { clearTimeout(this.timeoutData[key]) delete this.timeoutData[key] } /** * Retrieves the value associated with a given key. * * This method returns the value stored in the map for the specified key. If the key * does not exist or has expired, it returns undefined. * * @param key - The key for which to retrieve the value. * @returns The value associated with the key, or undefined if the key does not exist or has expired. */ get(key: string) { return this.data.get(key) } /** * Checks if a key exists in the map. * * This method returns true if the specified key exists in the map and has not expired, * otherwise it returns false. * * @param key - The key to check. * @returns True if the key exists and has not expired, otherwise false. */ has(key: string) { return this.data.has(key) } /** * Sets a key-value pair in the map with an optional TTL. * * This method sets a new key-value pair in the map. If a TTL is specified, the entry * will expire after the specified amount of time. If the key already exists, its value * is updated and its TTL is reset. * * @param key - The key for the new entry. * @param val - The value for the new entry. * @param ttl - The time-to-live for the new entry in milliseconds. If not specified, the entry does not expire. * @returns This instance of TTLMap. */ set(key: string, val: string, ttl?: number) { this.clearInstancedTimeout(key) this.data.set(key, val) const timeout = setTimeout(() => { this.clearInstancedTimeout(key) this.data.delete(key) this.delete(key) }, ttl) this.timeoutData[key] = timeout return this } /** * Deletes a key-value pair from the map. * * This method removes the specified key-value pair from the map. If the key exists * and has not expired, it returns true; otherwise, it returns false. * * @param key - The key to delete. * @returns True if the key existed and was deleted, otherwise false. */ delete(key: string) { this.clearInstancedTimeout(key) if (this.data.has(key)) { this.data.delete(key) return true } this.data.delete(key) return false } /** * Clears all key-value pairs from the map. * * This method removes all entries from the map and stops all associated timers. */ clear() { this.data.clear() for (const timeout of Object.values(this.timeoutData)) { clearTimeout(timeout) } this.timeoutData = {} } }