"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const grpc_1 = require("grpc");
const envoy_request_params_1 = require("./envoy-request-params");
const X_ENVOY_RETRY_GRPC_ON = "x-envoy-retry-grpc-on";
/**
 * Setting this header on egress requests will cause Envoy to attempt to retry
 * failed requests (number of retries defaults to 1, and can be controlled by
 * x-envoy-max-retries header or the route config retry policy). gRPC retries
 * are currently only supported for gRPC status codes in response headers. gRPC
 * status codes in trailers will not trigger retry logic.
 */
var GrpcRetryOn;
(function (GrpcRetryOn) {
    /**
     * Envoy will attempt a retry if the gRPC status code in the response headers is
     * “cancelled” (1)
     */
    GrpcRetryOn["CANCELLED"] = "cancelled";
    /**
     * Envoy will attempt a retry if the gRPC status code in the response headers is
     * “deadline-exceeded” (4)
     */
    GrpcRetryOn["DEADLINE_EXCEEDED"] = "deadline-exceeded";
    /**
     * Envoy will attempt a retry if the gRPC status code in the response headers is
     * “resource-exhausted” (8)
     */
    GrpcRetryOn["RESOURCE_EXHAUSTED"] = "resource-exhausted";
})(GrpcRetryOn = exports.GrpcRetryOn || (exports.GrpcRetryOn = {}));
/**
 * convert http header to grpc.Metadata
 * @param httpHeader the http header
 * @internal
 */
function httpHeader2Metadata(httpHeader) {
    const metadata = new grpc_1.default.Metadata();
    for (const [key, value] of Object.entries(httpHeader)) {
        if (Array.isArray(value)) {
            value.forEach(v => metadata.add(key, v));
        }
        else {
            metadata.add(key, value);
        }
    }
    return metadata;
}
exports.httpHeader2Metadata = httpHeader2Metadata;
/**
 * the gRPC request params, mainly two parts:
 * 1. EnvoyContext, telling what the situation is
 * 2. request params, like timeout, retry, etc.
 */
class EnvoyGrpcRequestParams extends envoy_request_params_1.default {
    /**
     * Setting the retry policies, if empty param is given will not generate any headers but using
     * the default setting in Envoy's config
     * @param params the params for initialize the request params
     */
    constructor(context, params) {
        const { maxRetries, retryOn, timeout, perTryTimeout, headers } = Object.assign({ maxRetries: -1, retryOn: [], timeout: -1, perTryTimeout: -1, headers: {} }, params);
        super(context, maxRetries, timeout, perTryTimeout, headers);
        this.retryOn = retryOn;
    }
    /**
     * assemble the request headers for setting retry.
     */
    assembleRequestMeta() {
        const metadata = httpHeader2Metadata(Object.assign({}, this.context.assembleTracingHeader(), this.customHeaders));
        if (this.maxRetries >= 0) {
            metadata.add(envoy_request_params_1.X_ENVOY_MAX_RETRIES, `${this.maxRetries}`);
        }
        if (this.maxRetries > 0) {
            metadata.add(X_ENVOY_RETRY_GRPC_ON, this.retryOn.join(","));
        }
        if (this.timeout > 0) {
            metadata.add(envoy_request_params_1.X_ENVOY_UPSTREAM_RQ_TIMEOUT_MS, `${this.timeout}`);
        }
        if (this.perTryTimeout > 0) {
            metadata.add(envoy_request_params_1.X_ENVOY_UPSTREAM_RQ_PER_TRY_TIMEOUT_MS, `${this.perTryTimeout}`);
        }
        return metadata;
    }
}
exports.default = EnvoyGrpcRequestParams;
//# sourceMappingURL=envoy-grpc-request-params.js.map