Azure JS SDK序列化长时间运行操作状态供后续复用报错求解
问题原因
你遇到的报错是因为直接对getPollState()返回的对象执行JSON序列化时,会自动丢弃所有函数类型的属性,其中就包含报错信息提到的operationSpec.serializer.deserialize方法。反序列化后重建的轮询器缺少必要的序列化/反序列化逻辑,调用poll()方法时就会抛出异常。
正确解决方案
@azure/ms-rest-azure-js 包提供的LROPoller实例已经内置了专门的序列化能力,无需手动处理轮询状态的序列化逻辑,按以下步骤实现即可:
- 序列化阶段直接调用LROPoller实例的
serialize()方法,得到可以安全存储的标准字符串,该方法已经自动完成了非序列化属性的适配处理 - 恢复阶段直接调用
SqlManagementClient实例的restoreLROPollerFromSerializedString()方法,传入之前得到的序列化字符串,即可得到可用的轮询器实例
修改后的代码示例
import { SqlManagementClient } from "@azure/arm-sql"; import { DefaultAzureCredential } from "@azure/identity"; import { LROPoller } from "@azure/ms-rest-azure-js"; const subscription = "<subscription ID>"; const rg = "myResourceGroup"; const server = "mySqlServer"; const dbName = "myDb"; const credentials = new DefaultAzureCredential(); const sqlClient = new SqlManagementClient(credentials, subscription); const originalDb = await sqlClient.databases.get(rg, server, dbName); const operation: LROPoller = await sqlClient.databases.beginCreateOrUpdate(rg, server, dbName + "_copy", { location: "westeurope", createMode: "Copy", sourceDatabaseId: originalDb.id }); // 直接调用内置序列化方法得到可存储的字符串 const serializedState = operation.serialize(); // 此处可将serializedState存入数据库、缓存等持久化存储,之后程序可直接退出 // 恢复阶段直接调用对应方法重建轮询器,无需手动JSON反序列化 const restoredOperation: LROPoller = sqlClient.restoreLROPollerFromSerializedString(serializedState); // 可正常执行轮询、等待完成等操作 await restoredOperation.poll(); // 若要直接等待操作完成可调用:await restoredOperation.pollUntilFinished()
补充说明
- 序列化得到的字符串支持跨进程、跨机器传输使用,只要恢复时使用的
SqlManagementClient实例权限配置正确,就可以正常轮询操作状态。 - 若你使用的SDK版本不支持上述内置序列化/恢复方法,也可以直接保存长时间运行操作的轮询URL(Azure LRO操作响应头的
Azure-AsyncOperation字段值),后续自行定时发GET请求轮询该地址即可:返回体中status字段为Succeeded/Failed时代表操作结束,这种方式更轻量,也不存在序列化依赖问题。
内容的提问来源于stack exchange,提问作者Radek Petruška
相关产品推荐
相关产品推荐

