'use strict';
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
    if (typeof path === "string" && /^\.\.?\//.test(path)) {
        return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
            return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
        });
    }
    return path;
};
Object.defineProperty(exports, "__esModule", { value: true });
// Install the worker process guard first so user job code cannot terminate
// the worker via process.exit() or an unhandled rejection.
const workerProcessGuard_ts_1 = require("../threads/workerProcessGuard.js");
const hdbTerms = __importStar(require("../../utility/hdbTerms.js"));
const hdbUtils = __importStar(require("../../utility/common_utils.js"));
const harper_logger_ts_1 = __importDefault(require("../../utility/logging/harper_logger.js"));
const globalSchema = __importStar(require("../../utility/globalSchema.js"));
const user = __importStar(require("../../security/user.js"));
const serverUtils = __importStar(require("../serverHelpers/serverUtilities.js"));
const moment_1 = __importDefault(require("moment"));
const jobs = __importStar(require("./jobs.js"));
const lodash_1 = require("lodash");
const node_url_1 = require("node:url");
const node_path_1 = require("node:path");
const node_worker_threads_1 = require("node:worker_threads");
const Application_ts_1 = require("./../../components/Application.js");
const packageUtils_js_1 = require("../../utility/packageUtils.js");
const JOB_NAME = process.env[hdbTerms.PROCESS_NAME_ENV_PROP];
const JOB_ID = JOB_NAME.substring(4);
/**
 * Finds the appropriate function for the request and runs it.
 * Then updates the job table accordingly.
 * @returns {Promise<void>}
 */
(async function job() {
    // The request value could potentially be quite large so it's set to undefined to clear it out after being processed.
    let jobObj = { id: JOB_ID, request: undefined };
    let exitCode = 0;
    try {
        harper_logger_ts_1.default.notify('Starting job:', JOB_ID);
        globalSchema.setSchemaDataToGlobal();
        await user.setUsersWithRolesCache();
        for (const { packageIdentifier } of (0, Application_ts_1.getEnvBuiltInComponents)()) {
            if (packageIdentifier.startsWith('@/')) {
                // for internal built-in components, we need to load the package in case it needs to register handlers
                await import(__rewriteRelativeImportExtension((0, node_url_1.pathToFileURL)((0, node_path_1.join)(packageUtils_js_1.PACKAGE_ROOT, packageIdentifier.slice(1))).toString()));
            }
        }
        // When the job record is first inserted in hdbJob table by HDB, the incoming API request is included, this is
        // how we pass the request to the job process. IPC was initially used but messages were getting lost under heavy load.
        const jobRecord = await jobs.getJobById(JOB_ID);
        if (hdbUtils.isEmptyOrZeroLength(jobRecord)) {
            throw new Error(`Unable to find a record in hdbJob for job: ${JOB_ID}`);
        }
        let { request } = jobRecord[0];
        if (hdbUtils.isEmptyOrZeroLength(request)) {
            throw new Error('Did not find job request in hdb_job table, unable to proceed');
        }
        request = (0, lodash_1.cloneDeep)(request);
        const operation = serverUtils.getOperationFunction(request);
        harper_logger_ts_1.default.trace('Running operation:', request.operation, 'for job', JOB_ID);
        // Run the job operation.
        const results = await operation.job_operation_function(request);
        harper_logger_ts_1.default.trace('Result from job:', JOB_ID, results);
        jobObj.status = hdbTerms.JOB_STATUS_ENUM.COMPLETE;
        if (typeof results === 'string')
            jobObj.message = results;
        else {
            jobObj.result = results;
            jobObj.message = 'Successfully completed job: ' + JOB_ID;
        }
        jobObj.end_datetime = (0, moment_1.default)().valueOf();
        harper_logger_ts_1.default.notify('Successfully completed job:', JOB_ID);
    }
    catch (err) {
        exitCode = 1;
        harper_logger_ts_1.default.error(err);
        jobObj.status = hdbTerms.JOB_STATUS_ENUM.ERROR;
        jobObj.message = err.message ? err.message : err;
        jobObj.end_datetime = (0, moment_1.default)().valueOf();
    }
    finally {
        await jobs.updateJob(jobObj);
        // On Bun 1.3.13, calling process.exit() in a worker thread with lmdb-js loaded
        // while sibling workers are running causes a NAPI fatal error crash. Unref
        // parentPort (which broadcastWithAcknowledgement may have ref'd during schema
        // changes) so the event loop drains naturally without calling process.exit().
        node_worker_threads_1.parentPort?.unref();
        setTimeout(() => {
            (0, workerProcessGuard_ts_1.realExit)(exitCode);
        }, 3000).unref();
    }
})();
//# sourceMappingURL=jobProcess.js.map