Show HN: Solidis - 轻量级无依赖 TS Redis 客户端,专为 Serverless 打造

Skip to content

vcms-io / **solidis ** Public

High-performance, SOLID-structured RESP client for Redis and other RESP-compatible servers

License

MIT license 29 stars 0 forks Branches Tags Activity

vcms-io/solidis

main BranchesTags

Code

Folders and files

Name| Name| Last commit message| Last commit date
---|---|---|---

Latest commit

History

5 Commits .github/workflows| .github/workflows
.vscode| .vscode
scripts| scripts
sources| sources
.editorconfig| .editorconfig
.gitattributes| .gitattributes
.gitignore| .gitignore
.npmignore| .npmignore
LICENSE| LICENSE
README.md| README.md
biome.json| biome.json
package-lock.json| package-lock.json
package.json| package.json
tsconfig.json| tsconfig.json
View all files

Repository files navigation

Solidis

@vcms-io/solidis

高性能、结构化的SOLID原则构建的RESP客户端,适用于Redis和其他兼容RESP的服务器

概述主要特性安装用法配置高级特性错误处理许可

npm version TypeScript ESM/CJS RESP2/RESP3 Zero Dependencies Bundle Size

概述

Solidis 是一个基于 SOLID 原则构建的现代 RESP 客户端,零依赖,并以企业级性能为目标。它支持 RESP2 和 RESP3 协议,并为现代 JavaScript/TypeScript 应用程序进行了优化。

该库旨在实现最小的包大小、最大的类型安全和性能:

主要特性

要求

安装

# 使用 npm
npm install @vcms-io/solidis
# 使用 yarn
yarn add @vcms-io/solidis
# 使用 pnpm
pnpm add @vcms-io/solidis

用法

客户端类型

Solidis 提供了两种客户端实现:

1. 基础客户端 (SolidisClient)

基础客户端包含最少的功能,以减少包大小。你需要使用特定命令扩展它:

import { SolidisClient } from '@vcms-io/solidis';
import { get } from '@vcms-io/solidis/command/get';
import { set } from '@vcms-io/solidis/command/set';
import { multi } from '@vcms-io/solidis/command/multi';
import type { SolidisClientExtensions } from '@vcms-io/solidis';

// 定义带有类型安全性的扩展
const extensions = {
  get,
  set,
  multi
} satisfies SolidisClientExtensions;

// 使用扩展初始化客户端
const client = new SolidisClient({
  host: '127.0.0.1',
  port: 6379
}).extend(extensions);

// 使用命令
await client.set('key', 'value');
const value = await client.get('key');

2. 特性客户端 (SolidisFeaturedClient)

一个方便的客户端,预加载了所有 RESP 命令:

import { SolidisFeaturedClient } from '@vcms-io/solidis/featured';

// 所有 RESP 命令都已预加载
const client = new SolidisFeaturedClient({
  host: '127.0.0.1',
  port: 6379
});

// 直接使用任何 RESP 命令
await client.set('key', 'value');
await client.hset('hash', 'field', 'value');
await client.lpush('list', 'item-1', 'item-2');

连接管理

// 创建客户端 (带延迟连接)
const client = new SolidisClient({
  host: '127.0.0.1',
  port: 6379,
  lazyConnect: true
}).extend({ get, set });

// 在需要时显式连接
await client.connect();

// 处理连接事件
client.on('connect', () => console.log('Connected to server'));
client.on('ready', () => console.log('Client is ready for commands'));
client.on('error', (err) => console.error('Error occurred:', err));
client.on('end', () => console.log('Connection closed'));

// 完成后关闭连接
client.quit();

基本操作

// 设置键
await client.set('key', 'value');

// 获取键
const value = await client.get('key');
console.log(value); // 'value'

// 删除键
await client.del('key');

事务

// 启动一个事务
const transaction = client.multi();

// 将命令排队 (不需要 await)
transaction.set('key', 'value');
transaction.incr('counter');
transaction.get('key');

