0.1.6Updated a month ago
// deno-lint-ignore no-explicit-any

export class IdempotencyHandler {
  private expiration_time = 3000
  private interval_ms = 1000

  /**
   * Creates a new non-persistent idempotency cache.
   * 
   * @param expiration_period_seconds How long an entry should be kept in this cache.
   * @param clean_interval_seconds How frequently this cache should be checked for stale entries and cleaned up.
   */
  constructor() {
    setInterval(this.clean.bind(this), this.interval_ms);
  }

  private _entries: Record<string, number> = {}

  check(...keys: (string | number)[]) {
    const key = keys.map(k => k.toString()).join('--');

    const run = !this._entries[key];

    if(run) this._entries[key] = (Date.now() + this.expiration_time);

    return { execute: (fn: () => void | Promise<void>) => {
      if(run) fn();
    } };
  }

  private clean() {
    const expiration_timestamp = Date.now();

    for(const [key, expires_at] of Object.entries(this._entries)) {
      if(expires_at <= expiration_timestamp) delete this._entries[key];
    }
  }
}