import * as _alepha_core2 from "alepha";
import * as _alepha_core1 from "alepha";
import * as _alepha_core0 from "alepha";
import { AsyncFn, Descriptor, KIND, Static } from "alepha";
import * as _alepha_topic0 from "alepha/topic";
import { TopicProvider } from "alepha/topic";
import { DateTime, DateTimeProvider, DurationLike, Timeout } from "alepha/datetime";
import * as dayjs_plugin_duration0 from "dayjs/plugin/duration";

//#region src/providers/LockProvider.d.ts
/**
 * Store Provider Interface
 */
declare abstract class LockProvider {
  /**
   * Set the string value of a key.
   *
   * @param key The key of the value to set.
   * @param value The value to set.
   * @param nx If set to true, the key will only be set if it does not already exist.
   * @param px Set the specified expire time, in milliseconds.
   */
  abstract set(key: string, value: string, nx?: boolean, px?: number): Promise<string>;
  /**
   * Remove the specified keys.
   *
   * @param keys The keys to delete.
   */
  abstract del(...keys: string[]): Promise<void>;
}
//# sourceMappingURL=LockProvider.d.ts.map
//#endregion
//#region src/descriptors/$lock.d.ts
/**
 * Lock descriptor
 *
 * Make sure that only one instance of the handler is running at a time.
 *
 * When connected to a remote store, the lock is shared across all processes.
 *
 * @param options
 */
declare const $lock: {
  <TFunc extends AsyncFn>(options: LockDescriptorOptions<TFunc>): LockDescriptor<TFunc>;
  [KIND]: typeof LockDescriptor;
};
interface LockDescriptorOptions<TFunc extends AsyncFn> {
  /**
   * Function executed when the lock is acquired.
   */
  handler: TFunc;
  /**
   * If true, the handler will wait for the lock to be released.
   *
   * To understand:
   *
   * ### wait = false
   * You have 3 servers running scheduled tasks, you want to ensure that only one of them runs the task at a time.
   * But you don't want the other servers to wait for the lock to be released before they run the task.
   *
   * Problem with not waiting:
   * If the lock is released before a new late trigger, handler will be executed multiple times.
   * Aka, if you have 3 servers but not clock synchronized.
   *
   * ### wait = true
   * You have 3 servers running a migration script on startup, migration script must be run only once.
   * You want to wait the end of migration for each server as they all require the migration to be completed.
   *
   *
   * @default false
   */
  wait?: boolean;
  /**
   * Create you own unique key for the lock.
   */
  name?: string | ((...args: Parameters<TFunc>) => string);
  /**
   * Lock timeout.
   *
   * @default 5 minutes
   */
  maxDuration?: DurationLike;
  /**
   * Additional lifetime of the lock after the handler has finished executing.
   *
   * This is useful to ensure that the lock is not released too early
   *
   * @default null
   */
  gracePeriod?: ((...args: Parameters<TFunc>) => DurationLike | undefined) | DurationLike;
}
declare const envSchema: _alepha_core2.TObject<{
  LOCK_PREFIX_KEY: _alepha_core2.TString;
}>;
declare module "alepha" {
  interface Env extends Partial<Static<typeof envSchema>> {}
}
declare class LockDescriptor<TFunc extends AsyncFn> extends Descriptor<LockDescriptorOptions<TFunc>> {
  protected readonly log: _alepha_core2.Logger;
  protected readonly provider: LockProvider;
  protected readonly env: {
    LOCK_PREFIX_KEY: string;
  };
  protected readonly dateTimeProvider: DateTimeProvider;
  protected readonly id: `${string}-${string}-${string}-${string}-${string}`;
  readonly maxDuration: dayjs_plugin_duration0.Duration;
  protected readonly topicLockEnd: _alepha_topic0.TopicDescriptor<{
    payload: _alepha_core2.TObject<{
      name: _alepha_core2.TString;
    }>;
  }>;
  run(...args: Parameters<TFunc>): Promise<void>;
  /**
   * Set the lock for the given key.
   */
  protected lock(key: string): Promise<LockResult>;
  protected setGracePeriod(key: string, lock: LockResult, ...args: Parameters<TFunc>): Promise<void>;
  protected wait(key: string, maxDuration: DurationLike): Promise<void>;
  protected key(...args: Parameters<TFunc>): string;
  protected parse(value: string): LockResult;
}
interface LockResult {
  id: string;
  createdAt: DateTime;
  endedAt?: DateTime;
  response?: string;
}
//#endregion
//#region src/providers/LockTopicProvider.d.ts
declare abstract class LockTopicProvider extends TopicProvider {}
//# sourceMappingURL=LockTopicProvider.d.ts.map

//#endregion
//#region src/providers/MemoryLockProvider.d.ts
/**
 * A simple in-memory store provider.
 */
declare class MemoryLockProvider implements LockProvider {
  protected readonly dateTimeProvider: DateTimeProvider;
  protected readonly log: _alepha_core1.Logger;
  /**
   * The in-memory store.
   */
  protected store: Record<string, string>;
  /**
   * Timeouts used to expire keys.
   */
  protected storeTimeout: Record<string, Timeout>;
  set(key: string, value: string, nx?: boolean, px?: number): Promise<string>;
  del(...keys: string[]): Promise<void>;
  private ttl;
}
//# sourceMappingURL=MemoryLockProvider.d.ts.map
//#endregion
//#region src/index.d.ts
/**
 * Lock a resource for a certain period of time.
 *
 * This module provides a memory implementation of the lock provider.
 * You probably want to use an implementation like RedisLockProvider for distributed systems.
 *
 * @see {@link $lock}
 * @module alepha.lock
 */
declare const AlephaLock: _alepha_core0.Service<_alepha_core0.Module>;
//# sourceMappingURL=index.d.ts.map

//#endregion
export { $lock, AlephaLock, LockDescriptor, LockDescriptorOptions, LockProvider, LockResult, LockTopicProvider, MemoryLockProvider };
//# sourceMappingURL=index.d.ts.map