@f2a/network 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/README.md +278 -63
  2. package/dist/cli/commands.d.ts.map +1 -1
  3. package/dist/cli/commands.js +29 -2
  4. package/dist/cli/commands.js.map +1 -1
  5. package/dist/cli/config.d.ts +176 -0
  6. package/dist/cli/config.d.ts.map +1 -0
  7. package/dist/cli/config.js +386 -0
  8. package/dist/cli/config.js.map +1 -0
  9. package/dist/cli/daemon.d.ts +54 -0
  10. package/dist/cli/daemon.d.ts.map +1 -0
  11. package/dist/cli/daemon.js +572 -0
  12. package/dist/cli/daemon.js.map +1 -0
  13. package/dist/cli/index.js +90 -16
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/cli/init.d.ts +13 -0
  16. package/dist/cli/init.d.ts.map +1 -0
  17. package/dist/cli/init.js +352 -0
  18. package/dist/cli/init.js.map +1 -0
  19. package/dist/core/e2ee-crypto.d.ts +127 -1
  20. package/dist/core/e2ee-crypto.d.ts.map +1 -1
  21. package/dist/core/e2ee-crypto.js +446 -12
  22. package/dist/core/e2ee-crypto.js.map +1 -1
  23. package/dist/core/f2a.d.ts +2 -1
  24. package/dist/core/f2a.d.ts.map +1 -1
  25. package/dist/core/f2a.js +6 -2
  26. package/dist/core/f2a.js.map +1 -1
  27. package/dist/core/identity/encrypted-key-store.d.ts +19 -0
  28. package/dist/core/identity/encrypted-key-store.d.ts.map +1 -0
  29. package/dist/core/identity/encrypted-key-store.js +72 -0
  30. package/dist/core/identity/encrypted-key-store.js.map +1 -0
  31. package/dist/core/identity/identity-manager.d.ts +133 -0
  32. package/dist/core/identity/identity-manager.d.ts.map +1 -0
  33. package/dist/core/identity/identity-manager.js +454 -0
  34. package/dist/core/identity/identity-manager.js.map +1 -0
  35. package/dist/core/identity/index.d.ts +8 -0
  36. package/dist/core/identity/index.d.ts.map +1 -0
  37. package/dist/core/identity/index.js +7 -0
  38. package/dist/core/identity/index.js.map +1 -0
  39. package/dist/core/identity/types.d.ts +70 -0
  40. package/dist/core/identity/types.d.ts.map +1 -0
  41. package/dist/core/identity/types.js +17 -0
  42. package/dist/core/identity/types.js.map +1 -0
  43. package/dist/core/p2p-network.d.ts +26 -0
  44. package/dist/core/p2p-network.d.ts.map +1 -1
  45. package/dist/core/p2p-network.js +434 -105
  46. package/dist/core/p2p-network.js.map +1 -1
  47. package/dist/core/reputation-security.d.ts +15 -0
  48. package/dist/core/reputation-security.d.ts.map +1 -1
  49. package/dist/core/reputation-security.js +73 -3
  50. package/dist/core/reputation-security.js.map +1 -1
  51. package/dist/core/reputation.d.ts +129 -4
  52. package/dist/core/reputation.d.ts.map +1 -1
  53. package/dist/core/reputation.js +294 -1
  54. package/dist/core/reputation.js.map +1 -1
  55. package/dist/core/review-committee.d.ts +2 -2
  56. package/dist/core/review-committee.d.ts.map +1 -1
  57. package/dist/core/review-committee.js +17 -0
  58. package/dist/core/review-committee.js.map +1 -1
  59. package/dist/daemon/control-server.d.ts.map +1 -1
  60. package/dist/daemon/control-server.js +44 -1
  61. package/dist/daemon/control-server.js.map +1 -1
  62. package/dist/daemon/webhook.d.ts +3 -0
  63. package/dist/daemon/webhook.d.ts.map +1 -1
  64. package/dist/daemon/webhook.js +318 -6
  65. package/dist/daemon/webhook.js.map +1 -1
  66. package/dist/index.d.ts +3 -3
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +7 -3
  69. package/dist/index.js.map +1 -1
  70. package/dist/types/index.d.ts +4 -0
  71. package/dist/types/index.d.ts.map +1 -1
  72. package/dist/types/index.js.map +1 -1
  73. package/dist/types/result.d.ts +1 -1
  74. package/dist/types/result.d.ts.map +1 -1
  75. package/dist/types/result.js.map +1 -1
  76. package/dist/utils/crypto-utils.d.ts +17 -0
  77. package/dist/utils/crypto-utils.d.ts.map +1 -0
  78. package/dist/utils/crypto-utils.js +28 -0
  79. package/dist/utils/crypto-utils.js.map +1 -0
  80. package/dist/utils/logger.d.ts +1 -0
  81. package/dist/utils/logger.d.ts.map +1 -1
  82. package/dist/utils/logger.js +9 -3
  83. package/dist/utils/logger.js.map +1 -1
  84. package/dist/utils/rate-limiter.d.ts.map +1 -1
  85. package/dist/utils/rate-limiter.js +3 -1
  86. package/dist/utils/rate-limiter.js.map +1 -1
  87. package/dist/utils/signature.d.ts +47 -1
  88. package/dist/utils/signature.d.ts.map +1 -1
  89. package/dist/utils/signature.js +166 -11
  90. package/dist/utils/signature.js.map +1 -1
  91. package/package.json +9 -1
  92. package/.github/workflows/ci.yml +0 -113
  93. package/.github/workflows/publish.yml +0 -60
  94. package/MONOREPO.md +0 -58
  95. package/SKILL.md +0 -137
  96. package/dist/adapters/openclaw.d.ts +0 -103
  97. package/dist/adapters/openclaw.d.ts.map +0 -1
  98. package/dist/adapters/openclaw.js +0 -297
  99. package/dist/adapters/openclaw.js.map +0 -1
  100. package/dist/core/connection-manager.d.ts +0 -80
  101. package/dist/core/connection-manager.d.ts.map +0 -1
  102. package/dist/core/connection-manager.js +0 -235
  103. package/dist/core/connection-manager.js.map +0 -1
  104. package/dist/core/connection-manager.test.d.ts +0 -2
  105. package/dist/core/connection-manager.test.d.ts.map +0 -1
  106. package/dist/core/connection-manager.test.js +0 -52
  107. package/dist/core/connection-manager.test.js.map +0 -1
  108. package/dist/core/identity.d.ts +0 -47
  109. package/dist/core/identity.d.ts.map +0 -1
  110. package/dist/core/identity.js +0 -130
  111. package/dist/core/identity.js.map +0 -1
  112. package/dist/core/identity.test.d.ts +0 -2
  113. package/dist/core/identity.test.d.ts.map +0 -1
  114. package/dist/core/identity.test.js +0 -43
  115. package/dist/core/identity.test.js.map +0 -1
  116. package/dist/core/serverless.d.ts +0 -155
  117. package/dist/core/serverless.d.ts.map +0 -1
  118. package/dist/core/serverless.js +0 -615
  119. package/dist/core/serverless.js.map +0 -1
  120. package/dist/daemon/webhook.test.d.ts +0 -2
  121. package/dist/daemon/webhook.test.d.ts.map +0 -1
  122. package/dist/daemon/webhook.test.js +0 -24
  123. package/dist/daemon/webhook.test.js.map +0 -1
  124. package/dist/protocol/messages.d.ts +0 -739
  125. package/dist/protocol/messages.d.ts.map +0 -1
  126. package/dist/protocol/messages.js +0 -188
  127. package/dist/protocol/messages.js.map +0 -1
  128. package/dist/protocol/messages.test.d.ts +0 -2
  129. package/dist/protocol/messages.test.d.ts.map +0 -1
  130. package/dist/protocol/messages.test.js +0 -55
  131. package/dist/protocol/messages.test.js.map +0 -1
  132. package/docs/F2A-PROTOCOL.md +0 -61
  133. package/docs/MOBILE_BOOTSTRAP_DESIGN.md +0 -126
  134. package/docs/a2a-lessons.md +0 -316
  135. package/docs/middleware-guide.md +0 -448
  136. package/docs/readme-update-checklist.md +0 -90
  137. package/docs/reputation-guide.md +0 -396
  138. package/docs/rfcs/001-reputation-system.md +0 -712
  139. package/docs/security-design.md +0 -247
  140. package/install.sh +0 -231
  141. package/packages/openclaw-adapter/README.md +0 -510
  142. package/packages/openclaw-adapter/openclaw.plugin.json +0 -106
  143. package/packages/openclaw-adapter/package.json +0 -40
  144. package/packages/openclaw-adapter/src/announcement-queue.test.ts +0 -449
  145. package/packages/openclaw-adapter/src/announcement-queue.ts +0 -403
  146. package/packages/openclaw-adapter/src/capability-detector.test.ts +0 -99
  147. package/packages/openclaw-adapter/src/capability-detector.ts +0 -183
  148. package/packages/openclaw-adapter/src/claim-handlers.test.ts +0 -974
  149. package/packages/openclaw-adapter/src/claim-handlers.ts +0 -482
  150. package/packages/openclaw-adapter/src/connector.business.test.ts +0 -583
  151. package/packages/openclaw-adapter/src/connector.ts +0 -795
  152. package/packages/openclaw-adapter/src/index.test.ts +0 -82
  153. package/packages/openclaw-adapter/src/index.ts +0 -18
  154. package/packages/openclaw-adapter/src/integration.e2e.test.ts +0 -829
  155. package/packages/openclaw-adapter/src/logger.ts +0 -51
  156. package/packages/openclaw-adapter/src/network-client.test.ts +0 -266
  157. package/packages/openclaw-adapter/src/network-client.ts +0 -251
  158. package/packages/openclaw-adapter/src/network-recovery.test.ts +0 -465
  159. package/packages/openclaw-adapter/src/node-manager.test.ts +0 -136
  160. package/packages/openclaw-adapter/src/node-manager.ts +0 -429
  161. package/packages/openclaw-adapter/src/plugin.test.ts +0 -439
  162. package/packages/openclaw-adapter/src/plugin.ts +0 -104
  163. package/packages/openclaw-adapter/src/reputation.test.ts +0 -221
  164. package/packages/openclaw-adapter/src/reputation.ts +0 -368
  165. package/packages/openclaw-adapter/src/task-guard.test.ts +0 -502
  166. package/packages/openclaw-adapter/src/task-guard.ts +0 -860
  167. package/packages/openclaw-adapter/src/task-queue.concurrency.test.ts +0 -462
  168. package/packages/openclaw-adapter/src/task-queue.edge-cases.test.ts +0 -284
  169. package/packages/openclaw-adapter/src/task-queue.persistence.test.ts +0 -408
  170. package/packages/openclaw-adapter/src/task-queue.ts +0 -668
  171. package/packages/openclaw-adapter/src/tool-handlers.test.ts +0 -906
  172. package/packages/openclaw-adapter/src/tool-handlers.ts +0 -574
  173. package/packages/openclaw-adapter/src/types.ts +0 -361
  174. package/packages/openclaw-adapter/src/webhook-pusher.test.ts +0 -188
  175. package/packages/openclaw-adapter/src/webhook-pusher.ts +0 -220
  176. package/packages/openclaw-adapter/src/webhook-server.test.ts +0 -580
  177. package/packages/openclaw-adapter/src/webhook-server.ts +0 -202
  178. package/packages/openclaw-adapter/tsconfig.json +0 -20
  179. package/src/cli/commands.test.ts +0 -157
  180. package/src/cli/commands.ts +0 -129
  181. package/src/cli/index.test.ts +0 -77
  182. package/src/cli/index.ts +0 -234
  183. package/src/core/autonomous-economy.test.ts +0 -291
  184. package/src/core/autonomous-economy.ts +0 -428
  185. package/src/core/e2ee-crypto.test.ts +0 -125
  186. package/src/core/e2ee-crypto.ts +0 -246
  187. package/src/core/f2a.test.ts +0 -269
  188. package/src/core/f2a.ts +0 -618
  189. package/src/core/p2p-network.test.ts +0 -199
  190. package/src/core/p2p-network.ts +0 -1432
  191. package/src/core/reputation-security.test.ts +0 -403
  192. package/src/core/reputation-security.ts +0 -562
  193. package/src/core/reputation.test.ts +0 -260
  194. package/src/core/reputation.ts +0 -576
  195. package/src/core/review-committee.test.ts +0 -380
  196. package/src/core/review-committee.ts +0 -401
  197. package/src/core/token-manager.test.ts +0 -133
  198. package/src/core/token-manager.ts +0 -140
  199. package/src/daemon/control-server.test.ts +0 -216
  200. package/src/daemon/control-server.ts +0 -292
  201. package/src/daemon/index.test.ts +0 -85
  202. package/src/daemon/index.ts +0 -89
  203. package/src/daemon/main.ts +0 -44
  204. package/src/daemon/start.ts +0 -29
  205. package/src/daemon/webhook.test.ts +0 -68
  206. package/src/daemon/webhook.ts +0 -105
  207. package/src/index.test.ts +0 -436
  208. package/src/index.ts +0 -72
  209. package/src/types/index.test.ts +0 -87
  210. package/src/types/index.ts +0 -341
  211. package/src/types/result.ts +0 -68
  212. package/src/utils/benchmark.ts +0 -237
  213. package/src/utils/logger.ts +0 -331
  214. package/src/utils/middleware.ts +0 -229
  215. package/src/utils/rate-limiter.ts +0 -207
  216. package/src/utils/signature.ts +0 -136
  217. package/src/utils/validation.ts +0 -186
  218. package/tests/docker/Dockerfile.node +0 -23
  219. package/tests/docker/Dockerfile.runner +0 -18
  220. package/tests/docker/docker-compose.test.yml +0 -73
  221. package/tests/integration/message-passing.test.ts +0 -109
  222. package/tests/integration/multi-node.test.ts +0 -92
  223. package/tests/integration/p2p-connection.test.ts +0 -83
  224. package/tests/integration/test-config.ts +0 -32
  225. package/tsconfig.json +0 -21
  226. package/vitest.config.ts +0 -26
