"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AsyncCompletionClient = exports.ActivityResetError = exports.ActivityPausedError = exports.ActivityCancelledError = exports.ActivityCompletionError = exports.ActivityNotFoundError = void 0;
const grpc_js_1 = require("@grpc/grpc-js");
const common_1 = require("@temporalio/common");
const internal_non_workflow_1 = require("@temporalio/common/lib/internal-non-workflow");
const internal_workflow_1 = require("@temporalio/common/lib/internal-workflow");
const type_helpers_1 = require("@temporalio/common/lib/type-helpers");
const base_client_1 = require("./base-client");
const errors_1 = require("./errors");
const helpers_1 = require("./helpers");
/**
 * Thrown by {@link AsyncCompletionClient} when trying to complete or heartbeat an Activity that does not exist in the
 * system.
 */
let ActivityNotFoundError = class ActivityNotFoundError extends Error {
};
exports.ActivityNotFoundError = ActivityNotFoundError;
exports.ActivityNotFoundError = ActivityNotFoundError = __decorate([
    (0, type_helpers_1.SymbolBasedInstanceOfError)('ActivityNotFoundError')
], ActivityNotFoundError);
/**
 * Thrown by {@link AsyncCompletionClient} when trying to complete or heartbeat
 * an Activity for any reason apart from {@link ActivityNotFoundError}.
 */
let ActivityCompletionError = class ActivityCompletionError extends Error {
};
exports.ActivityCompletionError = ActivityCompletionError;
exports.ActivityCompletionError = ActivityCompletionError = __decorate([
    (0, type_helpers_1.SymbolBasedInstanceOfError)('ActivityCompletionError')
], ActivityCompletionError);
/**
 * Thrown by {@link AsyncCompletionClient.heartbeat} when the Workflow has
 * requested to cancel the reporting Activity.
 */
let ActivityCancelledError = class ActivityCancelledError extends Error {
};
exports.ActivityCancelledError = ActivityCancelledError;
exports.ActivityCancelledError = ActivityCancelledError = __decorate([
    (0, type_helpers_1.SymbolBasedInstanceOfError)('ActivityCancelledError')
], ActivityCancelledError);
/**
 * Thrown by {@link AsyncCompletionClient.heartbeat} when the reporting Activity
 * has been paused.
 */
let ActivityPausedError = class ActivityPausedError extends Error {
};
exports.ActivityPausedError = ActivityPausedError;
exports.ActivityPausedError = ActivityPausedError = __decorate([
    (0, type_helpers_1.SymbolBasedInstanceOfError)('ActivityPausedError')
], ActivityPausedError);
/**
 * Thrown by {@link AsyncCompletionClient.heartbeat} when the reporting Activity
 * has been reset.
 */
let ActivityResetError = class ActivityResetError extends Error {
};
exports.ActivityResetError = ActivityResetError;
exports.ActivityResetError = ActivityResetError = __decorate([
    (0, type_helpers_1.SymbolBasedInstanceOfError)('ActivityResetError')
], ActivityResetError);
function defaultAsyncCompletionClientOptions() {
    return (0, base_client_1.defaultBaseClientOptions)();
}
/**
 * A client for asynchronous completion and heartbeating of Activities.
 *
 * Typically this client should not be instantiated directly, instead create the high level {@link Client} and use
 * {@link Client.activity} to complete async activities.
 */
