/**
 * Contains types and functions to define (implement) and call actor instances locally (within
 * the same process).
 *
 * Actors are just plain classes with public async action methods, decorated with {@link action|@action}. They can
 * optionally implement {@link IActivatable} by adding an async {@link IActivatable.activate} method
 * and/or {@link IDeactivatable} by adding an async {@link IDeactivatable.deactivate} method.
 *
 * Although it is possible to instantiate and/or invoke such an actor instance directly by calling
 * its methods, the locking and automatic activation/deactivation that normally takes place is
 * then bypassed. Therefore, it is not recommended to directly create and invoke actor instances
 * (except, for example, for unit tests that do not require this additional behaviour).
 *
 * The prefered way of invoking actor instances is by means of an {@link InstanceWrapper}, either
 * directly by creating a new {@link InstanceWrapper} around a certain actor instance, or by creating
 * an {@link InstanceContainer} with an {@link InstanceCreator} that creates new instances
 * on the fly (and also deactivates instances when the configured container capacity is exceeded).
 *
 * Both {@link InstanceWrapper} and {@link InstanceContainer} respect the configured locking and
 * activation/deactivation mechanisms (by means of the {@link action|@action}, {@link actor|@action}
 * and {@link service|@service} decorators).
 *
 * @packageDocumentation
 */
/// <reference types="node" />
import { Mutex, SharedExclusiveLock } from '@darlean/utils';
import { EventEmitter } from 'events';
import { ITime } from '@darlean/utils';
import { ApplicationError, FrameworkError, IActionDecoration, IActionError, IInstanceContainer, IInstanceWrapper, IMultiTypeInstanceContainer, InstanceCreator } from '@darlean/base';
import { IVolatileTimer, IVolatileTimerHandle } from '@darlean/base';
import { IAcquiredActorLock, IActorLock } from './distributedactorlock';
export declare const APPLICATION_ERROR_FRAMEWORK_ERROR = "FRAMEWORK_ERROR";
export declare const APPLICATION_ERROR_UNEXPECTED_ERROR = "UNEXPECTED_ERROR";
export declare const FRAMEWORK_ERROR_APPLICATION_ERROR = "APPLICATION_ERROR";
/**
 * Container for instances of a certain type T. The container acts as a cache
 * for already created instances up to a certain capacity. Instances
 * are removed by means of a LRU policy.
 */
export declare class InstanceContainer<T extends object> implements IInstanceContainer<T> {
    protected creator: InstanceCreator<T>;
    protected capacity: number;
    protected instances: Map<string, InstanceWrapper<T>>;
    protected callCounter: number;
    protected cleaning: Map<string, boolean>;
    protected finalizing: boolean;
    protected actorLock?: IActorLock;
    protected actorType: string;
    constructor(actorType: string, creator: InstanceCreator<T>, capacity: number, actorLock?: IActorLock);
    delete(id: string[]): Promise<void>;
    obtain(id: string[]): T;
    /**
     *
     * @param id
     * @returns
     * @throws {@link FrameworkError} when something goes wrong.
     */
    wrapper(id: string[]): IInstanceWrapper<T>;
    finalize(): Promise<void>;
    protected deleteImpl(id: string): Promise<void>;
    protected cleanup(): void;
}
/**
 * Implementation of {@link IMultiTypeInstanceContainer}.
 */
export declare class MultiTypeInstanceContainer implements IMultiTypeInstanceContainer {
    protected containers: Map<string, IInstanceContainer<object>>;
    protected finalizing: boolean;
    constructor();
    register<T extends object>(type: string, container: IInstanceContainer<T>): void;
    /**
     *
     * @param type
     * @param id
     * @returns
     * @throws {@link FrameworkError} with code {@link FRAMEWORK_ERROR_UNKNOWN_ACTOR_TYPE}
     * when the actor type is unknown
     */
    obtain<T extends object>(type: string, id: string[]): T;
    finalize(): Promise<void>;
}
export type InstanceWrapperActorLock = (onBroken: () => void) => Promise<IAcquiredActorLock>;
/**
 * Wrapper around an instance of type T. The wrapper understands class and method
 * decorations, and applies the proper locking and activation/deactivation of the
 * instance.
 */
export declare class InstanceWrapper<T extends object> extends EventEmitter implements IInstanceWrapper<T> {
    protected proxy: T;
    protected instance: T;
    protected revoke: () => void;
    protected state: 'created' | 'activating' | 'active' | 'deactivating' | 'inactive';
    protected lock: SharedExclusiveLock;
    protected callCounter: number;
    protected methods: Map<string, Function>;
    protected activeContinuation?: () => void;
    protected actorLock?: InstanceWrapperActorLock;
    protected lifecycleMutex: Mutex<void>;
    protected acquiredActorLock?: IAcquiredActorLock;
    protected actorType: string;
    /**
     * Creates a new wrapper around the provided instance of type T.
     * @param instance The instance around which the wrapper should be created.
     * @throws {@link FrameworkError} with code {@link FRAMEWORK_ERROR_UNKNOWN_ACTION}
     * when methods on this object are invokes that do not exist in the underlying instance.
     */
    constructor(actorType: string, instance: T, actorLock: InstanceWrapperActorLock | undefined);
    /**
     * Performs deactivation of the underlying instance (which includes invoking the {@link IDeactivatable.deactivate})
     * method when it exists and waiting for it to complete) and then invalidates the internal proxy (that could have previously been
     * obtained via {@link getProxy}), so that all future requests to the proxy raise an exception. Once deactivated, deactivation cannot be undone.
     */
    deactivate(skipMutex?: boolean): Promise<void>;
    /**
     *
     * @returns Returns a reference to the proxy that can be used to invoke methods on the underlying
     * instance until {@link deactivate} is invoked. After that, the proxy does not invoke the underlying
     * instance anymore but only throws exceptions.
     */
    getProxy(): T;
    getInstance(): T;
    invoke(method: Function | string | undefined, args: unknown): Promise<unknown>;
    protected handleCall(method: Function | undefined, actionName: string, args: unknown, defaultConfig?: IActionDecoration, conditional?: () => boolean, shortCircuit?: boolean): Promise<unknown>;
    protected ensureActive(): Promise<void>;
    protected ensureActorLock(): Promise<void>;
    protected releaseActorLock(): Promise<void>;
    protected acquireLocalLock(locking: 'none' | 'shared' | 'exclusive', callId: string): Promise<void>;
    protected releaseLocalLock(locking: 'none' | 'shared' | 'exclusive', callId: string): void;
    protected obtainMethods(): Map<string, Function>;
}
export declare class VolatileTimer<T extends object> implements IVolatileTimer {
    protected wrapper?: IInstanceWrapper<T>;
    protected time: ITime;
    constructor(time: ITime, wrapper?: IInstanceWrapper<T>);
    setWrapper(wrapper: IInstanceWrapper<T>): void;
    once(handler: Function, delay: number, args?: unknown): IVolatileTimerHandle;
    repeat(handler: Function, interval: number, delay?: number | undefined, repeatCount?: number | undefined, args?: unknown): IVolatileTimerHandle;
}
export declare function toApplicationError(e: unknown): ApplicationError;
export declare function toFrameworkError(e: unknown): FrameworkError;
export declare function toActionError(e: unknown): IActionError;
