import { type OplogIndex } from "./hostapi";
import { Result } from "./result";
/**
 * Represents an atomic operation of the transaction which has a rollback action.
 *
 * Implement this interface and use it within a `transaction` block.
 * Operations can also be constructed from closures using `operation`.
 */
export interface Operation<In, Out, Err> {
    /**
     * The action to execute.
     * @param input - The input to the operation.
     * @returns The result of the operation.
     */
    execute(input: In): Result<Out, Err>;
    /**
     * Compensation to perform in case of failure.
     * Compensations should not throw errors.
     * @param input - The input to the operation.
     * @param result - The result of the operation.
     * @returns The result of the compensation.
     */
    compensate(input: In, result: Out): Result<void, Err>;
}
/**
 * Creates an Operation from the provided execute and compensate functions.
 * @param execute - The function to execute the operation.
 * @param compensate - The function to compensate the operation in case of failure.
 * @returns The created Operation.
 */
export declare function operation<In, Out, Err>(execute: (input: In) => Result<Out, Err>, compensate: (input: In, result: Out) => Result<void, Err>): Operation<In, Out, Err>;
declare class InfallibleTransaction {
    private readonly beginOplogIndex;
    private compensations;
    constructor(beginOplogIndex: OplogIndex);
    /**
     * Executes an operation within the infallible transaction.
     * @param operation - The operation to execute.
     * @param input - The input to the operation.
     * @returns The result of the operation.
     */
    execute<In, Out, Err>(operation: Operation<In, Out, Err>, input: In): Out;
    private retry;
}
declare class FallibleTransaction<Err> {
    private compensations;
    /**
     * Executes an operation within the fallible transaction.
     * @param operation - The operation to execute.
     * @param input - The input to the operation.
     * @returns The result of the operation.
     */
    execute<In, Out, OpErr extends Err>(operation: Operation<In, Out, OpErr>, input: In): Result<Out, Err>;
    /**
     * Handles the failure of the fallible transaction.
     * @param error - The error that caused the failure.
     * @returns The transaction failure result.
     */
    onFailure(error: Err): TransactionFailure<Err>;
}
export type TransactionResult<Out, Err> = Result<Out, TransactionFailure<Err>>;
export type TransactionFailure<Err> = {
    type: "FailedAndRolledBackCompletely";
    error: Err;
} | {
    type: "FailedAndRolledBackPartially";
    error: Err;
    compensationFailure: Err;
};
/**
 * Executes an infallible transaction.
 *
 * InfallibleTransaction is a sequence of operations that are executed in a way that if any of the
 * operations or the underlying Golem executor fails, the whole transaction is going to
 * be retried.
 *
 * In addition to that, **user level failures** (represented by the `Result::Err` value
 * of an operation) lead to performing the compensation actions of each already performed operation
 * in reverse order.
 *
 * Fatal errors (panic) and external executor failures currently cannot perform the
 * rollback actions.
 *
 * @param f - The function that defines the transaction.
 * @returns The result of the transaction.
 */
export declare function infallibleTransaction<Out>(f: (tx: InfallibleTransaction) => Out): Out;
/**
 * Executes a fallible transaction.
 *
 * FallibleTransaction is a sequence of operations that are executed in a way that if any of the
 * operations fails, all the already performed operation's compensation actions get executed in
 * reverse order.
 *
 * In case of fatal errors (panic) and external executor failures, it does not perform the
 * compensation actions and the whole transaction gets retried.
 *
 * @param f - The function that defines the transaction.
 * @returns The result of the transaction.
 */
export declare function fallibleTransaction<Out, Err>(f: (tx: FallibleTransaction<Err>) => Result<Out, Err>): TransactionResult<Out, Err>;
/**
 * Extracts the error types from an array of operations.
 *
 * @template T - An array of `Operation` objects.
 * @returns A union type representing the possible error types that can occur in the operations.
 *
 * @example
 * ```typescript
 * const operationOne: Operation<bigint, bigint, string> = operation(
 *   // ...
 * );
 *
 * const operationTwo: Operation<bigint, string, { code: string; message: string }> = operation(
 *   // ...
 * );
 *
 * type Errors = OperationErrors<[typeof operationOne, typeof operationTwo]>;
 * // Errors = string | { code: string; message: string }
 * ```
 *
 */
export type OperationErrors<T extends Operation<any, any, any>[]> = {
    [K in keyof T]: T[K] extends Operation<any, any, infer Err> ? Err : never;
}[number];
export {};