class AsyncCompletionClient extends base_client_1.BaseClient {
    options;
    constructor(options) {
        super(options);
        this.options = {
            ...defaultAsyncCompletionClientOptions(),
            ...(0, internal_workflow_1.filterNullAndUndefined)(options ?? {}),
            loadedDataConverter: this.dataConverter,
        };
    }
    /**
     * Raw gRPC access to the Temporal service.
     *
     * **NOTE**: The namespace provided in {@link options} is **not** automatically set on requests made via this service
     * object.
     */
    get workflowService() {
        return this.connection.workflowService;
    }
    /**
     * Transforms grpc errors into well defined TS errors.
     */
    handleError(err) {
        if ((0, errors_1.isGrpcServiceError)(err)) {
            (0, helpers_1.rethrowKnownErrorTypes)(err);
            if (err.code === grpc_js_1.status.NOT_FOUND) {
                throw new ActivityNotFoundError('Not found');
            }
            throw new ActivityCompletionError(err.details || err.message);
        }
        throw new ActivityCompletionError('Unexpected failure');
    }
    async complete(taskTokenOrFullActivityId, result) {
        const payloads = await (0, internal_non_workflow_1.encodeToPayloads)(this.dataConverter, result);
        try {
            if (taskTokenOrFullActivityId instanceof Uint8Array) {
                await this.workflowService.respondActivityTaskCompleted({
                    identity: this.options.identity,
                    namespace: this.options.namespace,
                    taskToken: taskTokenOrFullActivityId,
                    result: { payloads },
                });
            }
            else {
                await this.workflowService.respondActivityTaskCompletedById({
                    identity: this.options.identity,
                    namespace: this.options.namespace,
                    ...taskTokenOrFullActivityId,
                    result: { payloads },
                });
            }
        }
        catch (err) {
            this.handleError(err);
        }
    }
    async fail(taskTokenOrFullActivityId, err) {
        const failure = await (0, internal_non_workflow_1.encodeErrorToFailure)(this.dataConverter, (0, common_1.ensureTemporalFailure)(err));
        try {
            if (taskTokenOrFullActivityId instanceof Uint8Array) {
                await this.workflowService.respondActivityTaskFailed({
                    identity: this.options.identity,
                    namespace: this.options.namespace,
                    taskToken: taskTokenOrFullActivityId,
                    failure,
                });
            }
            else {
                await this.workflowService.respondActivityTaskFailedById({
                    identity: this.options.identity,
                    namespace: this.options.namespace,
                    ...taskTokenOrFullActivityId,
                    failure,
                });
            }
        }
        catch (err) {
            this.handleError(err);
        }
    }
    async reportCancellation(taskTokenOrFullActivityId, details) {
        const payloads = await (0, internal_non_workflow_1.encodeToPayloads)(this.dataConverter, details);
        try {
            if (taskTokenOrFullActivityId instanceof Uint8Array) {
                await this.workflowService.respondActivityTaskCanceled({
                    identity: this.options.identity,
                    namespace: this.options.namespace,
                    taskToken: taskTokenOrFullActivityId,
                    details: { payloads },
                });
            }
            else {
                await this.workflowService.respondActivityTaskCanceledById({
                    identity: this.options.identity,
                    namespace: this.options.namespace,
                    ...taskTokenOrFullActivityId,
                    details: { payloads },
                });
            }
        }
        catch (err) {
            this.handleError(err);
        }
    }
    async heartbeat(taskTokenOrFullActivityId, details) {
        const payloads = await (0, internal_non_workflow_1.encodeToPayloads)(this.dataConverter, details);
        let cancelRequested = false;
        let paused = false;
        let reset = false;
        try {
            if (taskTokenOrFullActivityId instanceof Uint8Array) {
                const response = await this.workflowService.recordActivityTaskHeartbeat({
                    identity: this.options.identity,
                    namespace: this.options.namespace,
                    taskToken: taskTokenOrFullActivityId,
                    details: { payloads },
                });
                cancelRequested = !!response.cancelRequested;
                paused = !!response.activityPaused;
                reset = !!response.activityReset;
            }
            else {
                const response = await this.workflowService.recordActivityTaskHeartbeatById({
                    identity: this.options.identity,
                    namespace: this.options.namespace,
                    ...taskTokenOrFullActivityId,
                    details: { payloads },
                });
                cancelRequested = !!response.cancelRequested;
                paused = !!response.activityPaused;
                reset = !!response.activityReset;
            }
        }
        catch (err) {
            this.handleError(err);
        }
        // Note that it is possible for a heartbeat response to have multiple fields
        // set as true (i.e. cancelled and pause).
        if (cancelRequested) {
            throw new ActivityCancelledError('cancelled');
        }
        else if (reset) {
            throw new ActivityResetError('reset');
        }
        else if (paused) {
            throw new ActivityPausedError('paused');
        }
    }
}
exports.AsyncCompletionClient = AsyncCompletionClient;
//# sourceMappingURL=async-completion-client.js.map