inngest
Version:
Official SDK for Inngest.com. Inngest is the reliability layer for modern applications. Inngest combines durable execution, events, and queues into a zero-infra platform with built-in observability.
178 lines (176 loc) • 6.03 kB
JavaScript
const require_als = require('./execution/als.cjs');
const require_middleware = require('./middleware/middleware.cjs');
const require_Inngest = require('./Inngest.cjs');
//#region src/components/InngestMetadata.ts
/**
* Configures and sends metadata updates.
*
* It sends metadata updates via step opcodes if the metadata is
* configured to be attached to the current run/step/step attempt
* and `update` is called inside of `step.run`.
*
* Otherwise it sends updates via the Inngest API.
*/
var UnscopedMetadataBuilder = class UnscopedMetadataBuilder {
constructor(client, config = {}) {
this.client = client;
this.config = config;
}
run(id) {
return new UnscopedMetadataBuilder(this.client, {
...this.config,
runId: id ?? null
});
}
step(id, index) {
return new UnscopedMetadataBuilder(this.client, {
...this.config,
stepId: id ?? null,
stepIndex: index ?? 0
});
}
attempt(attempt) {
return new UnscopedMetadataBuilder(this.client, {
...this.config,
attempt: attempt ?? null
});
}
span(id) {
return new UnscopedMetadataBuilder(this.client, {
...this.config,
spanId: id
});
}
async update(values, kind = "default") {
await performOp(this.client, this.config, values, `userland.${kind}`, "merge");
}
toJSON() {
return this.config;
}
};
/**
* Creates a `MetadataTarget` based on the current execution context and the `BuilderConfig` created using
* `MetadataBuilder`.
*/
function buildTarget(config, ctx) {
const ctxExecution = ctx?.execution;
const ctxRunId = ctxExecution?.ctx?.runId;
const ctxStepId = ctxExecution?.executingStep?.id;
const ctxAttempt = ctxExecution?.ctx?.attempt;
const targetRunId = config.runId ?? ctxRunId;
if (!targetRunId) throw new Error("No run context available");
const isSameRunAsCtx = ctxRunId !== void 0 && targetRunId === ctxRunId;
const stepCtxReason = !ctxExecution ? "no function execution context is available" : !ctxExecution.executingStep ? "you are not inside a step.run() callback" : "you are targeting a different run";
if (config.attempt === null && (!isSameRunAsCtx || !ctxExecution?.executingStep)) throw new Error(`attempt() was called without a value, but ${stepCtxReason}`);
if (config.stepId === null && (!isSameRunAsCtx || !ctxExecution?.executingStep)) throw new Error(`step() was called without a value, but ${stepCtxReason}`);
if (config.spanId !== void 0) return {
run_id: targetRunId,
step_id: config.stepId ?? ctxStepId,
step_index: config.stepIndex,
step_attempt: config.attempt ?? ctxAttempt,
span_id: config.spanId
};
else if (config.attempt !== void 0) return {
run_id: targetRunId,
step_id: config.stepId ?? ctxStepId,
step_index: config.stepIndex,
step_attempt: config.attempt ?? ctxAttempt
};
else if (config.stepId !== void 0) return {
run_id: targetRunId,
step_id: config.stepId ?? ctxStepId,
step_index: config.stepIndex
};
else if (config.runId !== void 0) return { run_id: targetRunId };
else if (ctxStepId && ctxAttempt !== void 0) return {
run_id: targetRunId,
step_id: ctxStepId,
step_attempt: ctxAttempt
};
else return { run_id: targetRunId };
}
/**
* Creates a metadata array payload for API calls.
*/
function createMetadataPayload(kind, op, metadata) {
return [{
kind,
op,
values: metadata
}];
}
/**
* Sends metadata update via REST API to a specific target.
*/
async function sendMetadataViaAPI(client, target, kind, op, metadata, headers) {
const metadataArray = createMetadataPayload(kind, op, metadata);
await client["updateMetadata"]({
target,
metadata: metadataArray,
headers
});
}
function getBatchScope(config) {
if (config.spanId !== void 0) return "extended_trace";
if (config.attempt !== void 0) return "step_attempt";
if (config.stepId !== void 0) return "step";
if (config.runId !== void 0) return "run";
return "step_attempt";
}
async function performOp(client, config, values, kind, op) {
const ctx = await require_als.getAsyncCtx();
const target = buildTarget(config, ctx);
const isInsideRun = !!ctx?.execution;
const isInsideStep = !!ctx?.execution?.executingStep;
if (isInsideRun && !isInsideStep) client[require_Inngest.internalLoggerSymbol].warn("metadata.update() called outside of a step; this metadata may be lost on retries. Wrap the call in step.run() for durable metadata.");
const runId = config.runId ?? ctx?.execution?.ctx?.runId;
const stepId = config.stepId ?? ctx?.execution?.executingStep?.id;
const attempt = config.attempt ?? ctx?.execution?.ctx?.attempt;
if (runId === ctx?.execution?.ctx?.runId && stepId === ctx?.execution?.executingStep?.id && attempt === ctx?.execution?.ctx?.attempt && !config.spanId) {
const executingStep = ctx?.execution?.executingStep;
const execInstance = ctx?.execution?.instance;
const scope = getBatchScope(config);
if (executingStep?.id && execInstance && execInstance.addMetadata(executingStep.id, kind, scope, op, values)) return;
}
await sendMetadataViaAPI(client, target, kind, op, values, (ctx?.execution?.instance)?.options?.headers ?? void 0);
}
const metadataSymbol = Symbol.for("inngest.step.metadata");
/**
* Middleware that enables the experimental step.metadata() feature.
*
* @example
* ```ts
* import { metadataMiddleware } from "inngest/experimental";
*
* const inngest = new Inngest({
* id: "my-app",
* middleware: [metadataMiddleware()],
* });
* ```
*/
const metadataMiddleware = () => {
class MetadataMiddleware extends require_middleware.Middleware.BaseMiddleware {
id = "inngest:metadata";
static onRegister({ client }) {
client["experimentalMetadataEnabled"] = true;
}
transformFunctionInput(arg) {
return {
...arg,
ctx: {
...arg.ctx,
step: {
...arg.ctx.step,
metadata: arg.ctx.step[metadataSymbol]
}
}
};
}
}
return MetadataMiddleware;
};
//#endregion
exports.UnscopedMetadataBuilder = UnscopedMetadataBuilder;
exports.metadataMiddleware = metadataMiddleware;
exports.metadataSymbol = metadataSymbol;
//# sourceMappingURL=InngestMetadata.cjs.map