@@ -1,462 +0,0 @@
1
- /**
2
- * TaskQueue 真实并发测试
3
- * 使用 worker_threads 测试并发访问
4
- */
5
-
6
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
7
- import { TaskQueue } from './task-queue.js';
8
- import { Worker, isMainThread, parentPort, workerData } from 'worker_threads';
9
- import path from 'path';
10
- import fs from 'fs';
11
- import { fileURLToPath } from 'url';
12
-
13
- const __filename = fileURLToPath(import.meta.url);
14
- const __dirname = path.dirname(__filename);
15
-
16
- const TEST_DIR = './test-tmp-concurrency';
17
-
18
- // Worker 脚本内容
19
- const workerScript = `
20
- import { parentPort, workerData } from 'worker_threads';
21
- import { TaskQueue } from './task-queue.js';
22
-
23
- const { action, taskId, persistDir } = workerData;
24
-
25
- const queue = new TaskQueue({
26
- maxSize: 1000,
27
- persistDir: persistDir,
28
- persistEnabled: true
29
- });
30
-
31
- try {
32
- let result;
33
- switch (action) {
34
- case 'add':
35
- result = queue.add({ taskId, taskType: 'concurrent-test', description: 'Test task' });
36
- break;
37
- case 'getPending':
38
- result = queue.getPending(10);
39
- break;
40
- case 'markProcessing':
41
- result = queue.markProcessing(taskId);
42
- break;
43
- case 'complete':
44
- result = queue.complete(taskId, { status: 'success', result: 'done' });
45
- break;
46
- case 'getStats':
47
- result = queue.getStats();
48
- break;
49
- default:
50
- throw new Error('Unknown action: ' + action);
51
- }
52
- parentPort.postMessage({ success: true, result });
53
- } catch (error) {
54
- parentPort.postMessage({ success: false, error: error.message });
55
- } finally {
56
- queue.close();
57
- }
58
- `;
59
-
60
- describe('TaskQueue 真实并发测试', () => {
61
- let queue: TaskQueue;
62
-
63
- beforeEach(() => {
64
- if (!fs.existsSync(TEST_DIR)) {
65
- fs.mkdirSync(TEST_DIR, { recursive: true });
66
- }
67
- queue = new TaskQueue({
68
- maxSize: 1000,
69
- persistDir: TEST_DIR,
70
- persistEnabled: true
71
- });
72
- });
73
-
74
- afterEach(() => {
75
- queue.close();
76
- if (fs.existsSync(TEST_DIR)) {
77
- fs.rmSync(TEST_DIR, { recursive: true });
78
- }
79
- });
80
-
81
- describe('使用 Promise.all 测试并发', () => {
82
- it('应该正确处理并发添加 100 个任务', async () => {
83
- const promises = [];
84
-
85
- for (let i = 0; i < 100; i++) {
86
- promises.push(
87
- new Promise<void>((resolve) => {
88
- // 模拟异步操作
89
- setImmediate(() => {
90
- queue.add({ taskId: `task-${i}`, taskType: 'concurrent' });
91
- resolve();
92
- });
93
- })
94
- );
95
- }
96
-
97
- await Promise.all(promises);
98
-
99
- const stats = queue.getStats();
100
- expect(stats.total).toBe(100);
101
- expect(stats.pending).toBe(100);
102
- });
103
-
104
- it('应该正确处理并发 add 和 getPending', async () => {
105
- const addPromises: Promise<void>[] = [];
106
- const getPromises: Promise<void>[] = [];
107
-
108
- // 同时添加和获取
109
- for (let i = 0; i < 50; i++) {
110
- addPromises.push(
111
- new Promise<void>((resolve) => {
112
- setImmediate(() => {
113
- queue.add({ taskId: `task-${i}`, taskType: 'race-test' });
114
- resolve();
115
- });
116
- })
117
- );
118
-
119
- getPromises.push(
120
- new Promise<void>((resolve) => {
121
- setImmediate(() => {
122
- queue.getPending();
123
- resolve();
124
- });
125
- })
126
- );
127
- }
128
-
129
- await Promise.all([...addPromises, ...getPromises]);
130
-
131
- const stats = queue.getStats();
132
- expect(stats.total).toBe(50);
133
- });
134
-
135
- it('应该正确处理并发 markProcessing', async () => {
136
- // 先添加任务
137
- for (let i = 0; i < 20; i++) {
138
- queue.add({ taskId: `task-${i}`, taskType: 'processing-test' });
139
- }
140
-
141
- const promises = [];
142
- for (let i = 0; i < 20; i++) {
143
- promises.push(
144
- new Promise<void>((resolve) => {
145
- setImmediate(() => {
146
- queue.markProcessing(`task-${i}`);
147
- resolve();
148
- });
149
- })
150
- );
151
- }
152
-
153
- await Promise.all(promises);
154
-
155
- const stats = queue.getStats();
156
- expect(stats.processing).toBe(20);
157
- });
158
-
159
- it('应该正确处理并发 complete', async () => {
160
- // 先添加任务
161
- for (let i = 0; i < 30; i++) {
162
- queue.add({ taskId: `task-${i}`, taskType: 'complete-test' });
163
- }
164
-
165
- const promises = [];
166
- for (let i = 0; i < 30; i++) {
167
- promises.push(
168
- new Promise<void>((resolve) => {
169
- setImmediate(() => {
170
- queue.complete(`task-${i}`, { status: 'success', result: `result-${i}` });
171
- resolve();
172
- });
173
- })
174
- );
175
- }
176
-
177
- await Promise.all(promises);
178
-
179
- const stats = queue.getStats();
180
- expect(stats.completed).toBe(30);
181
- });
182
- });
183
-
184
- describe('竞态条件测试', () => {
185
- it('应该正确处理 add 和 delete 的竞态', async () => {
186
- // 先添加一些任务
187
- for (let i = 0; i < 50; i++) {
188
- queue.add({ taskId: `task-${i}`, taskType: 'race-delete' });
189
- }
190
-
191
- const addPromises: Promise<void>[] = [];
192
- const deletePromises: Promise<void>[] = [];
193
-
194
- // 添加新任务
195
- for (let i = 50; i < 100; i++) {
196
- addPromises.push(
197
- new Promise<void>((resolve) => {
198
- setImmediate(() => {
199
- try {
200
- queue.add({ taskId: `task-${i}`, taskType: 'race-delete' });
201
- } catch (e) {
202
- // 忽略错误
203
- }
204
- resolve();
205
- });
206
- })
207
- );
208
- }
209
-
210
- // 同时删除旧任务
211
- for (let i = 0; i < 50; i++) {
212
- deletePromises.push(
213
- new Promise<void>((resolve) => {
214
- setImmediate(() => {
215
- queue.delete(`task-${i}`);
216
- resolve();
217
- });
218
- })
219
- );
220
- }
221
-
222
- await Promise.all([...addPromises, ...deletePromises]);
223
-
224
- // 最终队列应该有 50 个任务(新添加的)
225
- const stats = queue.getStats();
226
- expect(stats.total).toBe(50);
227
- });
228
-
229
- it('应该正确处理同一任务的并发操作', async () => {
230
- queue.add({ taskId: 'concurrent-task', taskType: 'same-task' });
231
-
232
- const promises = [
233
- // 同时进行多种操作
234
- new Promise<void>((resolve) => {
235
- setImmediate(() => {
236
- queue.markProcessing('concurrent-task');
237
- resolve();
238
- });
239
- }),
240
- new Promise<void>((resolve) => {
241
- setImmediate(() => {
242
- queue.complete('concurrent-task', { status: 'success', result: 'done' });
243
- resolve();
244
- });
245
- }),
246
- new Promise<void>((resolve) => {
247
- setImmediate(() => {
248
- queue.get('concurrent-task');
249
- resolve();
250
- });
251
- }),
252
- ];
253
-
254
- await Promise.all(promises);
255
-
256
- // 任务最终应该处于某个一致状态
257
- const task = queue.get('concurrent-task');
258
- expect(task).toBeDefined();
259
- expect(['processing', 'completed']).toContain(task?.status);
260
- });
261
- });
262
-
263
- describe('使用 setImmediate 模拟时间片', () => {
264
- it('应该在高并发下保持数据一致性', async () => {
265
- const operations: Promise<void>[] = [];
266
-
267
- // 创建大量并发操作
268
- for (let round = 0; round < 5; round++) {
269
- for (let i = 0; i < 20; i++) {
270
- const taskId = `task-${round}-${i}`;
271
- operations.push(
272
- new Promise<void>((resolve) => {
273
- setImmediate(() => {
274
- queue.add({ taskId, taskType: 'high-concurrency' });
275
- resolve();
276
- });
277
- })
278
- );
279
- }
280
- }
281
-
282
- await Promise.all(operations);
283
-
284
- // 验证数据一致性
285
- const stats = queue.getStats();
286
- expect(stats.total).toBe(100);
287
-
288
- // 验证每个任务都能被正确获取
289
- for (let round = 0; round < 5; round++) {
290
- for (let i = 0; i < 20; i++) {
291
- const taskId = `task-${round}-${i}`;
292
- const task = queue.get(taskId);
293
- expect(task).toBeDefined();
294
- expect(task?.status).toBe('pending');
295
- }
296
- }
297
- });
298
-
299
- it('应该在并发清理下保持稳定', async () => {
300
- const shortLivedQueue = new TaskQueue({
301
- maxSize: 1000,
302
- maxAgeMs: 100, // 100ms 过期
303
- persistDir: TEST_DIR,
304
- persistEnabled: true
305
- });
306
-
307
- // 添加任务
308
- for (let i = 0; i < 50; i++) {
309
- shortLivedQueue.add({ taskId: `expiring-${i}`, taskType: 'cleanup-test' });
310
- }
311
-
312
- // 等待任务过期
313
- await new Promise(r => setTimeout(r, 150));
314
-
315
- // 并发触发清理(通过添加新任务)
316
- const promises: Promise<void>[] = [];
317
- for (let i = 0; i < 20; i++) {
318
- promises.push(
319
- new Promise<void>((resolve) => {
320
- setImmediate(() => {
321
- shortLivedQueue.add({ taskId: `new-${i}`, taskType: 'cleanup-test' });
322
- resolve();
323
- });
324
- })
325
- );
326
- }
327
-
328
- await Promise.all(promises);
329
-
330
- const stats = shortLivedQueue.getStats();
331
- // 新任务应该存在,旧任务应该被清理
332
- expect(stats.total).toBe(20);
333
-
334
- shortLivedQueue.close();
335
- });
336
- });
337
-
338
- describe('事务原子性测试', () => {
339
- it('应该在事务失败时回滚', async () => {
340
- // 填满队列
341
- for (let i = 0; i < 1000; i++) {
342
- queue.add({ taskId: `fill-${i}`, taskType: 'fill' });
343
- }
344
-
345
- const failedAdds: Promise<void>[] = [];
346
- const successfulAdds: Promise<void>[] = [];
347
-
348
- // 尝试在满队列上添加任务(应该失败)
349
- for (let i = 0; i < 10; i++) {
350
- failedAdds.push(
351
- new Promise<void>((resolve) => {
352
- setImmediate(() => {
353
- try {
354
- queue.add({ taskId: `overflow-${i}`, taskType: 'overflow' });
355
- } catch (e) {
356
- // 预期会失败
357
- }
358
- resolve();
359
- });
360
- })
361
- );
362
- }
363
-
364
- await Promise.all(failedAdds);
365
-
366
- // 队列大小应该保持 1000
367
- const stats = queue.getStats();
368
- expect(stats.total).toBe(1000);
369
- });
370
-
371
- it('应该在并发删除和查询时保持一致性', async () => {
372
- for (let i = 0; i < 50; i++) {
373
- queue.add({ taskId: `delete-test-${i}`, taskType: 'delete' });
374
- }
375
-
376
- const deletePromises: Promise<void>[] = [];
377
- const getPromises: Promise<void>[] = [];
378
-
379
- for (let i = 0; i < 50; i++) {
380
- const taskId = `delete-test-${i}`;
381
-
382
- deletePromises.push(
383
- new Promise<void>((resolve) => {
384
- setImmediate(() => {
385
- queue.delete(taskId);
386
- resolve();
387
- });
388
- })
389
- );
390
-
391
- getPromises.push(
392
- new Promise<void>((resolve) => {
393
- setImmediate(() => {
394
- queue.get(taskId);
395
- resolve();
396
- });
397
- })
398
- );
399
- }
400
-
401
- await Promise.all([...deletePromises, ...getPromises]);
402
-
403
- // 所有任务应该被删除
404
- const stats = queue.getStats();
405
- expect(stats.total).toBe(0);
406
- });
407
- });
408
-
409
- describe('Webhook 相关并发测试', () => {
410
- it('应该正确处理并发 markWebhookPushed', async () => {
411
- for (let i = 0; i < 20; i++) {
412
- queue.add({ taskId: `webhook-${i}`, taskType: 'webhook' });
413
- }
414
-
415
- const promises: Promise<void>[] = [];
416
- for (let i = 0; i < 20; i++) {
417
- promises.push(
418
- new Promise<void>((resolve) => {
419
- setImmediate(() => {
420
- queue.markWebhookPushed(`webhook-${i}`);
421
- resolve();
422
- });
423
- })
424
- );
425
- }
426
-
427
- await Promise.all(promises);
428
-
429
- const webhookPending = queue.getWebhookPending();
430
- expect(webhookPending.length).toBe(0);
431
- });
432
-
433
- it('应该在并发 getWebhookPending 时保持一致性', async () => {
434
- for (let i = 0; i < 30; i++) {
435
- queue.add({ taskId: `concurrent-webhook-${i}`, taskType: 'webhook' });
436
- }
437
-
438
- const promises: Promise<unknown>[] = [];
439
-
440
- // 并发获取和标记
441
- for (let i = 0; i < 30; i++) {
442
- promises.push(
443
- new Promise((resolve) => {
444
- setImmediate(() => {
445
- const pending = queue.getWebhookPending();
446
- if (pending.length > 0) {
447
- queue.markWebhookPushed(pending[0].taskId);
448
- }
449
- resolve(pending.length);
450
- });
451
- })
452
- );
453
- }
454
-
455
- const results = await Promise.all(promises);
456
-
457
- // 最终所有任务都应该被标记
458
- const finalPending = queue.getWebhookPending();
459
- expect(finalPending.length).toBe(0);
460
- });
461
- });
462
- });