JavaScript 的 AWS 持久执行 SDK
TypeScript SDK用于构建状态,长期运行的AWS Lambda功能,具有自动状态持久性,重试逻辑,和工作流程管弦.
特征
- 持久执行: 自动维持状态,并从检查站恢复
- 自动检索: 可配置的重试策略,带有指数后退和焦急
- 工作流程管弦: 将复杂的工作流程与步骤、儿童背景和平行执行结合起来
- 外部一体化: 等待外部系统的召回
- 批量操作: 具有货币控制和完成政策的流程数组
- 类型安全: 包含全面类型定义的完整类型脚本支持
安装
npm install @aws/durable-execution-sdk-js
快速启动
import {
withDurableExecution,
DurableContext,
} from "@aws/durable-execution-sdk-js";
const handler = async (event: any, context: DurableContext) => {
// Execute a durable step with automatic retry
const userData = await context.step("fetch-user", async () =>
fetchUserFromDB(event.userId),
);
// Wait for 5 seconds
await context.wait({ seconds: 5 });
// Process data in another step
const result = await context.step("process-user", async () =>
processUser(userData),
);
return result;
};
export const lambdaHandler = withDurableExecution(handler);
文档
这个README为SDK的主要功能提供了快速的参考. 详细情况:
- API 参考 - 附有详细类型定义和操作规格的完整技术参考
- 概念和使用案例 - 了解重放模式、最佳做法和现实世界的例子,包括GenAI代理、人入工作流程和saga模式
- 捐款 - 学习如何为JavaScript的 AWS 持久执行 SDK 做出贡献
核心概念
持久语句
这个 DurableContext 是构建持久工作流程的主要接口。 它提供了执行步骤、等待、援引其他职能和协调平行行动的方法.
步骤操作
用自动重试和状态持久性执行原子操作 :
// Named step with retry configuration
const result = await context.step(
"fetch-data",
async (ctx) => {
return await fetchFromAPI();
},
{
retryStrategy: (error, attempt) => ({
shouldRetry: attempt < 3,
delay: { seconds: Math.pow(2, attempt) },
}),
},
);
// Anonymous step
const data = await context.step(async () => processData());
重要数字 : step() 仅用于单一原子操作。 组合多个可持久操作, 使用 runInChildContext()。 。 。 .
儿童背景
以孤立状态跟踪方式分组多个持久操作 :
const orderResult = await context.runInChildContext(
"process-order",
async (childCtx) => {
// Child context has its own step counter and state
const validated = await childCtx.step("validate", async () =>
validateOrder(order),
);
await childCtx.wait({ seconds: 1 });
const charged = await childCtx.step("charge", async () =>
chargePayment(validated),
);
return charged;
},
);
引用其他函数
调用另一个 AWS Lambda 函数并等待完成 :
const result = await context.invoke(
"process-payment",
"arn:aws:lambda:us-east-1:123456789012:function:payment-processor",
{ amount: 100, currency: "USD" },
);
等待操作
在指定期限内暂停执行 :
// Wait 30 seconds
await context.wait({ seconds: 30 });
// Named wait for tracking
await context.wait("rate-limit-delay", { seconds: 5 });
有条件的等待
等待定期检查状态满足条件 :
const finalState = await context.waitForCondition(
"wait-for-job",
async (currentState, ctx) => {
const status = await checkJobStatus(currentState.jobId);
return { ...currentState, status };
},
{
initialState: { jobId: "job-123", status: "pending" },
waitStrategy: (state, attempt) => {
if (state.status === "completed") {
return { shouldContinue: false };
}
return {
shouldContinue: true,
delay: { seconds: Math.min(attempt * 2, 60) },
};
},
},
);
外部调用
等待外部系统完成操作 :
// Create a callback and send ID to external system
const [callbackPromise, callbackId] = await context.createCallback(
"external-approval",
{ timeout: { minutes: 3 } },
);
await sendApprovalRequest(callbackId, requestData);
const approvalResult = await callbackPromise;
// Or use waitForCallback with submitter function
const result = await context.waitForCallback(
"wait-for-webhook",
async (callbackId, ctx) => {
await submitToExternalAPI(callbackId);
},
{ timeout: { minutes: 5 } },
);
批量操作
地图
处理项目阵列,对每个有货币控制的持久操作:
const results = await context.map(
"process-users",
users,
async (ctx, user, index) => {
return await ctx.step(`process-${user.id}`, async () => processUser(user));
},
{
maxConcurrency: 5,
completionConfig: {
minSuccessful: 8,
toleratedFailureCount: 2,
},
itemNamer: (user, index) => `User-${user.id}`,
},
);
// Check results
console.log(
`Succeeded: ${results.successCount}, Failed: ${results.failureCount}`,
);
results.throwIfError(); // Throws if any failures
说明数字 : map() 在同一 Lambda 范围内,利用儿童背景进行持久行动(步骤、等等)。 它不会产生单独的Lambda功能.
平行
执行多个分支,同时进行持久操作:
const results = await context.parallel(
"parallel-tasks",
[
{ name: "task1", func: async (ctx) => ctx.step(async () => fetchData1()) },
{ name: "task2", func: async (ctx) => ctx.step(async () => fetchData2()) },
async (ctx) => ctx.step(async () => fetchData3()),
],
{
maxConcurrency: 2,
completionConfig: { minSuccessful: 2 },
},
);
说明数字 : parallel() 在同一 Lambda 引用范围内执行持久操作。 每个分支在自己的儿童背景中运行,都有孤立的状态跟踪.
提前完成
A 类 map() 或者说 parallel() 完成时间很早,在每件物品完成之前,完成规则。 没有 completionConfig,规则为故障快取: 第一次故障完成批次. minSuccessful, (中文(简体) ), toleratedFailureCount, (中文(简体) ), toleratedFailurePercentage 财务报告和审定财务报表 shouldComplete 设置其他规则。 设置其中的任何一个替换故障快取 .
批量检查它的规则 每次一个物品的结果到达它。 一旦遵守规则,其余物品即被废弃:
- 正在运行的项目报告为
STARTED。不计为successCount或者说failureCount。 。 。 . - 由于
maxConcurrency,不出现在all。 。 。 . - 该批货物不等待被废弃的物品,也不阻止它们。 批次上下文完成后,物品的出站点即被撤销. 被遗弃的物品只有在等待停放检查站时才停止。 在此之前,它的代码可以在引用活动时持续运行,它的副作用可能发生. 没有什么等待它, 所以引用可以先结束:
- 引用激活时, 函数运行的一步会持续运行 。 它不能保证完成。 如果在批次上下文后完成,则其结果不作记录.
- 一个新的
step默认值StepSemantics.AtLeastOncePerRetry运行过一次功能,历史没有记录。 一个新的waitForCondition运行过一次检查功能。 东西就停了. runInChildContext不等待自己的检查站。 因此它的功能运行,内部的操作遵循了这些规则.- 一个新的
wait, (中文(简体) ),invoke, (中文(简体) ),createCallback, (中文(简体) ),waitForCallback,或与StepSemantics.AtMostOncePerRetry在项目生效前停止。 "新"指批次上下文完成后项目开始. 较早开始的一次行动可能已经记录其开始和生效.
接下来会发生什么取决于 处理器在批次后所做的:
- 如果处理器返回,引用可以结束,而被废弃的代码仍然运行. 那密码不能保证完成.
- 如果操作者等待, 例如在一个
wait或召回,在放弃步骤函数时,援引不能中止,或waitForCondition检查仍在运行中 。 这种行动在功能返回和关闭的检查站解除之前,即为运行。 因此一个缓慢被放弃的功能使引用活动得以进行,这增加了其持续时间和成本.
被废弃的物品可以在批次上下文完成前记录其结果. 这包括一个在完成批次的项目之前记录了结果的项目,但其结果后来到达了批次。 处决历史显示其儿童背景 SUCCEEDED 或者说 FAILED,则 BatchResult 报告为: STARTED与 NestingType.FLAT,项目没有儿童背景,历史显示它的运作.
处理器只接收 BatchResult重放返回相同的已完成项目和相同的 completionReason。重放可以省略 STARTED 项,因此 started(), (中文(简体) ), startedCount 财务报告和审定财务报表 totalCount 可以在重播后有所不同。 因此,根据已完成的项目作出决定,不核对 BatchResult 与处决历史.
要得到每个项目的结果,使用一个不能提前完成的规则. 设定 toleratedFailurePercentage: 100,然后离开 minSuccessful, (中文(简体) ), toleratedFailureCount 财务报告和审定财务报表 shouldComplete 未设. 然后,批量等待每一个项目。 失败的项目出现在 failed()。电话没有发出,所以打电话 throwIfError() 如果失败必须阻止处理者:
const results = await context.map("process-all", items, processItem, {
completionConfig: { toleratedFailurePercentage: 100 },
});
const failures = results.failed(); // every failed item, with its error
承诺组合者
用于快速、模拟操作(使用) map() 或者说 parallel() 长期作业:
// Wait for all promises
const [user, posts, comments] = await context.promise.all([
fetchUser(userId),
fetchPosts(userId),
fetchComments(userId),
]);
// Race promises
const fastest = await context.promise.race([
fetchFromPrimary(),
fetchFromSecondary(),
]);
// Wait for first success
const result = await context.promise.any([
fetchFromSource1(),
fetchFromSource2(),
fetchFromSource3(),
]);
// Wait for all to settle
const results = await context.promise.allSettled([operation1(), operation2()]);
说明:承诺协调人接受已经执行的承诺,不能提供货币控制或持久性。 使用 map() 或者说 parallel() 用于持久,有控制的处决.
操作子类型
runInChildContext, (中文(简体) ), step,以及 createCallback 接受一个 subType 选项。 构成多个操作的函数可以使用它来标记其部件. SDK在检查站中记录了子类型并传递给插件. 因此,执行历史和插件可以过滤这些部件而不解析名称.
ctx.runInChildContext(
name,
async (child) => {
const receipt = await child.step("charge", async () => charge(orderId), {
subType: "OrderCharge",
});
await child.step("notify", async () => notify(receipt), {
subType: "OrderNotify",
});
return receipt;
},
{ subType: "ChargeAndNotify" },
);
服务接受1至32个字符 [a-zA-Z0-9-_]。空字符串选择默认子类型,例如 Step 或者说 Callback。重放时将子类型与检查站进行比较。 所以,改变一个子类型 是一种突破性的改变 在飞行中处决.
@aws/durable-execution-sdk-js-extras 以这种方式建造的现成作业,例如 microvm。 。 。 .
配置
动态仪器插件
仪器插件可以在 Lambda 冷起步时不导入 在功能的文物。 在函数或函数中安装一个提供者软件包 Lambda 层,然后设置一个命令的包或模块规格列表:
DURABLE_EXECUTION_PLUGINS=@example/durable-otel,@example/durable-audit/provider
SDK 导入每个模块一次 withDurableExecution(...) 初始化
包裹的处理器。 未设置或空白变量保留了已有的
行为 插件通过 DurableExecutionConfig.plugins 首先运行在
它们的配置顺序; 环境选择的插件按照列出的顺序遵循
内 DURABLE_EXECUTION_PLUGINS两种来源都是添加剂,包括:
创建相同的插件类型.
提供者模块导出一个命名的工厂 durableExecutionPluginProviderA级
工厂是一个带有 createPlugin(info) 方法; 一个空函数不是
一并被拒绝。 SDK电话 createPlugin 一次引用,与此
引用 InvocationInfo,所以它返回的例子 正好服务于一个
援引:
import type {
DurableInstrumentationPlugin,
DurableInstrumentationPluginFactory,
} from "@aws/durable-execution-sdk-js";
class AuditPlugin implements DurableInstrumentationPlugin {
constructor(
private readonly exporter: Exporter,
private readonly executionArn: string,
) {}
// Implement the lifecycle hooks needed by this plugin.
}
// Built once for the execution environment and shared by every instance.
const exporter = new Exporter();
export const durableExecutionPluginProvider: DurableInstrumentationPluginFactory<AuditPlugin> =
{
createPlugin: (info) => new AuditPlugin(exporter, info.executionArn),
};
因为一个实例在引用返回时被放弃,所以插件从来没有 通过执行 ARN 到密钥执行状态, 以及两个执行状态 在一个执行环境中 同时不能观察对方的状态. 属于执行环境的国家——出口国、追踪国 供货商,一个调度员——如上所述,属于厂外.
模块指定符必须通过普通应用模块解决
解析或节点.js模块路径。 对于Lambda层,包装提供者和
其附属关系 nodejs/node_modules数字 :
plugin-layer.zip
`-- nodejs
`-- node_modules
`-- @example
`-- durable-audit
配置不当, 缺少模块或导出, a
durableExecutionPluginProvider 无 createPlugin 方法和条目
DurableExecutionConfig.plugins 报告为: PluginLoadError
执行状态读取前失败 —— 两个来源由相同的检查
规则,因为一个条目没有 createPlugin 无法生成插件 。 A 类
createPlugin 当它运行时扔出,或返回的任何东西, 都象
任何其它插件失败: 该插件会排出引用和执行
不受影响.
仪器操作状态和出错
使用 OperationInfo.status 以识别终端操作状态,例如 FAILED, (中文(简体) ),
CANCELLED, (中文(简体) ), TIMED_OUT,以及 STOPPED。 。 。 . OperationInfo.error 包含可选
错误细节; 操作失败 error === undefined,包括
重放和 onOperationChange 元数据。 缺少或空的检查出错数据
不创建错误。 应用的部分细节,包括明确为空
字符串或空堆栈跟踪,仍然可用.
这也适用于 API-v1 插件: 只使用存在 error
因为它的故障信号应该检查 status 换句话说 对于一个尝试端钩,
使用情况 AttemptEndInfo.outcome 以确定该尝试是否失败。 一个外部
没有错误细节的调回失败仍然拒绝调回承诺
保留其失败的运行状态; 可选的仪器细节没有
改变呼叫者的结果 或坚持状态.
重试策略
自定义重试策略 :
await context.step("custom-retry", async () => riskyOperation(), {
retryStrategy: (error, attempt) => ({
shouldRetry: attempt < 5 && error.message.includes("timeout"),
delay: { seconds: attempt * 2 },
}),
});
步骤语义
控制执行保证:
import { StepSemantics } from "@aws/durable-execution-sdk-js";
// At-least-once per retry (default)
await context.step("retriable-operation", async () => sendNotification(), {
semantics: StepSemantics.AtLeastOncePerRetry,
});
// At-most-once per retry
await context.step("idempotent-operation", async () => updateDatabase(), {
semantics: StepSemantics.AtMostOncePerRetry,
});
重要: 这些语义应用 每次重试,不是每个总体执行:
- AtLEastOncePertrich 重写时: 该步骤将在每次重试时至少执行一次 。 如果该步骤成功但检查站失败(如沙盒崩溃),该步骤将在重放时重新执行.
- 在最旧的回收站: 该步骤每次重试最多一次执行. 执行前会设置一个检查点,因此如果在检查点之后但步骤完成前发生故障,在重放时会跳过之前的尝试.
一步步实现最高一等语义,使用自定义重试策略:
await context.step(
"truly-once-only",
async () => callThatCannotTolerateDuplicates(),
{
semantics: StepSemantics.AtMostOncePerRetry,
retryStrategy: () => ({ shouldRetry: false }), // No retries
},
);
没有这个,一个步骤使用 AtMostOncePerRetry 已启用的重试仍然可以在不同的重试尝试中执行多次 .
抖动策略
防止雷鸣群:
import {
JitterStrategy,
createRetryStrategy,
} from "@aws/durable-execution-sdk-js";
const retryStrategy = createRetryStrategy({
maxAttempts: 5,
initialDelay: { seconds: 1 },
maxDelay: { seconds: 60 },
exponentialDelayFactor: 2,
jitterStrategy: JitterStrategy.FULL,
});
自定义运输
默认SDK与Lambda持久行刑API会谈. 你可以换了
通过实施 DurableExecutionClient,它有两个操作
名称中无 AWS 类型 :
import {
CheckpointDurableExecutionRequest,
CheckpointDurableExecutionResponse,
DurableExecutionClient,
DurableExecutionClientError,
DurableExecutionClientErrorScope,
GetDurableExecutionStateRequest,
GetDurableExecutionStateResponse,
withDurableExecution,
} from "@aws/durable-execution-sdk-js";
class HttpDurableExecutionClient implements DurableExecutionClient {
constructor(private readonly endpoint: string) {}
async getExecutionState(
params: GetDurableExecutionStateRequest,
): Promise<GetDurableExecutionStateResponse> {
const response = await fetch(`${this.endpoint}/state`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(params),
});
if (!response.ok) {
throw this.toClientError(
"Failed to read execution state",
response.status,
);
}
return response.json() as Promise<GetDurableExecutionStateResponse>;
}
async checkpoint(
params: CheckpointDurableExecutionRequest,
): Promise<CheckpointDurableExecutionResponse> {
const response = await fetch(`${this.endpoint}/checkpoint`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(params),
});
if (!response.ok) {
throw this.toClientError("Checkpoint failed", response.status);
}
return response.json() as Promise<CheckpointDurableExecutionResponse>;
}
// Tell the SDK whether to end just this invocation or the whole execution.
private toClientError(
message: string,
status: number,
): DurableExecutionClientError {
return new DurableExecutionClientError(`${message}: ${status}`, {
scope:
status >= 400 && status < 500 && status !== 429
? // A rejected request will not succeed on retry.
DurableExecutionClientErrorScope.EXECUTION
: // Throttling and server-side errors may.
DurableExecutionClientErrorScope.INVOCATION,
});
}
}
export const handler = withDurableExecution(myHandler, {
durableExecutionClient: new HttpDurableExecutionClient(
process.env.DURABLE_ENDPOINT!,
),
});
没有说明的范围,每一次失败都被当作是短暂的,所以一个永久的被重审 直到处决时间结束 请注意,在SDK自己的范围之前,人们相信有明确的范围 检查错误,所以一个运输 包另一个承担责任 将它所包裹的错误分类.
为了保持Lambda的运输, 但要自己配置客户端, 传递给
DurableExecutionApiClient 而不是使用被贬值的 client 选项 :
import { DurableExecutionApiClient } from "@aws/durable-execution-sdk-js";
import { LambdaClient } from "@aws-sdk/client-lambda";
export const handler = withDurableExecution(myHandler, {
durableExecutionClient: new DurableExecutionApiClient(
new LambdaClient({ region: "us-west-2", maxAttempts: 5 }),
),
});
日志
访问已丰富日志 :
const handler = async (event: any, context: DurableContext) => {
context.logger.info("Processing started", { userId: event.userId });
try {
const result = await context.step("process", async (ctx) => {
ctx.logger.debug("Step executing");
return processData();
});
context.logger.info("Processing completed", { result });
return result;
} catch (error) {
context.logger.error("Processing failed", error);
throw error;
}
};
自定义日志 :
context.configureLogger({
customLogger: {
log: (level, message, data, error) =>
console.log(`[${level}] ${message}`, data),
error: (message, error, data) => console.error(message, error, data),
warn: (message, data) => console.warn(message, data),
info: (message, data) => console.info(message, data),
debug: (message, data) => console.debug(message, data),
},
modeAware: false, // Optional: show logs during replay (default: true)
});
本地开发提示 : 设定 modeAware: false 以在重放时查看所有日志,这可以帮助调试:
context.configureLogger({ modeAware: false });
AWS Lambda 的动力工具( TypeScript)
createPowertoolsLogger 包裹一个 动力工具 Logger。然后每个日志条目都包含持久执行元数据: executionArn, (中文(简体) ), requestId, (中文(简体) ), tenantId, (中文(简体) ), operationId, (中文(简体) ), operationName,以及 attempt。没有值的密钥会被省略。 每个条目还包含配置插件所添加的字段, 如 OTel 插件 traceId 财务报告和审定财务报表 spanId,如同默认日志的条目.
import { Logger } from "@aws-lambda-powertools/logger";
import {
createPowertoolsLogger,
DurableContext,
PowertoolsDurableLogger,
withDurableExecution,
} from "@aws/durable-execution-sdk-js";
const logger = new Logger({ serviceName: "my-service" });
export const handler = withDurableExecution(
async (
event: { orderId: string },
context: DurableContext<PowertoolsDurableLogger<Logger>>,
) => {
context.configureLogger({ customLogger: createPowertoolsLogger(logger) });
context.logger.info("workflow-started", { orderId: event.orderId });
},
);
- 声明
context作为DurableContext<PowertoolsDurableLogger<Logger>>,如上. (中文(简体) ). 礛context.logger而步骤日志接受 Powertools 参数类型。 没有声明,context.logger接受任何参数. - 密钥使用与默认日志机和Python SDK相同的名称.
- 在日志调用中传递的密钥会用同名的元数据密钥取而代之. 元数据替换密钥为
appendKeys或者说persistentKeys,因为Powertools应用的每个调用键后面这些. - 适配器读取每通呼叫的元数据. 所以一个适配器实例记录正确
operationId财务报告和审定财务报表attempt(c) 对同时采取的步骤和儿童的背景. - 仅读出功用工具
message从一个Error成为第一个争论, 要登录堆栈,通过Error作为后来的论点:context.logger.error("charge failed", error)。 。 。 . - SDK并不依赖于
@aws-lambda-powertools/logger。安装到您的函数中. logger.addContext(context.lambdaContext)添加 Powertools Lambda 上下文字段, 例如cold_start财务报告和审定财务报表function_name。还添加function_request_id,重复requestId对于租户范围的处决,它增加了tenant_id,重复tenantId。电源工具在Logger举个例子 因此,当几个引用同时在一个过程中进行时,例如关于Lambda管理案例,它们具有援引的价值观addContext最后一个 持久的元数据字段没有这个问题.
离开 POWERTOOLS_DEV 已部署的函数中未设置环境变量。 当它被设定时, Powertools通过全球写作 console使用 Lambda 的 JSON 日志格式, Lambda 将每个 console 在 JSON 对象中行。 因此,每个Powertools 条目在 message 第二个 JSON 对象的字段.
这个 powertools-logger 用于定义它自己的适配器类的示例, 适配器类会写出 snake case key(execution_arn, (中文(简体) ), request_id, (中文(简体) ), operation_id) (中文(简体) ). createPowertoolsLogger 写入骆驼Case键 。 如果您复制了这个示例, 可将日志查询和度量过滤器更新到骆驼 案件名称.
运行时间要求
SDK的目标是Lambda管理的节点运行时间(nodejs22.x, (中文(简体) ), nodejs24.x),在其中
下面的一切都自动满足。 它也运行在一个 带有您的容器图像
拥有 JavaScript 运行时间,这就是如何在运行时间Lambda上部署持久函数
无法管理.
在装入时,SDK会导入这些节点所建的: async_hooks, (中文(简体) ), crypto, (中文(简体) ), events, (中文(简体) ),
node:console, (中文(简体) ), node:crypto, (中文(简体) ), node:fs/promises (单位:千美元)mkdir, (中文(简体) ), readFile, (中文(简体) ), writeFile, (中文(简体) ),
node:path, (中文(简体) ), node:url 财务报告和审定财务报表 node:util说明a 名为 EME 的缺失导出导入
在舱载时致命,最初不使用——所以运行时间提供模块但不能使用
成员 SDK 的进口将因 SyntaxError 在你的操作员运行之前.
也装入 @aws-sdk/client-lambda 在第一个检查站,通过动态导入。 如果你捆绑
与 @aws-sdk 标记外部,运行时间必须提供该客户端.
没有 Async 本地服务器的运行时间
一些轻量级的跑步时间—— 专 员例如——执行 只有节点 API 的一部分。 SDK探测并围绕两个缺口工作 否则就是 致命 :
async_hooks.AsyncLocalStorage用于跟踪在全局运行的持久操作await边框。 没有它,SDK只能回到同步码内追踪.util.formatWithOptions用于默认日志。 没有它,SDK会回到util.format。 。 。 .
检查和重放不受影响,检查站数据为同字节. SDK每一次执行环境都会发出一个警告 是否为:
对不运行时间的影响 AsyncLocalStorage | |
|---|---|
之后发布的日志记录 await | 输 operationId, (中文(简体) ), operationName 财务报告和审定财务报表 attempt |
| 重放- 意识记录 | 无法禁用重放记录, 因此重放边框后的日志语句会被重新发送到 每次重播 这增加了长期处决的云表成本 |
在内部使用父上下文或兄弟上下文 runInChildContext | 仅在同步发生时检测到 |
最后一个项目是防止真正的决定性错误, 所以如果你部署在这样的运行时间,
启用 no-nested-durable-operations 规则从
@aws/durable-execution-sdk-js-eslint-plugin, (中文(简体) ),
它在建设时也发现了同样的错误.
表现是一个与支持不同的问题. 持久处决重放,重放成本增加 以已完成的操作数量计算,所以没有JIT的运行时间总体上可以更慢 具有大型操作的工作流程计数或计算重级步骤——即使开始得更快. 在切换前测量你自己的工作量 .
许可证
这个项目根据Apache-2.0许可证获得许可证.
SDK 3.x 插件迁移
见 2.x至3.0移徙指南 页:1 软件包版本,实例前/之后,提供者包装,以及验证.
SDK 3.x要求从遗留的v1供应商合同中明确迁移.
供应商声明 pluginApiVersion 以 PluginLoadError 内
两者 plugins 财务报告和审定财务报表 DURABLE_EXECUTION_PLUGINS 登记。 他们不是沉默的
调用不同的寿命 : v1 createPlugin() 跑一次每个操作员,
而一个3.x工厂 createPlugin(info) 每次引用一次.
将遗留的提供者/机构登记改为工厂对象:
import { withDurableExecution, type InvocationInfo } from "@aws/durable-execution-sdk-js";
const factory = {
createPlugin(info: InvocationInfo) {
return new MyPlugin(info);
},
};
const handler = withDurableExecution(myHandler, { plugins: [factory] });
为每次引用返回一个新插件实例 。 继续有意分享
援引范围之外的资源,如追踪提供者/出口商;
将特定引用的跨度、操作图和缓冲器保留在内。 删除
遗产 pluginApiVersion 财务报告和审定财务报表 pluginType 迁移工厂后的元数据.
环境加载模块仍在导出 durableExecutionPluginProvider,其
值现在是这个工厂形状。 升级捆绑的 OTel 层与核心
3.x 并使用其工厂建造者; 旧的 1.x 层被拒绝而不是
默然再释. Core 2.x 支持的 v1 供应商不受此影响
主要政策.