拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Dagger TypeScript SDK 中的 Error 对象:从 GraphQL 错误传播到结构化扩展值的完整指南

Dagger TypeScript SDK 中的 Error 对象从 GraphQL 错误传播到结构化扩展值的完整指南【免费下载链接】daggerAutomation engine to build, test and ship any codebase. Runs locally, in CI, or directly in the cloud项目地址: https://gitcode.com/GitHub_Trending/da/daggerDagger 是一个自动化引擎用于构建、测试和交付任意代码库。在 Dagger 的 TypeScript SDKdagger.io/dagger中Error是一个特殊的客户端类它并非普通 JS 的Error而是映射到引擎 GraphQL 核心类型Error的懒求值对象用于在 Dagger 调用链中以结构化方式承载错误消息与可机读的扩展值key/value 扩展。本文将基于 Dagger v0.21 TypeScript SDK 的官方 API 参考见 Error.md逐方法解析Error类与配套的ErrorValue类的用法并深入 core/error.go 与 core/schema/error.go 的源码实现帮助你理解错误对象在 Dagger 引擎中的真实行为从而在自己的 Dagger 模块中正确创建、扩展和读取错误。类定义与继承关系Error类在 TypeScript SDK 中定义于 sdk/typescript/src/api/client.gen.ts其类型声明位于Extends: BaseClient所有由 Dagger 代码生成器产出的客户端类Container、Directory、Client等都继承自内部的BaseClient。BaseClient持有 GraphQL 查询构建所需的Context与惰性选择器Selection因此Error对象本身只是一个未执行的查询占位符当你调用它的message()、values()等方法时才真正向引擎发起 GraphQL 查询并返回结果。这正是 Dagger SDK 一贯的惰性求值 可组合调用链设计本类也延续了这一模式。在 client.gen.ts 中可以看到Error类的真实实现它维护了_id与_message两个私有字段作为本地缓存当对应字段已被构造函数注入时直接返回避免多余的引擎往返。构造函数仅供内部使用new Error(ctx?, _id?, _message?): Error构造函数接收三个可选参数参数类型说明ctx?ContextDagger GraphQL 查询上下文由 SDK 内部注入_id?ID该 Error 的唯一标识符用于selectNode反查对象_message?string错误描述注入后message()可免查询直接返回官方文档明确标注Constructor is used for internal usage only, do not create object from it.构造函数仅供内部使用请勿自行创建对象。对应的 TS 源码注释在 client.gen.ts 中完全一致。在实际代码中你也不需要直接 new 一个Error正确的创建入口是Client上的工厂方法error()其签名为error (message: string): Error对应实现见 client.gen.ts它通过select(error, { message })构造一个指向 GraphQLerror(message: ...)字段的查询并包装为Error实例。服务端该字段的解析逻辑位于 core/schema/error.gofunc (s *errorSchema) error(ctx context.Context, _ *core.Query, args struct { Message string doc:A description of the error. }) (*core.Error, error) { // We dont want to see these in the UI trace.SpanFromContext(ctx).SetAttributes(attribute.Bool(telemetry.UIInternalAttr, true)) return core.Error{ Message: args.Message, }, nil }注意其中的细节创建Error对象时会在当前 span 上标记UIInternalAttr true表示这类对象属于内部实现细节不应展示在 Dagger UI 中。实例方法详解id()获取错误对象的唯一标识id(): PromiseID返回该 Error 的唯一标识符类型为ID一个不透明字符串。如果构造函数已经注入了_id则直接返回缓存值否则执行select(id)查询并返回结果见 client.gen.ts。ID在 Dagger 中承担了持久化对象句柄的作用core.Error实现了dagql.PersistedObject与dagql.PersistedObjectDecoder接口见 core/error.goEncodePersistedObject将Message与Values编码为 JSON payloadDecodePersistedObject负责反向还原因此Error可以像Container、Directory一样被序列化后在引擎内传递、跨会话引用。message()获取错误描述message(): PromisestringA description of the error.错误的描述文本。与id()相同若构造时已注入_message则直接返回否则执行select(message)查询。在服务端Message字段定义于 core/error.gotype Error struct { Message string field:true doc:A description of the error. Values []*ErrorValue field:true doc:The extensions of the error. }values()读取错误的扩展值列表values(): PromiseErrorValue[]The extensions of the error.错误的扩展。该方法返回ErrorValue对象数组每个ErrorValue是{ name: string; value: JSON }的键值对用于承载附加的结构化信息。其生成实现比较有代表性client.gen.tsSDK 首先执行select(values).select(id)拿到每个ErrorValue的 ID 列表随后通过selectNode(r.id, ErrorValue)为每个 ID 构建独立的懒查询对象——这是 Dagger TS SDK 处理对象数组字段的标准手法最终返回的ErrorValue[]中的每个元素都可以继续链式调用name()、value()。with()在不破坏调用链的前提下复用当前对象with(arg: (param: Error) Error): ErrorCall the provided function with current Error. This is useful for reusability and readability by not breaking the calling chain.以当前 Error 调用传入的函数便于在不打断调用链的前提下实现复用与可读性。实现非常简单client.gen.tswith (arg: (param: Error) Error) { return arg(this) }这是 Dagger 各 SDK 通用的with()模式把对当前对象的后续操作封装进回调函数返回回调的产物从而支持类似client.error(...).with(e e.withValue(code, 42))的可读写法。withValue()向错误附加结构化扩展值withValue(name: string, value: JSON): Error参数类型说明namestringThe name of the value.值的名称valueJSONThe value to store on the error.要存储在错误上的值返回一个新的Error。注意该方法是返回新对象而非原地修改——它通过select(withValue, { name, value })构造一条新的 GraphQL 选择器并包装成新的Error返回client.gen.ts这与整个 Dagger API 的不可变/惰性设计一致每次调用都产生一条新的查询链路最终由引擎统一求值。服务端withValue的实现见 core/schema/error.go它委托给core.Error.WithValuefunc (s *errorSchema) withValue(ctx context.Context, self *core.Error, args struct { Name string doc:The name of the value. Value core.JSON doc:The value to store on the error. }) (*core.Error, error) { return self.WithValue(args.Name, args.Value), nil }而core.Error.WithValue采用克隆后追加的不可变策略core/error.gofunc (e *Error) Clone() *Error { cp : *e cp.Values slices.Clone(e.Values) return cp } func (e *Error) WithValue(name string, value JSON) *Error { cp : e.Clone() cp.Values append(cp.Values, ErrorValue{ Name: name, Value: value, }) return cp }Values切片被深拷贝后再追加新元素保证原对象不受影响。配套类型ErrorValuevalues()返回的元素类型ErrorValue同样继承自BaseClient包含三个方法方法返回类型语义id()PromiseIDA unique identifier for this ErrorValue.唯一标识name()PromisestringThe name of the value.值的名称value()PromiseJSONThe value.值本体类型为 JSON服务端ErrorValue是core/error.go中一个精简的持久化对象core/error.gotype ErrorValue struct { Name string field:true doc:The name of the value. Value JSON field:true doc:The value. }JSON是 Dagger 对任意 JSON 值的封装类型因此withValue的第二个参数可以传入对象、数组、字符串、数字等任意可 JSON 序列化的数据使得错误不仅能携带人类可读的message还能附带错误码、失败步骤、重试建议、结构化上下文等供程序消费的数据。底层原理Error 如何参与 Dagger 的错误传播理解Error客户端对象的最佳方式是看它如何在引擎内部与 Go 的error体系打通。core.Error同时实现了两个 Go 接口core/error.govar _ error (*Error)(nil) func (e *Error) Error() string { return e.Message } var _ dagql.ExtendedError (*Error)(nil) func (e *Error) Extensions() map[string]any { ext : map[string]any{} for _, v : range e.Values { var val any json.Unmarshal(v.Value, val) ext[v.Name] val } return ext }这意味着任何返回*core.Error的解析器同时也是一个标准error其Error()返回Message且它的Values会被映射为 GraphQL 错误扩展字段extensions——这正好与values()在文档中的描述 The extensions of the error 遥相呼应。更关键的是转换函数NewErrorFromErrcore/error.go当引擎需要把一个任意 Go error 包装成可返回给客户端的Error对象时它会检查该 error 是否实现了dagql.ExtendedError接口若实现了则通过error(message: ...)字段创建Error并按 key 排序后逐个调用withValue(name, value)把Extensions()中的全部键值对附加进去若未实现则仅用error(message: fromErr.Error())创建只有message的Error。这一转换由CurrentDagqlServer(ctx).Select在服务端执行最终以 GraphQL 选择器序列的形式完成与你用 TS SDK 手工构造的调用链在语义上完全等价。可以推断当你在模块函数中抛出错误时Dagger 引擎会借助类似机制将错误投影为 GraphQLError对象使得错误信息能够以结构化的方式跨越引擎边界、出现在调用方的values()中。完整使用示例综合以上内容一个典型的 TypeScript SDK 使用场景如下import { dag } from dagger.io/dagger // 通过 Client 工厂方法创建 Error不要直接 new Error const err dag .error(build failed) .withValue(stage, compile) .withValue(exitCode, 1) // 惰性求值真正执行时才发起 GraphQL 查询 const message await err.message() const values await err.values() for (const v of values) { console.log(await v.name(), await v.value()) } // with() 让复用和组合更简洁 const decorated err.with((e) e.withValue(retryable, false))需要再次强调的是创建使用dag.error(message)对应 client.gen.ts构造函数仅供 SDK 内部使用惰性Error是查询占位符字段方法在被await时才执行 GraphQL 查询部分字段命中本地缓存时免查询不可变withValue()返回新对象原Error不受影响适合构建可复用的错误模板扩展values()读取的即 GraphQLextensions与core.Error.Extensions()的双向映射保持一致见 core/error.go。补充说明与适用前提本文基于仓库中version-0.21版本化文档目录下的 Error.md 及其关联的 ErrorValue.md。该页面是 SDK 自动生成的 API 参考的一部分完整索引见 client.gen 参考首页当前仓库主版本对应的 TS SDK 生成源码可在 sdk/typescript/src/api/client.gen.ts 中查阅核心类型定义与 GraphQL 解析器分别在 core/error.go 与 core/schema/error.go 中。若你使用的 Dagger 版本不同方法签名与行为可能有所差异请以你所安装版本的 SDK 生成代码与文档为准。【免费下载链接】daggerAutomation engine to build, test and ship any codebase. Runs locally, in CI, or directly in the cloud项目地址: https://gitcode.com/GitHub_Trending/da/dagger创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门