"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createWorker = exports.replaceLocalhostWithDockerHost = void 0;
const queue_descriptor_1 = require("../shared/queue-descriptor");
const usage_meter_1 = require("../shared/usage-meter");
const node_fetch_1 = __importDefault(require("node-fetch"));
const token_repo_1 = require("../shared/token-repo");
const secure_webhooks_1 = require("secure-webhooks");
const telemetrist_1 = require("../shared/telemetrist");
const owl_1 = require("../shared/owl");
const ssrf_filter_1 = require("./ssrf-filter");
const posthog_node_1 = require("posthog-node");
function replaceLocalhostWithDockerHost(_url) {
    const url = new URL(_url);
    if (url.hostname === "localhost") {
        url.hostname = "host.docker.internal";
    }
    return url.toString();
}
exports.replaceLocalhostWithDockerHost = replaceLocalhostWithDockerHost;
async function createWorker({ redisFactory, enableUsageMetering, runningInDocker, concurrency = 100, disableTelemetry, logger, incidentReceiver, webhookSigningPrivateKey, enableSSRFPrevention, postHogApiKey, }) {
    const redisClient = redisFactory();
    const telemetrist = disableTelemetry
        ? undefined
        : new telemetrist_1.Telemetrist(runningInDocker !== null && runningInDocker !== void 0 ? runningInDocker : false);
    const tokenRepo = webhookSigningPrivateKey
        ? undefined
        : new token_repo_1.TokenRepo(redisClient);
    let usageMeter = undefined;
    if (enableUsageMetering) {
        usageMeter = new usage_meter_1.UsageMeter(redisClient);
    }
    let postHog = undefined;
    if (postHogApiKey) {
        postHog = new posthog_node_1.PostHog(postHogApiKey, {
            host: "https://app.posthog.com",
        });
    }
    const owl = await (0, owl_1.createOwl)(redisFactory, logger, incidentReceiver, telemetrist);
    const worker = await owl.createWorker(async (job, ack, span) => {
        let { tokenId, endpoint } = (0, queue_descriptor_1.decodeQueueDescriptor)(job.queue);
        const body = job.payload;
        const executionDone = logger === null || logger === void 0 ? void 0 : logger.startingExecution({
            tokenId,
            endpoint,
            body,
            id: job.id,
        });
        const headers = {
            "Content-Type": "text/plain",
            "x-quirrel-meta": JSON.stringify({
                id: job.id,
                count: job.count,
                exclusive: job.exclusive,
                retry: job.retry,
                nextRepetition: ack.nextExecutionDate,
            }),
        };
        if (tokenId) {
            const payload = body !== null && body !== void 0 ? body : "";
            if (webhookSigningPrivateKey) {
                headers["x-quirrel-signature"] = secure_webhooks_1.asymmetric.sign(payload, webhookSigningPrivateKey);
            }
            else {
                const token = await (tokenRepo === null || tokenRepo === void 0 ? void 0 : tokenRepo.getById(tokenId));
                if (token) {
                    headers["x-quirrel-signature"] = secure_webhooks_1.symmetric.sign(payload, token);
                }
            }
        }
        if (runningInDocker) {
            endpoint = replaceLocalhostWithDockerHost(endpoint);
        }
        const [response] = await Promise.all([
            (0, node_fetch_1.default)(endpoint, {
                method: "POST",
                body,
                headers,
                agent: enableSSRFPrevention ? ssrf_filter_1.ssrfFilter : undefined,
            }),
            usageMeter === null || usageMeter === void 0 ? void 0 : usageMeter.record(tokenId),
        ]);
        postHog === null || postHog === void 0 ? void 0 : postHog.capture({
            distinctId: tokenId,
            event: "job executed",
            properties: {
                endpoint,
                status: response.status,
            },
        });
        if (response.status >= 200 && response.status < 300) {
            executionDone === null || executionDone === void 0 ? void 0 : executionDone();
            telemetrist === null || telemetrist === void 0 ? void 0 : telemetrist.dispatch("dispatch_job");
            await worker.acknowledger.acknowledge(ack, undefined, span);
        }
        else {
            const responseBody = await response.text();
            const error = {
                tokenId,
                endpoint,
                responseBody,
                responseStatus: response.status,
                toString() {
                    return responseBody;
                },
            };
            await worker.acknowledger.reportFailure(ack, job, error, {
                dontReschedule: response.status === 404,
            });
        }
    });
    async function close() {
        postHog === null || postHog === void 0 ? void 0 : postHog.shutdown();
        await worker.close();
        await redisClient.quit();
    }
    return {
        close,
    };
}
exports.createWorker = createWorker;
//# sourceMappingURL=index.js.map