/**
 * @module Semaphore
 */
import { type IReadableContext } from "../../execution-context/contracts/_module.js";
import { type InvokableFn } from "../../utilities/_module.js";
/**
 * Expiration configuration for a single semaphore slot.
 * Tracks when a slot becomes available again (expires).
 * Null expiration means the slot never expires automatically.
 *
 * IMPORT_PATH: `"@daiso-tech/core/semaphore/contracts"`
 * @group Contracts
 */
export type ISemaphoreSlotExpirationData = {
    /**
     * The expiration date and time of the slot.
     * After this time, the slot is automatically released and becomes available for reuse.
     * Null indicates the slot does not expire (persists until explicitly removed).
     */
    expiration: Date | null;
};
/**
 * Single semaphore slot data persisted in the database.
 * Represents one unit/position in a limited resource pool.
 *
 * Each slot has a unique `id` and tracks expiration time.
 * When a request acquires a slot, the slot is marked with expiration.
 * When expired or explicitly removed, the slot becomes available again.
 *
 * IMPORT_PATH: `"@daiso-tech/core/semaphore/contracts"`
 * @group Contracts
 */
export type ISemaphoreSlotData = ISemaphoreSlotExpirationData & {
    /**
     * Unique identifier for this slot within the semaphore.
     * Generated when a request acquires a slot.
     * Used to release or update the specific slot later.
     */
    id: string;
};
/**
 * Semaphore configuration persisted in the database.
 * Defines the constraint for the resource pool.
 *
 * A semaphore with limit=5 allows 5 concurrent requests.
 * Additional requests must wait for slots to become available (expire or be released).
 *
 * IMPORT_PATH: `"@daiso-tech/core/semaphore/contracts"`
 * @group Contracts
 */
export type ISemaphoreData = {
    /**
     * Maximum number of concurrent units/slots available.
     * Number of concurrent requests that can hold slots simultaneously.
     */
    limit: number;
};
/**
 * Transaction context for atomic semaphore operations.
 * Provides methods to read and modify semaphore state within a database transaction.
 *
 * All transaction methods must be executed together atomically.
 * The database guarantees isolation (race-condition free) for all operations.
 *
 * IMPORT_PATH: `"@daiso-tech/core/semaphore/contracts"`
 * @group Contracts
 */
export type IDatabaseSemaphoreTransaction = {
    /**
     * Retrieves semaphore configuration by key.
     * Returns the limit (max concurrent slots) or null if semaphore doesn't exist.
     *
     * @param context - Readable execution context for the operation
     * @param key - The semaphore identifier (e.g., "api-rate-limit", "db-connection-pool")
     * @returns Semaphore config with limit, or null if not found
     */
    findSemaphore(context: IReadableContext, key: string): Promise<ISemaphoreData | null>;
    /**
     * Retrieves all active slots (acquired requests) for a semaphore.
     * Returns empty array if semaphore has no slots or doesn't exist.
     * Includes expired slots (not auto-cleaned until explicitly removed).
     *
     * @param context - Readable execution context for the operation
     * @param key - The semaphore identifier
     * @returns Array of slot data with ids and expirations
     */
    findSlots(context: IReadableContext, key: string): Promise<Array<ISemaphoreSlotData>>;
    /**
     * Creates new semaphore or updates existing semaphore limit.
     * Idempotent: calling multiple times with same limit is safe.
     *
     * @param context - Readable execution context for the operation
     * @param key - The semaphore identifier
     * @param limit - Maximum number of concurrent slots
     * @returns Void (always succeeds)
     */
    upsertSemaphore(context: IReadableContext, key: string, limit: number): Promise<void>;
    /**
     * Creates new slot or updates existing slot expiration.
     * Called when a request acquires a slot (with expiration time).
     * Idempotent: updating same slot's expiration is safe.
     *
     * @param context - Readable execution context for the operation
     * @param key - The semaphore identifier
     * @param slotId - Unique slot identifier (generated by consumer)
     * @param expiration - When slot expires and becomes available again, or null for no expiration
     * @returns Void (always succeeds)
     */
    upsertSlot(context: IReadableContext, key: string, slotId: string, expiration: Date | null): Promise<void>;
};
/**
 * Database adapter contract for managing semaphores in SQL/document databases.
 * Simplifies semaphore implementation using transactional CRUD patterns.
 *
 * Designed for persistent semaphores stored in databases like:
 * - SQL databases (PostgreSQL, MySQL) with TypeORM or MikroORM
 * - Document databases with transaction support
 * - Any backend with atomic transaction capability
 *
 * IMPORT_PATH: `"@daiso-tech/core/semaphore/contracts"`
 * @group Contracts
 */
export type IDatabaseSemaphoreAdapter = {
    /**
     * Executes a function within a database transaction.
     * Ensures all operations in the function are atomic and isolated.
     *
     * Implementations must use the strictest transaction isolation level available
     * (SERIALIZABLE for SQL, highest for document databases) to prevent race conditions.
     *
     * @param context - Readable execution context for the operation
     * @param fn - Async function receiving transaction object, returns value of any type
     * @returns The value returned by the function
     * @throws Error if transaction fails or is rolled back
     *
     * @template TValue - Return type of the transaction function
     */
    transaction<TValue>(context: IReadableContext, fn: InvokableFn<[
        transaction: IDatabaseSemaphoreTransaction
    ], Promise<TValue>>): Promise<TValue>;
    /**
     * Removes a specific slot, making that resource unit available again.
     * Returns the slot's expiration info.
     * Returns null if slot doesn't exist (idempotent - safe to call multiple times).
     *
     * @param context - Readable execution context for the operation
     * @param key - The semaphore identifier
     * @param slotId - The slot to remove
     * @returns Expiration info of the removed slot, or null if not found
     */
    removeSlot(context: IReadableContext, key: string, slotId: string): Promise<ISemaphoreSlotExpirationData | null>;
    /**
     * Removes all slots from a semaphore.
     * Used for cleanup or reset operations.
     * Returns expiration info for all removed slots.
     *
     * @param context - Readable execution context for the operation
     * @param key - The semaphore identifier
     * @returns Array of expiration info for all removed slots
     */
    removeAllSlots(context: IReadableContext, key: string): Promise<Array<ISemaphoreSlotExpirationData>>;
    /**
     * Updates a slot's expiration time if it's currently valid (not expired).
     * Useful for extending a held slot's lifetime (e.g., heartbeat/keep-alive).
     *
     * Conditions for success:
     * - Slot must exist
     * - Slot must not be expired (expiration time >= current time or null)
     * - New expiration must be in the future
     *
     * @param context - Readable execution context for the operation
     * @param key - The semaphore identifier
     * @param slotId - The slot to update
     * @param expiration - New expiration time (or null for persistent)
     * @returns Number of rows affected (1 if updated, 0 if slot not found or expired)
     */
    updateExpiration(context: IReadableContext, key: string, slotId: string, expiration: Date): Promise<number>;
};
