Skip to content

Commit c88dcfd

Browse files
authored
fix: 优化 c++ bindings 的析构函数和生命周期管理 (#2)
* refactor: 项目重构为 ts, 优化 js 侧状态管理,新增队列对实例状态更新进行处理, 优化 build 脚本 * fix: build.sh 支持 macos * fix: 单测优化 * cd: Bump version from 1.0.5 to 1.1.0 * feat: 单测重构为ts, 使用 vitest, 解决队列中的竞态问题 * fix: filename typo * fix: 优化 c++ bindings 的析构函数和生命周期管理 * style: add ESLint and Prettier configuration files - Add .eslintrc.js with TypeScript support and comprehensive linting rules - Configure ESLint to enforce code style including indentation, quotes, and semicolons - Add .prettierrc with formatting standards for consistent code formatting - Set print width to 120 characters and use 2-space indentation - Establish consistent code style across the TypeScript project to improve code quality and maintainability * chore: bump version from 1.1.0 to 1.1.1 - Update package.json version to 1.1.1 - Prepare release with bug fixes and improvements from recent commits * fix: exmaple * fix: 解决潜在死锁风险 * chore: eslint 配置更新 * fix: 抽象 common_utils, 修复了线程安全问题以及内存泄漏风险 * fix: 解决 producer send 的潜在内存泄露问题 * fix: ProducerSendCallback 构造函数内存泄漏问题,ConsumerMessageListener 内存管理 * fix: C++ bindings 新增 utils,抽象日志等公共处理, ts 状态处理与 C++ 保持一致
1 parent ac563a6 commit c88dcfd

25 files changed

Lines changed: 967 additions & 330 deletions

.prettierrc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"semi": true,
3+
"trailingComma": "none",
4+
"singleQuote": true,
5+
"printWidth": 120,
6+
"tabWidth": 2,
7+
"useTabs": false,
8+
"bracketSpacing": true,
9+
"arrowParens": "avoid",
10+
"endOfLine": "lf"
11+
}

AGENTS.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# AI 编码助手项目指令
2+
3+
> **语言要求**: 始终使用中文回复
4+
5+
---
6+
7+
## 🔴 强制规则 (MUST)
8+
9+
以下规则必须严格遵守,违反任何一条都是不可接受的:
10+
11+
12+
### 代码质量检查
13+
编码任务完成前,**必须按顺序执行以下检查**
14+
1. TypeScript 检查必须通过
15+
2. Lint 检查必须通过
16+
3. 单元测试必须全部通过
17+
4. Code Review 必须完成
18+
19+
### 单元测试要求
20+
- **服务端代码必须编写单测**
21+
- **单测覆盖率必须达到 100%**
22+
- **禁止 skip 任何测试用例**
23+
- **必须使用终端工具实际运行单测** - 不能假装运行
24+
25+
---
26+
27+
## 📋 命令参考
28+
29+
### TypeScript 检查
30+
31+
## TIPS
32+
- ts check
33+
```shell
34+
npm run build:ts
35+
```
36+
37+
### Lint 检查
38+
```shell
39+
# TypeScript/JavaScript 文件
40+
npm run lint
41+
42+
```
43+
44+
### 单元测试
45+
```shell
46+
## 可以有选择执行,对 lib 下的 C++ 文件进行编译
47+
./build.sh local
48+
## 然后执行
49+
npm run test <文件路径>
50+
```
51+
52+
53+
## ⚡ 执行流程
54+
55+
完成编码任务的标准流程:
56+
57+
```
58+
1. 理解需求
59+
60+
2. 编写/修改代码
61+
62+
3. 运行 TypeScript 检查
63+
64+
4. 运行 Lint 检查
65+
66+
5. 编写单测 (如需要)
67+
68+
6. 运行单测并等待完成
69+
70+
7. Code Review
71+
72+
8. 如有问题,返回步骤 2 修复
73+
74+
9. 完成
75+
```
76+
77+
---
78+
79+
## ⏳ 单测执行注意事项
80+
81+
- 单测启动和执行需要较长时间,**耐心等待**
82+
- 如支持后台进程读取,可使用 Background process 异步等待
83+
- **绝对禁止使用 sleep 命令等待**
84+

