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

资讯详情

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

Dagger TypeScript SDK 中的 connection():全局客户端连接机制完全指南

Dagger TypeScript SDK 中的 connection():全局客户端连接机制完全指南 Dagger TypeScript SDK 中的 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/dagger导读connection()是 Dagger TypeScript SDK 提供的核心连接函数用于在任意回调函数中自动建立与 Dagger 引擎的会话并通过全局默认客户端dag执行构建、测试和发布等流水线操作。本文基于 docs/versioned_docs/version-0.20/reference/typescript/connect/functions/connection.md 展开结合 sdk/typescript/src/connect.ts 等源码与测试用例深入讲解它的函数签名、配置项、底层引擎会话建立流程、自动清理机制以及与connect()的异同帮助你写出可复制、可运行、符合工程实践的 TypeScript Dagger 脚本。函数签名与核心语义签名与参数connection()的完整函数签名如下connection(fct, cfg?): Promisevoid参数类型说明fct() Promisevoid要执行的异步回调函数在连接建立后被调用cfg?ConnectOpts {}可选的连接配置对象默认值为空对象{}返回值Promisevoid回调执行完毕后连接自动关闭按照官方参考文档的定义connection 使用默认的全局 Dagger 客户端dag执行给定的函数。也就是说回调函数体内不需要显式创建Client实例直接通过模块级导入的dag对象即可访问全部 Dagger API。官方示例原文档给出了一个完整可运行的示例——在 Alpine 容器中安装 curl 并抓取 Dagger 官网首页await connection( async () { await dag .container() .from(alpine) .withExec([apk, add, curl]) .withExec([curl, https://dagger.io/]) .sync() }, { LogOutput: process.stderr } )这里有两个值得注意的细节回调函数体内直接使用dag.container().from(alpine)构造容器执行链没有手动 new 任何客户端第二个参数{ LogOutput: process.stderr }将引擎会话的日志输出重定向到标准错误流便于在终端实时观察连接建立与执行进度。ConnectOpts 配置项详解ConnectOpts定义了连接引擎时使用的可选配置。其公开定义位于 sdk/typescript/src/connectOpts.ts共有三个对外暴露的字段Workdir类型string默认值process.cwd()作用覆盖 Dagger 的工作目录workdir。SDK 会将该目录通过--workdir参数传给引擎会话引擎中的host().workdir()等 API 将基于此目录解析宿主文件系统路径。LoadWorkspaceModules类型boolean默认值未开启false作用选择是否为本连接加载工作区模块workspace modules。默认情况下只暴露核心 APIcore API开启后connection会向引擎会话追加--load-workspace-modules参数从而把当前工作区中定义的自定义模块一并加载进来。LogOutput类型Writable来自node:stream作用开启日志输出。可传入process.stdout或process.stderr等可写流SDK 会在下载 CLI、创建引擎会话、建立连接等关键阶段写入进度信息并把引擎子进程的 stderr 管道到该流。connect(async (client: Client) { const source await client.host().workdir().id() // ... }, { LogOutput: process.stdout })内部扩展配置在引擎连接层内部sdk/typescript/src/provisioning/engineconn.tsConnectOpts还包含Project与Timeout字段。Project会映射为引擎会话的--project参数用于指定项目路径这属于内部连接器的扩展接口公开文档层面对外暴露的仍是前面三个配置项。connection() 的底层实现四层调用链从源码看connection()的实现体现了懒初始化 全局单例 自动清理的设计思想。完整实现位于 sdk/typescript/src/connect.tsexport 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() } }整个调用链可以拆成四层第一层Telemetry 初始化与关闭。函数入口调用telemetry.initialize()在函数整体结束时通过finally块调用telemetry.close()保证即使回调抛错遥测资源也能被释放同时将整个连接过程包裹进 OpenTelemetry 的 context 中实现跨进程的 trace 传播。第二层withGQLClient建立 GraphQL 客户端。这是真正的连接核心定义在 sdk/typescript/src/common/graphql/connect.ts。它的逻辑是如果环境变量DAGGER_SESSION_PORT已设置则使用该端口和DAGGER_SESSION_TOKEN直接连接一个已经运行的引擎会话否则走自动供应provisioning路径按需下载/启动引擎后再连接。第三层写入全局连接。globalConnection.setGQLClient(gqlClient)把 GraphQL 客户端注入全局单例Connection见 sdk/typescript/src/common/graphql/connection.ts。dag就是基于这个全局连接进行懒求值的——在调用connection()之前dag的 GraphQL 客户端是undefined只有真正进入回调后查询才会被提交执行。第四层回调执行与自动清理。await fct()执行用户逻辑无论成功与否finally块中的globalConnection.resetClient()都会将全局连接置回undefined确保本次会话不会泄漏到下一次调用。两种连接方式connection() 与 connect() 的对比TypeScript SDK 实际上暴露了两个入口见 sdk/typescript/src/index.tsconnection和connect。它们的差异体现在回调签名上维度connection(fct, cfg?)connect(cb, config?)回调参数无参数直接使用全局dag接收显式创建的Client实例客户端创建由globalConnection单例提供每个回调新建ConnectionContextClient版本检查无回调前调用client.version()做兼容性检查适用场景脚本/简单流水线需要独立客户端实例或精细控制的场景connect的实现位于 sdk/typescript/src/connect.ts其注释明确说明该实现基于现有的 Go SDK。它会在回调前尝试调用client.version()进行版本兼容性检查失败时向 stderr 打印警告但不中断执行。两个入口共享底层的withGQLClient与 provisioning 逻辑因此下文介绍的引擎会话建立机制对两者同样适用。引擎会话的自动供应Provisioning机制当没有预设DAGGER_SESSION_PORT时SDK 会自动完成下载 CLI → 启动引擎会话 → 解析连接参数的完整流程实现在 sdk/typescript/src/provisioning/bin.ts。整个流程如下定位 CLI 二进制优先使用环境变量_EXPERIMENTAL_DAGGER_CLI_BIN指定的路径未设置时从dl.dagger.io下载与 SDK 配套版本的 CLI当前 SDK 内置版本见 sdk/typescript/src/provisioning/default.ts 的CLI_VERSION。校验下载完整性SDK 先拉取checksums.txt下载归档后计算 SHA-256 并与期望值比对不匹配即抛出校验错误如果目标版本在发布源不可用HTTP 403/404则回退到从PATH中查找本地dagger可执行文件并输出兼容性警告。启动引擎会话以dagger session子命令启动子进程按需附加--workdir、--project、--label dagger.io/sdk.name:nodejs、--label dagger.io/sdk.version:sdkVersion以及--load-workspace-modules等参数。解析连接参数通过 readline 逐行读取子进程 stdout解析出 JSON 编码的{ port, session_token }连接参数见engineconn.ts中的ConnectParams接口再用其构造指向http://127.0.0.1:port/query的 GraphQL 客户端。超时与清理整个会话建立有 300 秒300000ms的超时上限超时抛出EngineSessionConnectionTimeoutError回调结束后通过 SIGTERM 终止引擎子进程。复用已运行引擎DAGGER_SESSION_PORT / DAGGER_SESSION_TOKENwithGQLClient对已运行引擎的检测逻辑如下sdk/typescript/src/common/graphql/connect.tsif (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)) }注意一旦设置了DAGGER_SESSION_PORTDAGGER_SESSION_TOKEN就是必填项否则直接抛错。这组环境变量常用于在已经启动的引擎会话例如由daggerCLI 或上层框架托管的会话内复用连接避免重复供应引擎。全局客户端 dag 的懒初始化与自动重置connection()之所以能让回调直接使用dag关键在于全局单例Connectionsdk/typescript/src/common/graphql/connection.tsexport 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()从测试用例 sdk/typescript/src/test/connect.spec.ts 可以看到这种懒初始化是如何被验证的// 调用前连接未建立GQL client 为 undefined assert.equal(dag[_ctx][_connection][_gqlClient], undefined) const ctr dag.container().from(alpine:3.16.2).withExec([echo, hello, world]) await connection(async () { const out await ctr.stdout() assert.equal(out, hello world\n) // 回调内连接已建立 assert.notEqual(dag[_ctx][_connection][_gqlClient], undefined) }) // 回调结束连接已被 resetClient 重置 assert.equal(dag[_ctx][_connection][_gqlClient], undefined)这个测试同时验证了三件事在进入connection()之前dag上的操作只是被记录、不会真的发起 GraphQL 请求懒求值回调内请求执行时连接可用退出回调后连接被可靠重置。因此每个connection()调用都是一个自包含的会话单元开发者不需要也不应该手动管理连接的开关。完整实战示例带日志输出的基础用法import { connection } from dagger.io/dagger await connection( async () { const out await dag .container() .from(alpine:3.16.2) .withExec([echo, hello, world]) .stdout() console.log(out) // 输出: hello world }, { LogOutput: process.stderr }, )指定工作目录并加载工作区模块import { connection } from dagger.io/dagger await connection( async () { // 基于宿主工作目录执行构建 const source await dag.host().workdir().id() // ... 后续构建逻辑 }, { Workdir: /path/to/your/project, LoadWorkspaceModules: true, LogOutput: process.stdout, }, )直接发送原生 GraphQL 查询dag还暴露了底层的getGQLClient()可以在connection()回调内直接提交 GraphQL 请求对应测试 connect.spec.tsimport { connection } from dagger.io/dagger await connection(async () { const result await dag.getGQLClient().request( query { container { from(address: alpine) { withExec(args: [echo, hello, world]) { stdout } } } } ) // result.container.from.withExec.stdout hello world\n })注意事项与最佳实践不要在connection()之外使用dag执行查询全局连接仅在回调期间有效回调结束后globalConnection已被重置在回调外调用会触发GraphQL client is not set错误。错误处理交给finallyconnection()内部无论回调成功还是抛错都会执行遥测关闭与连接重置因此无需在回调内自行清理连接。日志输出建议重定向到process.stderr官方示例即采用此方式可以避免与 stdout 上的业务输出混在一起。长任务注意 300 秒会话超时引擎会话建立阶段有 5 分钟超时上限源码中timeOutDuration 300000极耗时的首次引擎启动如首次拉取引擎镜像需要预留足够时间。优先复用已有会话在 CI 或已被框架托管的运行环境中设置DAGGER_SESSION_PORTDAGGER_SESSION_TOKEN可以跳过 CLI 下载与引擎启动显著缩短连接耗时。总结connection()是 Dagger TypeScript SDK 中最常用的连接入口它以全局客户端dag为媒介、以回调为生命周期边界封装了引擎会话的供应、连接、执行与清理全流程。理解它的签名、ConnectOpts配置项以及withGQLClient→ provisioning →globalConnection的底层链路可以帮助你在编写 Dagger TypeScript 流水线时写出更简洁、健壮且易于排查问题的代码。如需深入研究实现细节可继续阅读 sdk/typescript/src/connect.ts、sdk/typescript/src/common/graphql/connect.ts 与 sdk/typescript/src/provisioning/bin.ts 及其配套测试 sdk/typescript/src/test/connect.spec.ts。【免费下载链接】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),仅供参考
返回列表