ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Huly 客户端连接层剖析:@hcengineering/client-resources 的架构、演进与源码实现

Huly 客户端连接层剖析:@hcengineering/client-resources 的架构、演进与源码实现 Huly 客户端连接层剖析hcengineering/client-resources 的架构、演进与源码实现【免费下载链接】platformHuly — All-in-One Project Management Platform (alternative to Linear, Jira, Slack, Notion, Motion)项目地址: https://gitcode.com/GitHub_Trending/platform80/platform导读hcengineering/client-resources是 Huly 平台核心foundations/core中负责创建客户端连接的关键包它封装了 WebSocket 传输、RPC 编解码、心跳保活、断线重连、限流退避与模型过滤等能力。本文以该包自身文档与 CHANGELOG 为骨架结合仓库源码与测试用例完整讲解其连接建立流程、握手协议、超时机制、客户端模型加载策略以及版本演进脉络帮助你理解 Huly 客户端如何与平台服务端通信并掌握独立集成该连接层的实战方法。一、包定位平台客户端连接层的职责边界在 Huly 的 foundations/core 分层中hcengineering/client-resources位于 foundations/core/packages/client-resources其 readme.md 开宗明义本包允许创建与运行中平台交互的客户端Package allow to create a client to interact with running platform。从 package.json 可以看到它的依赖设计hcengineering/client定义客户端插件plugin id、元数据、GetClient资源声明与ClientSocket抽象hcengineering/core提供Client、ClientConnection、Tx、Hierarchy、ModelDb等核心类型与createClient组装逻辑hcengineering/rpc提供RPCHandler实现请求/响应的序列化与反序列化hcengineering/platform提供插件元数据getMetadata与平台状态setPlatformStatushcengineering/analytics错误上报snappyjs响应负载的压缩解压。也就是说client-resources 是连接层最贴近传输协议的那一层它把「平台插件资源」转化为可用的Client实例同时不关心具体业务模型。二、快速上手两行代码建立连接readme.md 给出了最简用法核心入口是默认导出资源的function.GetClient(token, transactorUrl)import clientResources from hcengineering/client-resources import core, { Client } from hcengineering/core // ... const token ... // Token obtained somehow. const connection: Client await (await clientResources()).function.GetClient(token, transactorUrl) // Now client is usable // Use close, to shutdown connection. await connection.close()注意这里的token是携带身份信息的 JWT。在 src/index.ts 中decodeTokenPayload会解析 JWT 的 payload 段atob(token.split(.)[1])从中提取workspace与account字段如果二者缺失会直接抛出Workspace or account not found in token错误。连接 URL 则由concatLink(endpoint, / token)拼接而成src/index.ts。Node.js 环境必须配置 WebSocket 工厂浏览器环境自带全局WebSocket但 Node.js 没有因此 readme 明确指出Node.js 环境必须使用ws包覆盖默认的 Socket 工厂readme.md// We need to override default WebSocket factory with ws one. setMetadata(client.metadata.ClientSocketFactory, (url) new WebSocket(url)) const connection: Client await (await clientResources()).function.GetClient(token, transactorUrl) // ...该元数据ClientSocketFactory定义在 foundations/core/packages/client/src/index.ts类型为(url: string) ClientSocket。在 src/connection.ts 中Socket 工厂的解析优先级是opt.socketFactory调用方显式传入 getMetadata(ClientSocketFactory)插件元数据 浏览器默认new WebSocket(url)。三、核心 APIconnect 函数与 Connection 类Connection类实现了ClientConnection接口是连接层的实体。对外暴露的工厂函数是connectsrc/connection.tsexport function connect ( url: string, handler: TxHandler, workspace: WorkspaceUuid, user: PersonUuid, opt?: ClientFactoryOptions ): ClientConnectionconnect的每次调用会创建一个独立的Connection实例内部维护会话标识浏览器环境下基于sessionStorage的session.id.url键管理sessionId页面刷新后可以复用同一会话beforeunload时回写保证刷新不丢会话src/connection.ts请求队列MapReqId, RequestPromise记录每个在途 RPC 请求事务处理器栈handlers: TxHandler[]服务端推送的事务会广播给所有 handler心跳状态pingResponse记录最近一次 pong 时间用于判定连接是否挂死。CHANGELOG 中 0.6.4 版本记录「Exposeconnect」正是把该函数作为公开 API 暴露随后 0.6.1 的「Fix server connection」修复了早期连接问题0.6.0 为初始发布Initial release。四、连接生命周期Hello 握手、二进制协议与压缩握手阶段Socketonopen后客户端立即发送hello请求src/connection.ts请求体包含客户端的能力声明const helloRequest: HelloRequest { method: hello, params: [], id: -1, binary: useBinary, // 是否启用二进制协议 compression: this.compressionMode // 是否启用协议压缩 }binary的默认值来自opt.useBinaryProtocol或元数据UseBinaryProtocol默认truecompression的默认值来自opt.useProtocolCompression或元数据UseProtocolCompression默认false。服务端以HelloResponse应答后客户端记录binaryMode、compressionMode、lastHash模型哈希与accountsrc/connection.ts并清除 dial 超时定时器随后通过onConnect回调通知上层连接事件区分Reconnected与Connected。心跳保活连接建立后立即启动schedulePingsrc/connection.ts。关键常量常量值含义pingTimeout10s每 10 秒发送一次pinghangTimeout5min超过 5 分钟未收到 pong 判定挂死并主动关闭 socketdialTimeout30s握手阶段 30 秒无响应触发onDialTimeout并强制重连CHANGELOG 中 0.6.2「server ping」与 0.6.3「ping」正是心跳机制逐步完善的记录。客户端同时支持文本ping/pong!与 ArrayBuffer 形式的 ping/pong 检测checkArrayBufferPing并通过pongConst刷新pingResponse。消息分块重组findAll的大结果集会被服务端按 chunk 分批返回。客户端在handleMsg中按index收集 chunk待final标记到达后排序拼接为完整FindResult并重建lookupMapsrc/connection.ts。五、断线重连与限流退避重连策略scheduleOpen负责重新打开连接src/connection.tsonclose或握手失败后会立即重连若处于错误状态delay从 0 开始逐次递增每次onerror增加 1上限由delay 3限制并作为秒数延迟下一次打开服务端返回state: upgrading维护/升级状态时delay被设为 3 秒客户端周期性重试直到升级完成已发出的请求在重连成功后通过promise.reconnect自动重发allowReconnect默认true从而对上层透明。限流处理服务端在响应中携带rateLimit信息时客户端维护currentRateLimit与slowDownTimersrc/connection.ts剩余配额低于limit / 3时slowDownTimer逐步上调上限 50ms每个请求发送前先 sleep 该时长避免触发封禁剩余配额为 0 时按retryAfter延迟后重发同一请求。六、客户端模型加载过滤、过滤模式与持久化GetClient内部通过createClient组装客户端src/index.ts。其核心参数是modelFilter取决于元数据FilterModel类型见 foundations/core/packages/client/src/index.ts模式行为none不过滤返回全部模型事务clientreturnClientTxes排除所有server-前缀插件以及 workbench/presentation/view/text-editor 等纯 UI 类定义如view:class:Action、view:class:Viewlet、presentation:class:ComponentPointExtensionuireturnUITxes排除所有未启用插件、未在getPlugins()与ExtraPlugins中注册的插件以及ExtraFilter中显式列出的插件这里ExtraFilter元数据正是 CHANGELOG 0.7.18「Add support for custom exclude filters」补丁的直接落点调用方可以通过setMetadata(client.metadata.ExtraFilter, [some-plugin])定制额外的插件排除列表从而在加载模型阶段就剔除不需要的插件事务。模型本身会持久化到浏览器的 IndexedDBmodel.db.persistenceobjectStoremodel以 workspace 为 key。createModelPersistence返回load/store两个方法src/index.ts并且允许通过OverridePersistenceStore元数据整体替换默认实现。在 foundations/core/packages/core/src/client.ts 的loadModel中客户端会先读取本地持久化的模型哈希与握手获得的lastHash比较哈希一致则直接用本地模型same否则增量拉取新事务addition或整体重建upgrade并把合并结果写回持久化存储。七、连接事件与会话恢复GetClient还支持可选参数ClientFactoryOptions定义于 foundations/core/packages/client/src/index.ts完整字段如下字段说明socketFactory自定义 Socket 工厂Node.js 必填useBinaryProtocol是否启用二进制协议默认 trueuseProtocolCompression是否启用协议压缩默认 falseconnectionTimeout连接超时毫秒超过后触发onDialTimeout并关闭连接onHello收到 hello 应答后回调返回 false 可拒绝连接onUpgrade检测到模型升级或维护结束时回调onError连接被服务端终止如工作区归档时回调错误码onConnect连接/重连事件回调ctx度量上下文MeasureContextonDialTimeout握手超时回调useGlobalRPCHandler是否复用全局 RPC handler在 src/index.ts 中connectionTimeout会创建一个竞态 Promise若超时仍未isConnected()则主动关闭连接并rejectonConnect回调则被包装为「服务端存活即 resolve」的信号Maintenance事件除外。重连后的模型一致性由 foundations/core/packages/core/src/client.ts 保证通过比较本地lastTx与服务端返回的lastTx决定触发Reconnected数据未变无需刷新还是Refresh数据有增量需要刷新查询。另外服务端推送TxWorkspaceEvent且事件为MaintenanceNotification时客户端会通过setPlatformStatus抛出MaintenanceWarning状态通知 UI 展示维护倒计时src/index.ts。八、测试验证连接与集成的证据链该包配有完善的测试可直接作为连接行为的事实依据connection.test.ts用MockWebSocket模拟 Socket覆盖连接建立、ping/pong往返、服务端主动推送事务simulateTransaction等场景integration.test.ts用MockClientConnection与createTestClient端到端验证createClient组装后的行为包括事务端到端流转、findAll/findOne、全文搜索searchFulltext、域请求domainRequest、多 handler 广播、并发事务、断线重连状态切换以及Upgraded/Maintenance事件分发。这些测试确认了connect创建的连接不仅能完成 RPC 请求还能正确地把服务端推送的事务分发给所有注册的TxHandler并在连接关闭时优雅清理定时器与在途请求。九、版本演进解读CHANGELOG 视角CHANGELOG.md 记录了两个重要阶段2021 年初始阶段0.6.x0.6.0 初始发布 → 0.6.1 修复服务端连接 → 0.6.2/0.6.3 引入服务端 ping 与 ping 保活 → 0.6.4 公开暴露connect工厂。这一阶段奠定了连接层的基础骨架其后的行为都可以在上述Connection类实现中找到对应。2025 年 0.7.x 阶段0.7.4 修复格式、0.7.5 升级 platform rig、0.7.6 更新依赖直到0.7.182025-11-26两个功能性补丁Add password agingCHANGELOG 明确记录该补丁从连接层视角看它意味着令牌/账号层面的过期校验被引入与decodeTokenPayload从 JWT 中解析workspace/account的身份模型协同工作Add support for custom exclude filters直接对应ExtraFilter元数据允许上层自定义模型过滤时的插件排除列表见第六节。当前包版本为 0.7.19见 package.json完整结构化的变更记录可对照 CHANGELOG.json含每次发布的依赖升级明细与 tag 命名规则如hcengineering/client-resources_v0.7.18。十、小结hcengineering/client-resources是 Huly 前端/客户端与平台服务端之间的「翻译层与链路管家」它用不到千行的核心实现承载了握手协议、二进制/压缩传输、心跳保活、挂死检测、指数退避重连、限流规避、分块结果重组、模型过滤与 IndexedDB 持久化等一整套生产级连接能力。对集成者而言只需准备好 JWT token 与服务端端点Node.js 额外配置ClientSocketFactory即可通过GetClient在数行代码内获得完整可用的Client实例。关联文档CHANGELOG.md · readme.md · CHANGELOG.json核心实现connection.ts · index.ts依赖与抽象foundations/core/packages/client/src/index.ts · foundations/core/packages/core/src/client.ts测试用例connection.test.ts · integration.test.ts【免费下载链接】platformHuly — All-in-One Project Management Platform (alternative to Linear, Jira, Slack, Notion, Motion)项目地址: https://gitcode.com/GitHub_Trending/platform80/platform创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表