eslint.config.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
const js = require('@eslint/js');
2+
const tseslint = require('@typescript-eslint/eslint-plugin');
3+
const tsparser = require('@typescript-eslint/parser');
4+
5+
module.exports = [
6+
// Base configuration for all files
7+
js.configs.recommended,
8+
9+
// TypeScript files configuration
10+
{
11+
files: ['**/*.ts', '**/*.tsx'],
12+
languageOptions: {
13+
parser: tsparser,
14+
parserOptions: {
15+
ecmaVersion: 2020,
16+
sourceType: 'module',
17+
},
18+
globals: {
19+
console: 'readonly',
20+
process: 'readonly',
21+
Buffer: 'readonly',
22+
__dirname: 'readonly',
23+
__filename: 'readonly',
24+
module: 'readonly',
25+
require: 'readonly',
26+
exports: 'readonly',
27+
global: 'readonly',
28+
setTimeout: 'readonly',
29+
setInterval: 'readonly',
30+
clearTimeout: 'readonly',
31+
clearInterval: 'readonly',
32+
NodeJS: 'readonly',
33+
},
34+
},
35+
plugins: {
36+
'@typescript-eslint': tseslint,
37+
},
38+
rules: {
39+
// Disable problematic rules for this project
40+
'@typescript-eslint/no-unused-vars': 'off',
41+
'@typescript-eslint/no-explicit-any': 'off',
42+
'@typescript-eslint/explicit-function-return-type': 'off',
43+
'@typescript-eslint/explicit-module-boundary-types': 'off',
44+
'@typescript-eslint/no-non-null-assertion': 'off',
45+
'no-unused-vars': 'off',
46+
'no-undef': 'off',
47+
'no-redeclare': 'off',
48+
'no-constant-condition': 'off',
49+
50+
// Keep essential rules
51+
'no-console': 'off',
52+
'prefer-const': 'error',
53+
'no-var': 'error',
54+
'semi': ['error', 'always'],
55+
'quotes': ['error', 'single'],
56+
'eol-last': 'error',
57+
},
58+
},
59+
60+
// Ignore patterns
61+
{
62+
ignores: [
63+
'dist/',
64+
'build/',
65+
'node_modules/',
66+
'deps/',
67+
'Release/',
68+
'coverage/',
69+
'*.js',
70+
'test/',
71+
],
72+
},
73+
];

example/common.js

Lines changed: 0 additions & 7 deletions
This file was deleted.

example/common.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const config = {
2+
nameServer: '127.0.0.1:9876'
3+
// nameServer: 'onsaddr.cn-hangzhou.mq.aliyuncs.com:80'
4+
// nameServer: 'v0-default-<instanceId>.mq.cloudrun.local:9515'
5+
};

example/producer.js

Lines changed: 0 additions & 59 deletions
This file was deleted.

example/producer.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import * as readline from 'readline';
2+
import { config } from './common';
3+
import { Producer } from '../src';
4+
5+
if (typeof (Promise as any).withResolvers === 'undefined') {
6+
(Promise as any).withResolvers = function () {
7+
let resolve: ((value?: any) => void) | null = null;
8+
let reject: ((reason?: any) => void) | null = null;
9+
const promise = new Promise((res, rej) => {
10+
resolve = res;
11+
reject = rej;
12+
});
13+
return { promise, resolve, reject };
14+
};
15+
}
16+
17+
const rl = readline.createInterface({
18+
input: process.stdin,
19+
output: process.stdout
20+
});
21+
22+
void async function () {
23+
const producer = new Producer('GID_GROUP', {
24+
nameServer: config.nameServer
25+
});
26+
27+
// producer.setSessionCredentials('accessKey', 'secretKey', 'ALIYUN')
28+
29+
await producer.start();
30+
31+
while(1) {
32+
const { promise, resolve, reject } = (Promise as any).withResolvers();
33+
rl.question('Enter input: ', async (input: string) => {
34+
await producer.send('TP_TOPIC', input).catch(reject);
35+
resolve();
36+
});
37+
await promise;
38+
}
39+
40+
// producer.start(async function() {
41+
// console.log('producer started');
42+
// while(1) {
43+
// const { promise, resolve, reject } = Promise.withResolvers()
44+
// rl.question('Enter input: ', input => {
45+
// producer.send('TP_TOPIC', input, function(err, ret) {
46+
// if (err) {
47+
// console.error(err);
48+
// reject(err)
49+
// }
50+
// console.log(ret);
51+
// resolve(ret)
52+
// });
53+
// });
54+
// await promise.catch(console.error);
55+
// }
56+
// });
57+
58+
}();

example/push_consumer.js

Lines changed: 0 additions & 22 deletions
This file was deleted.

example/push_consumer.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { config } from './common';
2+
import { PushConsumer, Message, ConsumerAck } from '../src';
3+
4+
void function () {
5+
const consumer = new PushConsumer('GID_GROUP', {
6+
nameServer: config.nameServer
7+
});
8+
9+
// consumer.setSessionCredentials('accessKey', 'secretKey', 'ALIYUN');
10+
11+
consumer.subscribe('TP_TOPIC', '*');
12+
consumer.on('message', function(msg: Message, ack: ConsumerAck) {
13+
console.log(msg);
14+
ack.done(true);
15+
});
16+
17+
consumer.start(function() {
18+
console.log('consumer started');
19+
});
20+
}();

0 commit comments

Comments
 (0)