UNPKG

@metacall/faas

Version:

Reimplementation of MetaCall FaaS platform written in TypeScript.

131 lines (130 loc) 4.9 kB
"use strict"; /* eslint-disable */ Object.defineProperty(exports, "__esModule", { value: true }); const package_1 = require("@metacall/protocol/package"); const fs_1 = require("fs"); const metacall_1 = require("metacall"); const os_1 = require("os"); const path_1 = require("path"); const protocol_1 = require("./protocol"); const functions = {}; const createMetacallJsonFiles = async (path, jsons) => { for (const el of jsons) { const filePath = path_1.join(path, `metacall-${el.language_id}.json`); await fs_1.promises.writeFile(filePath, JSON.stringify(el)); } }; const loadDeployment = (resource, jsonPaths) => { const deployment = { status: 'create', prefix: os_1.hostname(), suffix: resource.id, version: 'v1', packages: {}, ports: [] }; const configurations = jsonPaths.map(path => { const jsonPath = path_1.join(resource.path, path); return { path: jsonPath, json: require(jsonPath) }; }); const languages = new Set(configurations.map(({ json }) => json.language_id)); // Load resource path for each language for (const tag of languages) { metacall_1.metacall_execution_path(tag, resource.path); } for (const { path, json } of configurations) { if (!json.language_id) { throw new Error(`Field language_id not found in ${path}`); } // Load execution path for each json const executionPath = path_1.join(resource.path, json.path); metacall_1.metacall_execution_path(json.language_id, executionPath); // Load the json into metacall const exports = metacall_1.metacall_load_from_configuration_export(path); // Get the inspect information const inspect = metacall_1.metacall_inspect(); deployment.packages[json.language_id] = inspect[json.language_id]; // Store the functions Object.keys(exports).forEach(func => { functions[func] = exports[func]; }); } return deployment; }; const handleDeployment = async (resource) => { // Check if the deploy comes with extra JSONs and store them if (resource.jsons.length > 0) { const jsonPaths = await createMetacallJsonFiles(resource.path, resource.jsons); } // List all files except by the ignored ones const filesPaths = await package_1.findFilesPath(resource.path); // Get the JSONs from the list of files const jsonPaths = package_1.findMetaCallJsons(filesPaths); // Deploy the JSONs const deployment = loadDeployment(resource, jsonPaths); // Mark as ready so CLI and tests see deployment as fully up deployment.status = 'ready'; return deployment; }; process.on('message', (payload) => { switch (payload.type) { // Handle deploy load case protocol_1.WorkerMessageType.Load: { const resource = payload.data; handleDeployment(resource) .then(app => { if (process.send) { process.send({ type: protocol_1.WorkerMessageType.MetaData, data: app }); } }) .catch(err => { console.log(err); process.exit(1); }); break; } // Handle invoke function case protocol_1.WorkerMessageType.Invoke: { const fn = payload.data; void (async () => { try { const result = await functions[fn.name](...fn.args); if (process.send) { process.send({ type: protocol_1.WorkerMessageType.InvokeResult, data: { id: fn.id, result: result } }); } } catch (err) { // We must inform the master about the error or handle it gracefully. // Since there wasn't an explicit InvokeError type, we'll mimic the old // behavior but at least prevent the worker from crashing silently. console.error(`Error executing function ${fn.name}:`, err); if (process.send) { process.send({ type: protocol_1.WorkerMessageType.InvokeResult, data: { id: fn.id, result: { error: String(err) } } }); } } })(); break; } default: break; } });