import { SUBCONVERSATION_ID } from '@wireapp/api-client/lib/conversation'; import { QualifiedId } from '@wireapp/api-client/lib/user'; import { DomainMlsErrorType, MlsErrorMapper } from './MlsErrorMapper'; import { BaseCreateConversationResponse } from '../../../conversation'; /** * Coordinates recovery actions for MLS operations. * * The orchestrator takes an arbitrary async "operation" (e.g. send, add users, handle welcome), * executes it, and on failure maps the thrown error to a DomainMlsError via {@link MlsErrorMapper}. * A recovery policy is then resolved and executed exactly-once per unique key, with optional * re-run of the original operation after recovery. * * Key properties: * - Single-flight: duplicate recoveries (same action+conversation+group+subconv) are deduplicated. * - Per-operation policies: the same DomainMlsError can map to different actions depending on operation. * - Non-invasive: the orchestrator has no MLS logic; it calls provided deps to perform actions. */ /** * Concrete recovery actions the orchestrator can trigger. */ export declare enum RecoveryActionKind { /** * Issue an external-commit join for the conversation. */ JoinViaExternalCommit = "JoinViaExternalCommit", /** * Fetch missing epoch state and reconcile. */ RecoverFromEpochMismatch = "RecoverFromEpochMismatch", /** * Tear down local MLS state and re-create the group. */ ResetAndReestablish = "ResetAndReestablish", /** * Add users reported as missing to get the group back in sync. */ AddMissingUsers = "AddMissingUsers", /** * Remove local MLS artifacts for the group and retry welcome handling. */ WipeAndReprocessWelcome = "WipeAndReprocessWelcome", /** * No matching policy found; treated as no-op and the original error is re-thrown. */ Unknown = "Unknown" } /** * Retry behavior for an operation under recovery. */ export type RetryPolicy = { maxAttempts: number; delayMs?: number; /** * Whether to retry the original operation once after a successful recovery */ reRunOriginalOperation?: boolean; }; /** * A single recovery policy that pairs an action with a retry configuration. */ export type RecoveryPolicy = { action: RecoveryActionKind; retryConfig: RetryPolicy; }; type PerOperationPolicies = Partial>; /** * Global policy table from DomainMlsErrorType to RecoveryPolicy. * * A value can be either a flat policy (applies to all operations) or a per-operation * map that allows different actions depending on the invoking operation. */ export type PolicyTable = Partial>; export declare enum OperationName { send = "send", addUsers = "addUsers", removeUsers = "removeUsers", joinExternalCommit = "joinExternalCommit", handleWelcome = "handleWelcome", handleMessageAdd = "handleMessageAdd", keyMaterialUpdate = "keyMaterialUpdate" } /** * Context about the operation being orchestrated. Used for policy selection and keying. */ export type OperationContext = { operationName: OperationName; qualifiedConversationId?: QualifiedId; groupId?: string; subconvId?: SUBCONVERSATION_ID; }; /** * Public orchestrator interface. Wrap your async operation with {@link execute}. * * The callback is invoked immediately. If it throws, the orchestrator maps the error, * performs recovery according to policies, optionally waits, and may re-run the callback once. */ export interface MlsRecoveryOrchestrator { execute(params: executeParams): Promise; execute(params: executeParams): Promise; } /** * Concrete side-effecting functions the orchestrator uses to perform recovery. * Provided by the MLS layer/service. */ export type OrchestratorDeps = { joinViaExternalCommit: (conversationId: QualifiedId) => Promise; resetAndReestablish: (conversationId: QualifiedId) => Promise; recoverFromEpochMismatch: (conversationId: QualifiedId, subconvId?: SUBCONVERSATION_ID) => Promise; addMissingUsers: (conversationId: QualifiedId, groupId: string, users: QualifiedId[]) => Promise; wipeMLSConversation: (groupId: string) => Promise; }; /** * Parameters for {@link execute}. */ type executeParams = { context: OperationContext; callBack: () => Promise; retry?: boolean; }; /** * Default implementation with in-process deduplication keyed by action and context. */ export declare class MlsRecoveryOrchestratorImpl implements MlsRecoveryOrchestrator { private readonly mapper; private readonly policies; private readonly deps; private readonly inProgressRecoveries; private readonly logger; constructor(mapper: MlsErrorMapper, policies: PolicyTable, deps: OrchestratorDeps, inProgressRecoveries?: Set, logger?: import("logdown").Logger); /** * Execute the provided callback, and on failure, map and perform a configured recovery. * If {@link RetryPolicy.reRunOriginalOperation} is true, the callback is re-invoked once after recovery. */ execute(params: executeParams): Promise; execute(params: executeParams): Promise; /** Resolve the effective policy for the mapped error and operation. Supports per-operation policies. */ private getPolicyFor; /** * Execute the concrete recovery action once per unique recovery key. Throws if required context is missing. * For WipeAndReprocessWelcome, attempts to derive groupId from either the operation context or error context. */ private performRecovery; /** * Build a stable deduplication key from action and operation context. */ private getRecoveryKey; /** * Ensure the provided async task runs at most once for the given key at a time. */ private runOnceWithKey; /** Optionally wait before re-invoking the original operation. */ private maybeDelay; private sleep; } /** * Minimal default policies used by the initial integration. These can be extended over time. * * Highlights: * - WrongEpoch: reconcile and retry for typed ops; do not re-run for join. * - GroupNotEstablished: reset and re-establish; typed ops re-run once. * - GroupOutOfSync: add missing users and retry for typed ops. * - ConversationAlreadyExists (welcome): wipe local MLS state and re-run welcome once. * - OrphanWelcome (welcome): attempt join via external commit; do not re-run. */ export declare const minimalDefaultPolicies: PolicyTable; export {}; //# sourceMappingURL=MlsRecoveryOrchestrator.d.ts.map