// 执行事务
const results = await transaction.exec();
console.log(results); // [[ 'OK' ], [ 1 ], [ <Buffer 76 61 6c 75 65> ]]

// 或者根据需要放弃事务
const transaction = client.multi();
transaction.set('key', 'value');
transaction.discard(); // 取消事务

Pipelines

// 为 pipeline 创建命令
const commands = [
  ['set', 'pipeline', 'value'],
  ['incr', 'counter'],
  ['get', 'pipeline']
];

// 将命令作为 pipeline 发送
const results = await client.send(commands);
console.log(results); // [[ 'OK' ], [ 1 ], [ <Buffer 76 61 6c 75 65> ]]

Pub/Sub

// 订阅频道
client.on('message', (channel, message) => {
  console.log(`Received ${message} from ${channel}`);
});

await client.subscribe('news');

// 从另一个客户端发布
await client.publish('news', 'Hello world!');

配置

Solidis 提供了广泛的配置选项:

const client = new SolidisClient({
  // 连接
  host: '127.0.0.1',
  port: 6379,
  useTLS: false,
  lazyConnect: false,

  // 身份验证
  authentication: {
    username: 'user',
    password: 'password'
  },
  database: 0,

  // 协议 & 恢复
  clientName: 'solidis',
  protocol: 'RESP2',          // 'RESP2' 或 'RESP3'
  autoReconnect: true,
  enableReadyCheck: true,
  maxConnectionRetries: 20,
  connectionRetryDelay: 100,
  autoRecovery: {
    database: true,           // 重新连接后自动选择 DB
    subscribe: true,          // 自动重新订阅频道
    ssubscribe: true,          // 自动重新订阅分片频道
    psubscribe: true,          // 自动重新订阅模式
  },

  // 超时 (毫秒)
  commandTimeout: 5000,
  connectionTimeout: 2000,
  socketWriteTimeout: 1000,
  readyCheckInterval: 100,

  // 性能调优
  maxCommandsPerPipeline: 300,
  maxProcessRepliesPerChunk: 4 * 1024, // 4KB
  maxSocketWriteSizePerOnce: 64 * 1024, // 64KB
  rejectOnPartialPipelineError: false,

  // 解析器配置
  parser: {
    buffer: {
      initial: 4 * 1024 * 1024,     // 4MB
      shiftThreshold: 2 * 1024 * 1024, // 2MB
    },
  },

  // 事件监听器
  maxEventListenersForClient: 10 * 1024,
  maxEventListenersForSocket: 10 * 1024,

  // 调试选项
  debug: false,
  debugMaxEntries: 10 * 1024,
});

高级特性

自定义命令

import { SolidisClient } from '@vcms-io/solidis';
import { get, set } from '@vcms-io/solidis/command';
import type { SolidisClientExtensions } from '@vcms-io/solidis';

// 定义带有自定义命令的扩展
const extensions = {
  get,
  set,
  // 自定义命令实现
  fill: async function(this: typeof client, keys: string[], value: string) {
    return await Promise.all(keys.map((key) => this.set(key, value)));
  },
} satisfies SolidisClientExtensions;

const client = new SolidisClient({
  host: '127.0.0.1',
  port: 6379
}).extend(extensions);

// 使用自定义命令
await client.fill(['key1', 'key2', 'key3'], 'value');

原始命令

当您需要使用尚未实现的命令时:

// 使用 send() 的原始命令
const result = await client.send([['command', 'some', 'options']]);

调试

启用详细的调试日志记录:

// 启用调试模式
const client = new SolidisClient({
  debug: true
});

// 监听调试事件
client.on('debug', (entry) => {
  console.log(`[${entry.type}] ${entry.message}`, entry.data);
});

// 替代方案:环境变量
// DEBUG=solidis node app.js

错误处理

Solidis 为不同的故障模式提供了详细的错误类:

