尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Dagger TypeScript SDK connect 模块解析:connect() 与 connection() 的引擎连接机制

Dagger TypeScript SDK connect 模块解析:connect() 与 connection() 的引擎连接机制 Dagger TypeScript SDK connect 模块解析connect() 与 connection() 的引擎连接机制【免费下载链接】daggerAutomation engine to build, test and ship any codebase. Runs locally, in CI, or directly in the cloud项目地址: https://gitcode.com/GitHub_Trending/da/daggerconnect 模块是 Dagger TypeScript SDK 的引擎连接入口它负责启动/接入 Dagger 引擎会话、初始化 GraphQL 客户端并把可编程的Client对象或全局dag客户端交到你的回调函数中。读完本文你将掌握connect()与connection()两个 API 的完整签名、ConnectOpts全部配置项、底层会话建立链路自动 provisioning 与DAGGER_SESSION_*直连并能直接写出可运行的 Dagger TypeScript 流水线。本文基于仓库中 version-0.20 的 TypeScript 参考文档 展开并结合 sdk/typescript 目录下的真实源码进行验证与补充。一、connect 模块在 SDK 中的位置connect是 dagger.io/dagger 包内的一个核心子模块其 API 参考文档位于 reference/typescript/connect完整模块清单见 modules.md。从 sdk/typescript/src/index.ts 可以看出包的公开导出中与连接相关的部分包括// Connection for library export type { CallbackFct } from ./connect.js export { connect, connection } from ./connect.js export type { ConnectOpts } from ./connectOpts.js // Export dagger connection context export { Context, BaseClient } from ./common/context.js也就是说一个典型的 Dagger TypeScript 流水线只需要一行导入即可获得全部连接能力import { connect } from dagger.io/daggerconnect 模块本身暴露的 API 并不多参考文档中一共包含一个类型别名和两个函数API类型作用CallbackFctType Aliasconnect()回调函数的签名connectFunction建立连接并把Client实例传给回调connectionFunction用全局dag客户端执行回调二、CallbackFctconnect() 的回调类型CallbackFct是传给connect()的回调函数类型其完整定义是type CallbackFct (client: Client) Promisevoid参数client类型为 Client是经过代码生成client.gen的 Dagger GraphQL API 客户端container()、host()、directory()、git()等一切顶层操作都从它出发。返回值Promisevoid回调内部可以await任意 Dagger 操作返回后连接会话随即被清理。在 sdk/typescript/src/connect.ts 中它的声明与文档完全对应export type CallbackFct (client: Client) Promisevoid注意connection()的回调签名与CallbackFct不同——它不接收client参数详见下文第五节因此connect与connection在使用形态上有明显差异。三、connect()显式客户端连接函数签名connect(cb: CallbackFct, config?: ConnectOpts): Promisevoidcb类型为 CallbackFct接收Client实例。config?类型为ConnectOpts默认值{}。返回值Promisevoid。参考文档对connect的定位描述是connect runs GraphQL server and initializes a GraphQL client to execute query on it through its callback. This implementation is based on the existing Go SDK.运行/建立 GraphQL 会话并初始化 GraphQL 客户端通过回调在它上面执行查询实现基于既有 Go SDK。源码实现解读sdk/typescript/src/connect.ts 中的实现清晰地展示了它背后的四步动作export async function connect( cb: CallbackFct, config: ConnectOpts {}, ): Promisevoid { await withGQLClient(config, async (gqlClient: GraphQLClient) { const connection new Connection(gqlClient) const ctx new Context([], connection) const client new Client(ctx) // Warning shall be throw if versions are not compatible try { await client.version() } catch (e) { console.error(failed to check version compatibility:, e) } return await cb(client) }) }withGQLClient(config, cb)建立或复用指向 Dagger 引擎的 GraphQL 连接。这是整个连接机制的枢纽其内部逻辑在下一节详细展开。构造客户端栈new Connection(gqlClient)包装 GraphQL 客户端new Context([], connection)创建带连接上下文的求值上下文最后new Client(ctx)生成对外暴露的 Dagger 客户端。版本兼容性检查await client.version()会向引擎发起一次 version 查询如果失败例如 SDK 与引擎版本不匹配打印告警failed to check version compatibility但不会中断执行——注意源码注释为Warning shall be throw if versions are not compatible目前实现为捕获异常并输出到 stderr。执行用户回调await cb(client)把初始化完成的Client交给你的业务代码。典型用法import { connect } from dagger.io/dagger await connect( async (client) { const out await client .container() .from(alpine) .withExec([echo, hello from dagger]) .stdout() console.log(out) }, { LogOutput: process.stderr }, )四、ConnectOpts连接配置项全解ConnectOpts定义于 sdk/typescript/src/connectOpts.ts注释明确说明其用途ConnectOpts defines option used to connect to an engine.三个字段及其默认行为如下字段类型默认值说明Workdirstringprocess.cwd()覆盖 Dagger 的工作目录。流水线中client.host().workdir()读取到的就是该目录LoadWorkspaceModulesbooleanfalse不开启是否加载 workspace 模块默认只暴露核心 APIcore APILogOutputWritable不输出开启引擎日志输出需传入 Node.js 可写流如process.stdout/process.stderrWorkdir控制宿主工作目录当你的脚本运行目录与 Dagger 逻辑工作目录不一致时可以通过Workdir显式指定await connect( async (client) { const entries await client.host().workdir().entries() console.log(entries) }, { Workdir: /path/to/my/project }, )LoadWorkspaceModules加载 workspace 模块默认情况下连接只暴露 Dagger 核心 API。如果你的项目配置了 workspace 模块例如通过dagger.toml声明了模块依赖需要把该选项置为true连接时才会加载这些模块供dag/client调用。LogOutput日志流输出便于在终端直接观察引擎侧日志。源码注释给出了一个完整例子connect(async (client: Client) { const source await client.host().workdir().id() // ... 其余流水线逻辑 }, { LogOutput: process.stdout })五、connection()全局 dag 客户端函数签名connection(fct: () Promisevoid, cfg?: ConnectOpts): Promisevoidfct() Promisevoid无参数回调。cfg?ConnectOpts默认值{}。返回值Promisevoid。参考文档对connection的定位是connection executes the given function using the default global Dagger client.使用默认的全局 Dagger 客户端执行给定函数。这里的“全局客户端”即 SDK 代码生成文件中暴露的dag变量见 api/client.gen.ts 中的export const dag。源码实现解读export async function connection( fct: () Promisevoid, cfg: ConnectOpts {}, ) { try { telemetry.initialize() // Wrap connection into the opentelemetry context for propagation await opentelemetry.context.with(telemetry.getContext(), async () { try { await withGQLClient(cfg, async (gqlClient) { // Set the GQL client inside the global dagger client globalConnection.setGQLClient(gqlClient) await fct() }) } finally { globalConnection.resetClient() } }) } finally { await telemetry.close() } }相比connect()connection()做了三件额外的事初始化并关闭 OpenTelemetry 遥测telemetry.initialize()在开头调用telemetry.close()在finally中兜底确保任何路径下遥测资源都会被释放同时整个回调被包进opentelemetry.context.with(...)用于跨异步边界的上下文传播context propagation。注入全局 GQL 客户端globalConnection.setGQLClient(gqlClient)把当前会话的 GraphQL 客户端挂到全局Connection单例上之后dag的所有操作都走这个客户端。会话结束清理finally中globalConnection.resetClient()把全局客户端置空避免泄漏到下一个连接。参考文档示例参考文档为connection提供了可直接运行的示例——构建一个 Alpine 容器、安装 curl 并抓取 dagger.io 首页全程无需手写Clientawait connection( async () { await dag .container() .from(alpine) .withExec([apk, add, curl]) .withExec([curl, https://dagger.io/]) .sync() }, { LogOutput: process.stderr } )该示例与源码注释中的example完全一致是connection()最典型的用法回调体内直接使用全局dag变量配置项只需按需传入。六、底层连接机制withGQLClient 与会话建立无论是connect还是connection最终都汇聚到 sdk/typescript/src/common/graphql/connect.ts 的withGQLClient。它的职责注释写得很清楚Execute the callback with a GraphQL client connected to the Dagger engine. It automatically provisions the engine if needed.用连接到 Dagger 引擎的 GraphQL 客户端执行回调必要时自动拉起引擎。其决策逻辑分两条路径export async function withGQLClientT( connectOpts: ConnectOpts, cb: (gqlClient: GraphQLClient) PromiseT, ): PromiseT { if (process.env[DAGGER_SESSION_PORT]) { const port process.env[DAGGER_SESSION_PORT] if (!process.env[DAGGER_SESSION_TOKEN]) { throw new Error( DAGGER_SESSION_TOKEN must be set if DAGGER_SESSION_PORT is set, ) } const token process.env[DAGGER_SESSION_TOKEN] return await cb(createGQLClient(Number(port), token)) } try { const provisioning await import(../../provisioning/index.js) return await provisioning.withEngineSession(connectOpts, cb) } catch (e) { throw new Error( failed to execute function with automatic provisioning: ${e}, { cause: e }, ) } }直连已有会话Session 内运行当环境变量DAGGER_SESSION_PORT存在时SDK 认为当前进程运行在 Dagger 会话例如模块运行时、dagger call内中此时必须同时提供DAGGER_SESSION_TOKEN否则直接抛出DAGGER_SESSION_TOKEN must be set if DAGGER_SESSION_PORT is set。通过createGQLClient(port, token)建立 GraphQL 客户端不再自行启动引擎。自动 provisioning否则动态导入 sdk/typescript/src/provisioning/index.ts 中的withEngineSession自动完成引擎二进制下载、引擎启动、会话协商等全套流程对应ConnectOpts中的工作目录与日志配置也在此生效。任何失败都会被包装为failed to execute function with automatic provisioning: ...并带上原始cause。而 sdk/typescript/src/common/graphql/connection.ts 中的Connection类则负责 GraphQL 客户端的生命周期管理export class Connection { constructor(private _gqlClient?: GraphQLClient) {} resetClient() { this._gqlClient undefined } setGQLClient(gqlClient: GraphQLClient) { this._gqlClient gqlClient } getGQLClient(): GraphQLClient { if (!this._gqlClient) { throw new Error(GraphQL client is not set) } return this._gqlClient } } export const globalConnection new Connection()globalConnection是包级单例connection()用它挂载/重置全局客户端Context求值时通过getGQLClient()惰性取用。若在未连接状态下调用会得到明确的GraphQL client is not set错误——这也解释了为什么所有流水线代码都必须包在connect/connection回调内部执行。七、connect() 与 connection() 如何选择维度connect(cb, config?)connection(fct, cfg?)回调参数显式传入Client实例无参数使用全局dag适合场景普通脚本 / CLI 程序显式拿到客户端模块代码或习惯用dag全局变量的场景遥测不主动初始化/关闭自动初始化并关闭 OpenTelemetry 遥测版本检查连接时调用client.version()并告警不显式检查依赖全局客户端连接清理withGQLClient结束即释放额外resetClient()重置全局单例实践中两者可互换的场景很多把connection示例中的dag换成client就等价于connect的写法。但请注意保持统一——connection依赖全局客户端状态若在同一个进程里先connect再connectionglobalConnection的状态可能互相干扰因此官方建议按项目约定固定使用其一。八、完整实战一个可运行的 CI/CD 脚本综合上文所有内容下面是一个功能完整的示例连接引擎、读取宿主工作目录、执行容器构建并开启日志输出与版本检查告警。import { connect } from dagger.io/dagger async function main() { await connect( async (client) { // 1. 查看宿主工作目录受 ConnectOpts.Workdir 影响 const workdir client.host().workdir() console.log(workdir entries:, await workdir.entries()) // 2. 构建并运行一个 Alpine 容器任务 const out await client .container() .from(alpine:3.20) .withExec([sh, -c, echo DAGGER_OK uname -a]) .stdout() console.log(container output:, out) }, { Workdir: process.cwd(), // 默认值可显式覆盖 LogOutput: process.stderr, // 引擎日志输出到 stderr LoadWorkspaceModules: false, // 默认仅核心 API }, ) } main().catch((err) { console.error(err) process.exit(1) })配套的工程化准备来自 TypeScript SDK 说明文档# 安装 SDK建议作为开发依赖 npm install dagger.io/dagger --save-dev # SDK 以 ESM 类型模块导出项目需声明相同类型 npm pkg set typemodule # tsconfig.json 需使用 NodeNext 模块解析 # module: NodeNext运行时若设置了DAGGER_SESSION_PORT例如在 Dagger 模块会话中SDK 会直连现有引擎而不重复启动否则会自动 provisioning 一个引擎会话因此这段代码既可以本地ts-node直接跑也能放进dagger call的模块上下文中执行。九、进一步探索API 参考完整的 TypeScript SDK 模块索引、Client 客户端类 以及dag全局变量说明。源码连接核心 connect.ts 与 connectOpts.ts会话建立 common/graphql/connect.ts 与 common/graphql/connection.ts自动 provisioning 见 provisioning。测试connect.spec.ts 提供了connect/connection的端到端用例适合作为学习连接语义的补充材料。其他语言 SDK 的同类连接入口可在 sdk 目录下对照查看Go、Python、Java、PHP、Rust 等。【免费下载链接】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),仅供参考
返回列表