signalrpool-nodejs-sdk
v1.0.2
Published
SignalR Pool Node.js TypeScript SDK
Maintainers
Readme
SignalR Pool Node.js SDK
适用于 SignalR Pool 服务器的 TypeScript/Node.js SDK,提供分布式 RPC 能力和自动重连功能。
目录
功能特性
- 自动重连:内置无限重试机制,支持可配置的重连延迟
- 类型安全:完整的 TypeScript 支持,提供全面的类型定义
- RPC 支持:支持调用远程 Worker 方法,支持版本路由
- 服务发现:列出和发现池中的其他 Worker
- 心跳管理:自动处理心跳机制
- 流畅 API:易于使用的构建器模式进行配置
- 事件驱动:全面的事件系统用于监控连接状态
- 灵活注册:支持从对象或单个函数注册 RPC 方法
安装
# 使用 pnpm(推荐)
pnpm add signalrpool-nodejs-sdk
# 使用 npm
npm install signalrpool-nodejs-sdk
# 使用 yarn
yarn add signalrpool-nodejs-sdk快速开始
基础 Worker
import { createSignalRPoolClient } from 'signalrpool-nodejs-sdk';
class MyWorker {
async greet(name: string): Promise<string> {
return `Hello, ${name}!`;
}
async processData(data: any): Promise<any> {
// 在此处理您的数据
return { processed: true, data };
}
}
async function main() {
const worker = new MyWorker();
const client = createSignalRPoolClient()
.withEndpoint('http://localhost:5000/endpoints/worker')
.withToken('your-auth-token')
.withBasicManifest(
'my-worker', // 标识符
'My Worker', // 显示名称
'A simple worker', // 描述
'1.0.0' // 版本
)
.withLogging(true)
.registerFromObject(worker)
.build();
// 设置事件监听器
client.on('connected', (connectionId) => {
console.log(`Connected: ${connectionId}`);
});
client.on('error', (error) => {
console.error('Error:', error);
});
// 启动客户端
await client.start();
}
main().catch(console.error);高级配置
import { createSignalRPoolClient, ConnectionState } from 'signalrpool-nodejs-sdk';
const client = createSignalRPoolClient()
.withEndpoint('http://localhost:5000/endpoints/worker')
.withToken('your-auth-token')
.withManifest({
identifier: 'advanced-worker',
workerName: 'Advanced Worker',
description: 'Worker with advanced features',
version: '2.1.0',
systemInfo: 'Custom System Info',
implementation: 'Node.js Custom'
})
.withAutoReconnect(true)
.withReconnectDelay(3000)
.withMaxReconnectAttempts(10)
.withLogging(true)
.registerMethod('customMethod', async (param1, param2) => {
return { result: param1 + param2 };
})
.registerMethods({
method1: async () => 'result1',
method2: async (data) => ({ processed: data })
})
.build();
// 增强事件处理
client.on('stateChanged', (state: ConnectionState) => {
console.log(`State: ${state}`);
});
client.on('reconnecting', (attempt) => {
console.log(`Reconnecting... attempt ${attempt}`);
});
client.on('heartbeatStarted', (interval) => {
console.log(`Heartbeat started: ${interval}s`);
});
await client.start();API 参考
SignalRPoolClient
方法
| 方法 | 描述 |
|------|------|
| start() | 启动连接 |
| stop() | 停止连接 |
| dispose() | 释放客户端并清理资源 |
| registerMethod(name, handler) | 注册单个 RPC 方法 |
| unregisterMethod(name) | 注销 RPC 方法 |
| invokeAsync<T>(identifier, method, version?, ...params) | 调用远程 Worker 方法(有返回值) |
| callAsync(identifier, method, version?, ...params) | 调用远程 Worker 方法(无返回值) |
| getInfo() | 获取当前 Worker 信息 |
| listWorkers() | 列出所有 Worker |
| listWorkersByIdentifier(identifier) | 按标识符列出 Worker |
属性
| 属性 | 描述 |
|------|------|
| connectionState | 当前连接状态 |
| connectionId | 当前连接 ID |
| isConnected | 是否已连接 |
事件
| 事件 | 描述 |
|------|------|
| stateChanged | 连接状态变更 |
| connected | 已连接到服务器 |
| disconnected | 已从服务器断开 |
| reconnecting | 正在尝试重连 |
| reconnected | 重连成功 |
| heartbeatStarted | 心跳已启动 |
| closeRequested | 服务器请求关闭 |
| restartRequested | 服务器请求重启 |
| error | 发生错误 |
SignalRPoolClientBuilder
配置方法
| 方法 | 描述 |
|------|------|
| withEndpoint(url) | 设置服务器端点 |
| withToken(token) | 设置认证令牌 |
| withManifest(manifest) | 设置 Worker 清单 |
| withBasicManifest(id, name, desc, version?) | 创建基础清单 |
| withAutoReconnect(enabled?) | 启用/禁用自动重连 |
| withReconnectDelay(ms) | 设置重连延迟 |
| withMaxReconnectAttempts(max) | 设置最大重连次数 |
| withLogging(enabled?) | 启用/禁用日志 |
方法注册
| 方法 | 描述 |
|------|------|
| registerMethod(name, handler) | 注册单个方法 |
| registerMethods(methods) | 注册多个方法 |
| registerFromObject(obj, exclude?) | 从对象注册所有方法 |
构建方法
| 方法 | 描述 |
|------|------|
| build() | 构建客户端 |
| buildAndStart() | 构建并启动客户端 |
使用示例
调用远程 Worker
// 调用另一个 Worker 的方法
const result = await client.invokeAsync('other-worker', 'processData', null, { foo: 'bar' });
// 带版本目标的调用
const result = await client.invokeAsync('other-worker', 'processData', '1.2.0', data);
// 无需返回值的调用
await client.callAsync('other-worker', 'notify', null, 'Hello!');服务发现
// 获取当前 Worker 的信息
const info = await client.getInfo();
console.log('My info:', info);
// 列出池中的所有 Worker
const allWorkers = await client.listWorkers();
console.log('All workers:', allWorkers);
// 列出特定类型的 Worker
const sameTypeWorkers = await client.listWorkersByIdentifier('my-worker');
console.log('Same type workers:', sameTypeWorkers);错误处理
try {
const result = await client.invokeAsync('remote-worker', 'riskyMethod', null, data);
} catch (error) {
if (error.message.includes('Connection is not active')) {
console.log('Not connected, will retry when reconnected');
} else {
console.error('RPC call failed:', error);
}
}优雅关闭
process.on('SIGINT', async () => {
console.log('Shutting down...');
await client.dispose();
process.exit(0);
});
process.on('SIGTERM', async () => {
console.log('Shutting down...');
await client.dispose();
process.exit(0);
});配置选项
SignalRPoolOptions
interface SignalRPoolOptions {
endpoint: string; // 服务器端点 URL
token: string; // 认证令牌
manifest: WorkerManifest; // Worker 清单
autoReconnect?: boolean; // 启用自动重连(默认:true)
reconnectDelay?: number; // 重连延迟,单位毫秒(默认:5000)
maxReconnectAttempts?: number; // 最大重连次数(默认:Infinity)
enableLogging?: boolean; // 启用日志(默认:false)
}WorkerManifest
interface WorkerManifest {
identifier: string; // 唯一标识符
workerName: string; // 显示名称
description: string; // 描述
version: string; // 版本(语义化版本)
systemInfo: string; // 系统信息
implementation: string; // 实现细节
}连接状态
| 状态 | 描述 |
|------|------|
| Disconnected | 未连接 |
| Connecting | 正在尝试连接 |
| Connected | 连接成功 |
| Disconnecting | 正在断开连接 |
| Reconnecting | 正在尝试重连 |
最佳实践
- 始终处理错误:RPC 调用可能失败,请始终使用 try-catch 包裹
- 使用优雅关闭:在进程退出时正确释放客户端
- 监控连接状态:监听状态变更事件
- 版本化您的 API:为 Worker 方法使用语义化版本
- 保持方法简洁:RPC 方法应无状态且功能专注
- 使用适当的超时:避免 RPC 调用无限期挂起
故障排除
连接问题
- 验证端点 URL 是否正确
- 检查认证令牌是否有效
- 确保 SignalR Pool 服务器正在运行且可访问
RPC 调用失败
- 验证目标 Worker 标识符是否存在
- 检查方法名称是否正确
- 确保目标 Worker 已连接
- 验证方法参数
重连问题
- 检查网络连接
- 验证服务器是否接受连接
- 检查重连配置(延迟、最大尝试次数)