import {
  SolidisClientError,
  SolidisConnectionError,
  SolidisParserError,
  SolidisPubSubError,
  SolidisRequesterError,
  unwrapSolidisError,
} from '@vcms-io/solidis';

try {
  await client.set('key', 'value');
} catch (error) {
  // 获取带有堆栈跟踪的根本原因
  console.error(unwrapSolidisError(error));

  // 处理特定的错误类型
  if (error instanceof SolidisConnectionError) {
    console.error('Connection error:', error.message);
  } else if (error instanceof SolidisParserError) {
    console.error('Parser error:', error.message);
  } else if (error instanceof SolidisClientError) {
    console.error('Client error:', error.message);
  }
}

结构

┌─────────────────────────────────────────────────┐
│         SolidisClient         │
│                         │
│   Creates & coordinates all components    │
│                         │
│   ┌────────────────────────────────────┐   │
│   │       Debug Memory      │   │
│   └───────┬───────────────────┬────────┘   │
│       ▼          ▼        │
│   ┌────────────────┐ ┌────────────────┐   │
│   │  Connection  │─►│  Requester  │─┐  │
│   └────────────────┘ └────────────────┘ │  │
│             ┌────────────────┐ │  │
│             │   Parser   │◄┤  │
│             └────────────────┘ │  │
│             ┌────────────────┐ │  │
│             │   PubSub   │◄┘  │
│             └────────────────┘   │
│                         │
└─────────────────────────────────────────────────┘
     ┌──────────────┴─────────────┐
     ▼              ▼
┌─────────────────┐    ┌───────────────────────┐
│ SolidisClient  │    │ SolidisFeaturedClient │
│ (needs extend) │    │ (all commands)    │
└─────────────────┘    └───────────────────────┘

Solidis 结构遵循清晰的组件分离:

事件系统

Solidis 发出以下事件:

// 连接事件
client.on('connect', () => console.log('Connected to server'));
client.on('ready', () => console.log('Client is ready'));
client.on('end', () => console.log('Connection closed'));
client.on('error', (err) => console.error('Error:', err));

// Pub/Sub 事件
client.on('message', (channel, message) => console.log(`${channel}: ${message}`));
client.on('pmessage', (pattern, channel, message) => console.log(`${pattern} ${channel}: ${message}`));
client.on('subscribe', (channel, count) => console.log(`Subscribed to ${channel}`));
client.on('unsubscribe', (channel, count) => console.log(`Unsubscribed from ${channel}`));

// 调试事件
client.on('debug', (entry) => console.log(`[${entry.type}] ${entry.message}`));

贡献

Solidis 是一个开源项目,我们欢迎社区的贡献。 以下是如何做出贡献:

开发设置

# 克隆存储库
git clone https://github.com/vcms-io/solidis.git
cd solidis
# 安装依赖
npm install
# 构建项目
npm run build
# 运行测试
npm test

贡献指南

  1. Fork 存储库 : 首先 fork 存储库,然后克隆你的 fork。
  2. 创建分支 : 为你的特性或错误修复创建一个分支:
git checkout -b feature/your-feature-name
  1. 遵循代码风格 :
    • 使用 TypeScript 严格模式
    • 遵循现有的模式和命名约定
  2. 提交 Pull Request : 将你的更改推送到你的 fork 并提交一个 pull request。
    • 提供对更改的清晰描述
    • 引用任何相关问题
    • 添加适当的文档

代码质量指南

发布流程

Solidis 遵循语义版本控制 (SemVer):

许可

在 MIT 许可下获得许可。 有关更多信息,请参阅 LICENSE

关于

High-performance, SOLID-structured RESP client for Redis and other RESP-compatible servers

Resources

Readme

License

MIT license Activity Custom properties

Stars

29 stars

Watchers

1 watching

Forks

0 forks Report repository

Releases 1

Release v0.0.1 Latest May 16, 2025

Packages 0

No packages published

Languages

© 2025 GitHub, Inc.

Footer navigation