@winspan/claude-forge 1.16.15 → 1.17.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.
- package/README.md +11 -11
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +8 -0
- package/dist/daemon/index.js.map +1 -1
- package/dist/pipeline/aggregator.d.ts +118 -0
- package/dist/pipeline/aggregator.d.ts.map +1 -0
- package/dist/pipeline/aggregator.js +252 -0
- package/dist/pipeline/aggregator.js.map +1 -0
- package/dist/pipeline/event-sourced-engine.d.ts +77 -0
- package/dist/pipeline/event-sourced-engine.d.ts.map +1 -0
- package/dist/pipeline/event-sourced-engine.js +266 -0
- package/dist/pipeline/event-sourced-engine.js.map +1 -0
- package/dist/pipeline/event-store.d.ts +58 -0
- package/dist/pipeline/event-store.d.ts.map +1 -0
- package/dist/pipeline/event-store.js +184 -0
- package/dist/pipeline/event-store.js.map +1 -0
- package/dist/pipeline/events.d.ts +166 -0
- package/dist/pipeline/events.d.ts.map +1 -0
- package/dist/pipeline/events.js +29 -0
- package/dist/pipeline/events.js.map +1 -0
- package/dist/pipeline/optimized-aggregator.d.ts +36 -0
- package/dist/pipeline/optimized-aggregator.d.ts.map +1 -0
- package/dist/pipeline/optimized-aggregator.js +93 -0
- package/dist/pipeline/optimized-aggregator.js.map +1 -0
- package/dist/pipeline/progress-tracker.d.ts +29 -0
- package/dist/pipeline/progress-tracker.d.ts.map +1 -0
- package/dist/pipeline/progress-tracker.js +99 -0
- package/dist/pipeline/progress-tracker.js.map +1 -0
- package/dist/pipeline/snapshot-store.d.ts +45 -0
- package/dist/pipeline/snapshot-store.d.ts.map +1 -0
- package/dist/pipeline/snapshot-store.js +89 -0
- package/dist/pipeline/snapshot-store.js.map +1 -0
- package/dist/pipeline/state-machine-types.d.ts +156 -0
- package/dist/pipeline/state-machine-types.d.ts.map +1 -0
- package/dist/pipeline/state-machine-types.js +7 -0
- package/dist/pipeline/state-machine-types.js.map +1 -0
- package/dist/pipeline/state-machine.d.ts +44 -0
- package/dist/pipeline/state-machine.d.ts.map +1 -0
- package/dist/pipeline/state-machine.js +203 -0
- package/dist/pipeline/state-machine.js.map +1 -0
- package/dist/pipeline/state-query.d.ts +71 -0
- package/dist/pipeline/state-query.d.ts.map +1 -0
- package/dist/pipeline/state-query.js +192 -0
- package/dist/pipeline/state-query.js.map +1 -0
- package/dist/pipeline/store.d.ts +12 -17
- package/dist/pipeline/store.d.ts.map +1 -1
- package/dist/pipeline/store.js +214 -110
- package/dist/pipeline/store.js.map +1 -1
- package/dist/pipeline/store.legacy.d.ts +48 -0
- package/dist/pipeline/store.legacy.d.ts.map +1 -0
- package/dist/pipeline/store.legacy.js +163 -0
- package/dist/pipeline/store.legacy.js.map +1 -0
- package/dist/pipeline/transitions.d.ts +28 -0
- package/dist/pipeline/transitions.d.ts.map +1 -0
- package/dist/pipeline/transitions.js +336 -0
- package/dist/pipeline/transitions.js.map +1 -0
- package/dist/scripts/auto-migrate.d.ts +9 -0
- package/dist/scripts/auto-migrate.d.ts.map +1 -0
- package/dist/scripts/auto-migrate.js +161 -0
- package/dist/scripts/auto-migrate.js.map +1 -0
- package/dist/scripts/migrate-to-event-sourcing.d.ts +16 -0
- package/dist/scripts/migrate-to-event-sourcing.d.ts.map +1 -0
- package/dist/scripts/migrate-to-event-sourcing.js +179 -0
- package/dist/scripts/migrate-to-event-sourcing.js.map +1 -0
- package/dist/web-static/assets/{index-Tbfb5BBI.js → index-BmOm81pb.js} +1 -1
- package/dist/web-static/index.html +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline 事件溯源 + 状态机 集成示例
|
|
3
|
+
*
|
|
4
|
+
* 展示如何使用新架构替代旧的 PipelineEngine
|
|
5
|
+
*/
|
|
6
|
+
import { EventStore } from './event-store.js';
|
|
7
|
+
import { SnapshotStore } from './snapshot-store.js';
|
|
8
|
+
import { OptimizedAggregator } from './optimized-aggregator.js';
|
|
9
|
+
import { PipelineStateMachine } from './state-machine.js';
|
|
10
|
+
import { PipelineStateQuery } from './state-query.js';
|
|
11
|
+
import { PipelineEventType } from './events.js';
|
|
12
|
+
/**
|
|
13
|
+
* 新架构的 Pipeline 引擎
|
|
14
|
+
*/
|
|
15
|
+
export class EventSourcedPipelineEngine {
|
|
16
|
+
eventStore;
|
|
17
|
+
snapshotStore;
|
|
18
|
+
aggregator;
|
|
19
|
+
stateMachine;
|
|
20
|
+
stateQuery;
|
|
21
|
+
constructor(dbPath) {
|
|
22
|
+
// 初始化各个组件
|
|
23
|
+
this.eventStore = new EventStore(dbPath);
|
|
24
|
+
this.snapshotStore = new SnapshotStore(dbPath);
|
|
25
|
+
this.aggregator = new OptimizedAggregator(this.eventStore, this.snapshotStore);
|
|
26
|
+
this.stateMachine = new PipelineStateMachine(this.eventStore, this.aggregator);
|
|
27
|
+
this.stateQuery = new PipelineStateQuery(this.aggregator, this.eventStore, this.stateMachine);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 创建 Pipeline
|
|
31
|
+
*/
|
|
32
|
+
async createPipeline(params) {
|
|
33
|
+
const pipelineId = `pipeline-${Date.now()}`;
|
|
34
|
+
// 生成 PIPELINE_CREATED 事件
|
|
35
|
+
this.eventStore.append({
|
|
36
|
+
pipelineId,
|
|
37
|
+
type: PipelineEventType.PIPELINE_CREATED,
|
|
38
|
+
payload: {
|
|
39
|
+
requirement: params.requirement,
|
|
40
|
+
projectPath: params.projectPath,
|
|
41
|
+
sessionId: params.sessionId,
|
|
42
|
+
techStack: params.techStack,
|
|
43
|
+
complexity: params.complexity,
|
|
44
|
+
taskType: 'feature',
|
|
45
|
+
plannedPhases: params.plannedPhases,
|
|
46
|
+
},
|
|
47
|
+
metadata: {
|
|
48
|
+
sessionId: params.sessionId,
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
return pipelineId;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 添加任务
|
|
55
|
+
*/
|
|
56
|
+
async addTask(pipelineId, task) {
|
|
57
|
+
this.eventStore.append({
|
|
58
|
+
pipelineId,
|
|
59
|
+
type: PipelineEventType.TASK_CREATED,
|
|
60
|
+
payload: {
|
|
61
|
+
taskId: task.id,
|
|
62
|
+
title: task.title,
|
|
63
|
+
phase: task.phase,
|
|
64
|
+
description: task.description,
|
|
65
|
+
source: 'manual',
|
|
66
|
+
},
|
|
67
|
+
metadata: {
|
|
68
|
+
sessionId: '',
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 标记任务完成
|
|
74
|
+
*/
|
|
75
|
+
async completeTask(pipelineId, taskId, artifact) {
|
|
76
|
+
this.eventStore.append({
|
|
77
|
+
pipelineId,
|
|
78
|
+
type: PipelineEventType.TASK_COMPLETED,
|
|
79
|
+
payload: {
|
|
80
|
+
taskId,
|
|
81
|
+
title: '',
|
|
82
|
+
phase: '',
|
|
83
|
+
artifact,
|
|
84
|
+
detectionMethod: 'explicit_signal',
|
|
85
|
+
},
|
|
86
|
+
metadata: {
|
|
87
|
+
sessionId: '',
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
// 检查是否所有任务完成
|
|
91
|
+
const pipeline = this.aggregator.rebuild(pipelineId);
|
|
92
|
+
if (!pipeline)
|
|
93
|
+
return;
|
|
94
|
+
const phaseTasks = pipeline.tasks.filter(t => t.phase === pipeline.phase);
|
|
95
|
+
const completed = phaseTasks.filter(t => t.status === 'completed').length;
|
|
96
|
+
if (completed === phaseTasks.length && phaseTasks.length > 0) {
|
|
97
|
+
// 触发质量检查
|
|
98
|
+
await this.stateMachine.transition(pipelineId, {
|
|
99
|
+
type: 'ALL_TASKS_COMPLETED',
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* 质量检查通过
|
|
105
|
+
*/
|
|
106
|
+
async qualityCheckPassed(pipelineId, level) {
|
|
107
|
+
await this.stateMachine.transition(pipelineId, {
|
|
108
|
+
type: 'QUALITY_CHECK_PASSED',
|
|
109
|
+
level,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* 质量检查失败
|
|
114
|
+
*/
|
|
115
|
+
async qualityCheckFailed(pipelineId, issues, fixAttempt) {
|
|
116
|
+
if (fixAttempt >= 2) {
|
|
117
|
+
// 达到最大次数,强制放行
|
|
118
|
+
await this.stateMachine.transition(pipelineId, {
|
|
119
|
+
type: 'QUALITY_MAX_ATTEMPTS_REACHED',
|
|
120
|
+
unresolvedIssues: issues,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
// 阻塞并等待修复
|
|
125
|
+
await this.stateMachine.transition(pipelineId, {
|
|
126
|
+
type: 'QUALITY_CHECK_FAILED',
|
|
127
|
+
issues,
|
|
128
|
+
fixAttempt,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* 手动推进阶段(强制放行后)
|
|
134
|
+
*/
|
|
135
|
+
async manualAdvance(pipelineId, reason) {
|
|
136
|
+
await this.stateMachine.transition(pipelineId, {
|
|
137
|
+
type: 'MANUAL_ADVANCE',
|
|
138
|
+
reason,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* 获取进度快照
|
|
143
|
+
*/
|
|
144
|
+
getProgressSnapshot(pipelineId) {
|
|
145
|
+
const pipeline = this.aggregator.rebuild(pipelineId);
|
|
146
|
+
if (!pipeline)
|
|
147
|
+
return 'Pipeline not found';
|
|
148
|
+
const state = this.stateQuery.getCurrentState(pipelineId);
|
|
149
|
+
if (!state)
|
|
150
|
+
return 'State not found';
|
|
151
|
+
const progress = this.aggregator.getPhaseProgress(pipelineId, state.phase);
|
|
152
|
+
const globalProgress = this.aggregator.getGlobalProgress(pipelineId);
|
|
153
|
+
const phaseLabel = this.getPhaseLabel(state.phase);
|
|
154
|
+
const statusEmoji = this.getStatusEmoji(state.status);
|
|
155
|
+
const progressBar = this.renderProgressBar(progress.completed, progress.total);
|
|
156
|
+
let snapshot = `#${pipelineId.slice(0, 8)} ${phaseLabel} ${progress.completed}/${progress.total} [${progressBar}] 全局${globalProgress.percentage}%`;
|
|
157
|
+
// 添加状态标记
|
|
158
|
+
if (state.status === 'quality_checking') {
|
|
159
|
+
snapshot += '\n 🚦 阶段状态: 🔍 质量检查中...';
|
|
160
|
+
}
|
|
161
|
+
else if (state.status === 'quality_blocked') {
|
|
162
|
+
const fixAttempt = state.fixAttempt || 1;
|
|
163
|
+
snapshot += `\n 🚦 阶段状态: ⚠️ 待修复 (第${fixAttempt}次)`;
|
|
164
|
+
const blockReason = this.stateQuery.getBlockReason(pipelineId);
|
|
165
|
+
if (blockReason) {
|
|
166
|
+
snapshot += `\n ${blockReason}`;
|
|
167
|
+
}
|
|
168
|
+
snapshot += '\n ⏸️ 阶段推进已暂停,修复后将自动继续';
|
|
169
|
+
}
|
|
170
|
+
else if (state.status === 'quality_forced_pass') {
|
|
171
|
+
snapshot += '\n 🚦 阶段状态: 🟡 强制放行(质量不达标)';
|
|
172
|
+
snapshot += '\n ⚠️ 请手动确认产物质量后,使用 MANUAL_ADVANCE 推进阶段';
|
|
173
|
+
}
|
|
174
|
+
// 添加任务列表
|
|
175
|
+
const phaseTasks = pipeline.tasks.filter(t => t.phase === state.phase);
|
|
176
|
+
if (phaseTasks.length > 0) {
|
|
177
|
+
snapshot += '\n' + phaseTasks.map(t => {
|
|
178
|
+
const icon = t.status === 'completed' ? '✅' : t.status === 'in_progress' ? '▶' : '○';
|
|
179
|
+
return ` ${icon} ${t.title}`;
|
|
180
|
+
}).join('\n');
|
|
181
|
+
}
|
|
182
|
+
return snapshot;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* 获取状态历史
|
|
186
|
+
*/
|
|
187
|
+
getStateHistory(pipelineId) {
|
|
188
|
+
return this.stateQuery.getStateHistory(pipelineId);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* 获取质量门禁统计
|
|
192
|
+
*/
|
|
193
|
+
getQualityStats(pipelineId) {
|
|
194
|
+
return this.stateQuery.getQualityGateStats(pipelineId);
|
|
195
|
+
}
|
|
196
|
+
getPhaseLabel(phase) {
|
|
197
|
+
const labels = {
|
|
198
|
+
analyze: '需求分析',
|
|
199
|
+
design: '架构设计',
|
|
200
|
+
profile: '用户画像',
|
|
201
|
+
code: '编码实现',
|
|
202
|
+
test: '测试',
|
|
203
|
+
review: '代码审查',
|
|
204
|
+
done: '完成',
|
|
205
|
+
};
|
|
206
|
+
return labels[phase] || phase;
|
|
207
|
+
}
|
|
208
|
+
getStatusEmoji(status) {
|
|
209
|
+
switch (status) {
|
|
210
|
+
case 'in_progress': return '▶';
|
|
211
|
+
case 'quality_checking': return '🔍';
|
|
212
|
+
case 'quality_blocked': return '⚠️';
|
|
213
|
+
case 'quality_forced_pass': return '🟡';
|
|
214
|
+
case 'completed': return '✅';
|
|
215
|
+
default: return '○';
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
renderProgressBar(completed, total) {
|
|
219
|
+
if (total === 0)
|
|
220
|
+
return '░░░░░░░░░░';
|
|
221
|
+
const filled = Math.round((completed / total) * 10);
|
|
222
|
+
return '█'.repeat(filled) + '░'.repeat(10 - filled);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* 使用示例
|
|
227
|
+
*/
|
|
228
|
+
export async function example() {
|
|
229
|
+
const engine = new EventSourcedPipelineEngine('./pipeline.db');
|
|
230
|
+
// 1. 创建 Pipeline
|
|
231
|
+
const pipelineId = await engine.createPipeline({
|
|
232
|
+
requirement: '实现用户登录功能',
|
|
233
|
+
projectPath: '/path/to/project',
|
|
234
|
+
sessionId: 'session-123',
|
|
235
|
+
plannedPhases: ['analyze', 'design', 'code', 'test', 'review'],
|
|
236
|
+
});
|
|
237
|
+
console.log('Pipeline 创建:', pipelineId);
|
|
238
|
+
// 2. 添加任务
|
|
239
|
+
await engine.addTask(pipelineId, {
|
|
240
|
+
id: 'task-1',
|
|
241
|
+
title: '分析登录流程',
|
|
242
|
+
phase: 'analyze',
|
|
243
|
+
});
|
|
244
|
+
await engine.addTask(pipelineId, {
|
|
245
|
+
id: 'task-2',
|
|
246
|
+
title: '设计数据库表结构',
|
|
247
|
+
phase: 'analyze',
|
|
248
|
+
});
|
|
249
|
+
// 3. 完成任务
|
|
250
|
+
await engine.completeTask(pipelineId, 'task-1', '登录流程分析完成');
|
|
251
|
+
await engine.completeTask(pipelineId, 'task-2', '数据库表结构设计完成');
|
|
252
|
+
// 此时会自动触发质量检查
|
|
253
|
+
// 4. 质量检查失败
|
|
254
|
+
await engine.qualityCheckFailed(pipelineId, ['缺少安全性分析'], 1);
|
|
255
|
+
console.log('进度快照:', engine.getProgressSnapshot(pipelineId));
|
|
256
|
+
// 5. 修复后重新检查
|
|
257
|
+
await engine.qualityCheckPassed(pipelineId, 'pass');
|
|
258
|
+
console.log('进度快照:', engine.getProgressSnapshot(pipelineId));
|
|
259
|
+
// 6. 查看状态历史
|
|
260
|
+
const history = engine.getStateHistory(pipelineId);
|
|
261
|
+
console.log('状态历史:', history);
|
|
262
|
+
// 7. 查看质量统计
|
|
263
|
+
const stats = engine.getQualityStats(pipelineId);
|
|
264
|
+
console.log('质量统计:', stats);
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=event-sourced-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-sourced-engine.js","sourceRoot":"","sources":["../../src/pipeline/event-sourced-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline 事件存储层
|
|
3
|
+
*
|
|
4
|
+
* 职责:
|
|
5
|
+
* 1. 持久化事件到数据库
|
|
6
|
+
* 2. 按 Pipeline ID 查询事件流
|
|
7
|
+
* 3. 支持事件类型过滤
|
|
8
|
+
* 4. 保证事件顺序(timestamp 递增)
|
|
9
|
+
*/
|
|
10
|
+
import { PipelineEvent, PipelineEventType } from './events.js';
|
|
11
|
+
export declare class EventStore {
|
|
12
|
+
private db;
|
|
13
|
+
constructor(dbPath: string);
|
|
14
|
+
/**
|
|
15
|
+
* 初始化事件表
|
|
16
|
+
*/
|
|
17
|
+
private initSchema;
|
|
18
|
+
/**
|
|
19
|
+
* 追加事件到事件流
|
|
20
|
+
*/
|
|
21
|
+
append<T>(event: Omit<PipelineEvent<T>, 'id' | 'timestamp'>): PipelineEvent<T>;
|
|
22
|
+
/**
|
|
23
|
+
* 获取 Pipeline 的完整事件流
|
|
24
|
+
*/
|
|
25
|
+
getEvents(pipelineId: string, options?: {
|
|
26
|
+
types?: PipelineEventType[];
|
|
27
|
+
since?: number;
|
|
28
|
+
limit?: number;
|
|
29
|
+
}): PipelineEvent[];
|
|
30
|
+
/**
|
|
31
|
+
* 获取所有 Pipeline ID
|
|
32
|
+
*/
|
|
33
|
+
getAllPipelineIds(): string[];
|
|
34
|
+
/**
|
|
35
|
+
* 获取最新的 N 个事件
|
|
36
|
+
*/
|
|
37
|
+
getLatestEvents(pipelineId: string, limit: number): PipelineEvent[];
|
|
38
|
+
/**
|
|
39
|
+
* 获取特定类型的最新事件
|
|
40
|
+
*/
|
|
41
|
+
getLatestEventByType(pipelineId: string, type: PipelineEventType): PipelineEvent | null;
|
|
42
|
+
/**
|
|
43
|
+
* 统计事件数量
|
|
44
|
+
*/
|
|
45
|
+
countEvents(pipelineId: string, options?: {
|
|
46
|
+
types?: PipelineEventType[];
|
|
47
|
+
since?: number;
|
|
48
|
+
}): number;
|
|
49
|
+
/**
|
|
50
|
+
* 清理过期事件(可选功能,用于数据归档)
|
|
51
|
+
*/
|
|
52
|
+
pruneEvents(beforeTimestamp: number): number;
|
|
53
|
+
/**
|
|
54
|
+
* 关闭数据库连接
|
|
55
|
+
*/
|
|
56
|
+
close(): void;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=event-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-store.d.ts","sourceRoot":"","sources":["../../src/pipeline/event-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAE/D,qBAAa,UAAU;IACrB,OAAO,CAAC,EAAE,CAAoB;gBAElB,MAAM,EAAE,MAAM;IAK1B;;OAEG;IACH,OAAO,CAAC,UAAU;IAuBlB;;OAEG;IACH,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG,WAAW,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;IAwB9E;;OAEG;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QACtC,KAAK,CAAC,EAAE,iBAAiB,EAAE,CAAC;QAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,aAAa,EAAE;IA8CnB;;OAEG;IACH,iBAAiB,IAAI,MAAM,EAAE;IAW7B;;OAEG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,EAAE;IA4BnE;;OAEG;IACH,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,aAAa,GAAG,IAAI;IA8BvF;;OAEG;IACH,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QACxC,KAAK,CAAC,EAAE,iBAAiB,EAAE,CAAC;QAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,MAAM;IAmBV;;OAEG;IACH,WAAW,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM;IAQ5C;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline 事件存储层
|
|
3
|
+
*
|
|
4
|
+
* 职责:
|
|
5
|
+
* 1. 持久化事件到数据库
|
|
6
|
+
* 2. 按 Pipeline ID 查询事件流
|
|
7
|
+
* 3. 支持事件类型过滤
|
|
8
|
+
* 4. 保证事件顺序(timestamp 递增)
|
|
9
|
+
*/
|
|
10
|
+
import Database from 'better-sqlite3';
|
|
11
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
12
|
+
export class EventStore {
|
|
13
|
+
db;
|
|
14
|
+
constructor(dbPath) {
|
|
15
|
+
this.db = new Database(dbPath);
|
|
16
|
+
this.initSchema();
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 初始化事件表
|
|
20
|
+
*/
|
|
21
|
+
initSchema() {
|
|
22
|
+
this.db.exec(`
|
|
23
|
+
CREATE TABLE IF NOT EXISTS pipeline_events (
|
|
24
|
+
id TEXT PRIMARY KEY,
|
|
25
|
+
pipeline_id TEXT NOT NULL,
|
|
26
|
+
type TEXT NOT NULL,
|
|
27
|
+
timestamp INTEGER NOT NULL,
|
|
28
|
+
payload TEXT NOT NULL,
|
|
29
|
+
metadata TEXT NOT NULL,
|
|
30
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
CREATE INDEX IF NOT EXISTS idx_pipeline_events_pipeline_id
|
|
34
|
+
ON pipeline_events(pipeline_id);
|
|
35
|
+
|
|
36
|
+
CREATE INDEX IF NOT EXISTS idx_pipeline_events_timestamp
|
|
37
|
+
ON pipeline_events(pipeline_id, timestamp);
|
|
38
|
+
|
|
39
|
+
CREATE INDEX IF NOT EXISTS idx_pipeline_events_type
|
|
40
|
+
ON pipeline_events(pipeline_id, type);
|
|
41
|
+
`);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 追加事件到事件流
|
|
45
|
+
*/
|
|
46
|
+
append(event) {
|
|
47
|
+
const fullEvent = {
|
|
48
|
+
id: uuidv4(),
|
|
49
|
+
timestamp: Date.now(),
|
|
50
|
+
...event,
|
|
51
|
+
};
|
|
52
|
+
const stmt = this.db.prepare(`
|
|
53
|
+
INSERT INTO pipeline_events (id, pipeline_id, type, timestamp, payload, metadata)
|
|
54
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
55
|
+
`);
|
|
56
|
+
stmt.run(fullEvent.id, fullEvent.pipelineId, fullEvent.type, fullEvent.timestamp, JSON.stringify(fullEvent.payload), JSON.stringify(fullEvent.metadata));
|
|
57
|
+
return fullEvent;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 获取 Pipeline 的完整事件流
|
|
61
|
+
*/
|
|
62
|
+
getEvents(pipelineId, options) {
|
|
63
|
+
let sql = `
|
|
64
|
+
SELECT id, pipeline_id, type, timestamp, payload, metadata
|
|
65
|
+
FROM pipeline_events
|
|
66
|
+
WHERE pipeline_id = ?
|
|
67
|
+
`;
|
|
68
|
+
const params = [pipelineId];
|
|
69
|
+
if (options?.types && options.types.length > 0) {
|
|
70
|
+
sql += ` AND type IN (${options.types.map(() => '?').join(',')})`;
|
|
71
|
+
params.push(...options.types);
|
|
72
|
+
}
|
|
73
|
+
if (options?.since) {
|
|
74
|
+
sql += ` AND timestamp > ?`;
|
|
75
|
+
params.push(options.since);
|
|
76
|
+
}
|
|
77
|
+
sql += ` ORDER BY timestamp ASC`;
|
|
78
|
+
if (options?.limit) {
|
|
79
|
+
sql += ` LIMIT ?`;
|
|
80
|
+
params.push(options.limit);
|
|
81
|
+
}
|
|
82
|
+
const stmt = this.db.prepare(sql);
|
|
83
|
+
const rows = stmt.all(...params);
|
|
84
|
+
return rows.map(row => ({
|
|
85
|
+
id: row.id,
|
|
86
|
+
pipelineId: row.pipeline_id,
|
|
87
|
+
type: row.type,
|
|
88
|
+
timestamp: row.timestamp,
|
|
89
|
+
payload: JSON.parse(row.payload),
|
|
90
|
+
metadata: JSON.parse(row.metadata),
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* 获取所有 Pipeline ID
|
|
95
|
+
*/
|
|
96
|
+
getAllPipelineIds() {
|
|
97
|
+
const stmt = this.db.prepare(`
|
|
98
|
+
SELECT DISTINCT pipeline_id
|
|
99
|
+
FROM pipeline_events
|
|
100
|
+
ORDER BY pipeline_id
|
|
101
|
+
`);
|
|
102
|
+
const rows = stmt.all();
|
|
103
|
+
return rows.map(row => row.pipeline_id);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* 获取最新的 N 个事件
|
|
107
|
+
*/
|
|
108
|
+
getLatestEvents(pipelineId, limit) {
|
|
109
|
+
const stmt = this.db.prepare(`
|
|
110
|
+
SELECT id, pipeline_id, type, timestamp, payload, metadata
|
|
111
|
+
FROM pipeline_events
|
|
112
|
+
WHERE pipeline_id = ?
|
|
113
|
+
ORDER BY timestamp DESC
|
|
114
|
+
LIMIT ?
|
|
115
|
+
`);
|
|
116
|
+
const rows = stmt.all(pipelineId, limit);
|
|
117
|
+
return rows.reverse().map(row => ({
|
|
118
|
+
id: row.id,
|
|
119
|
+
pipelineId: row.pipeline_id,
|
|
120
|
+
type: row.type,
|
|
121
|
+
timestamp: row.timestamp,
|
|
122
|
+
payload: JSON.parse(row.payload),
|
|
123
|
+
metadata: JSON.parse(row.metadata),
|
|
124
|
+
}));
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* 获取特定类型的最新事件
|
|
128
|
+
*/
|
|
129
|
+
getLatestEventByType(pipelineId, type) {
|
|
130
|
+
const stmt = this.db.prepare(`
|
|
131
|
+
SELECT id, pipeline_id, type, timestamp, payload, metadata
|
|
132
|
+
FROM pipeline_events
|
|
133
|
+
WHERE pipeline_id = ? AND type = ?
|
|
134
|
+
ORDER BY timestamp DESC
|
|
135
|
+
LIMIT 1
|
|
136
|
+
`);
|
|
137
|
+
const row = stmt.get(pipelineId, type);
|
|
138
|
+
if (!row)
|
|
139
|
+
return null;
|
|
140
|
+
return {
|
|
141
|
+
id: row.id,
|
|
142
|
+
pipelineId: row.pipeline_id,
|
|
143
|
+
type: row.type,
|
|
144
|
+
timestamp: row.timestamp,
|
|
145
|
+
payload: JSON.parse(row.payload),
|
|
146
|
+
metadata: JSON.parse(row.metadata),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* 统计事件数量
|
|
151
|
+
*/
|
|
152
|
+
countEvents(pipelineId, options) {
|
|
153
|
+
let sql = `SELECT COUNT(*) as count FROM pipeline_events WHERE pipeline_id = ?`;
|
|
154
|
+
const params = [pipelineId];
|
|
155
|
+
if (options?.types && options.types.length > 0) {
|
|
156
|
+
sql += ` AND type IN (${options.types.map(() => '?').join(',')})`;
|
|
157
|
+
params.push(...options.types);
|
|
158
|
+
}
|
|
159
|
+
if (options?.since) {
|
|
160
|
+
sql += ` AND timestamp > ?`;
|
|
161
|
+
params.push(options.since);
|
|
162
|
+
}
|
|
163
|
+
const stmt = this.db.prepare(sql);
|
|
164
|
+
const result = stmt.get(...params);
|
|
165
|
+
return result.count;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* 清理过期事件(可选功能,用于数据归档)
|
|
169
|
+
*/
|
|
170
|
+
pruneEvents(beforeTimestamp) {
|
|
171
|
+
const stmt = this.db.prepare(`
|
|
172
|
+
DELETE FROM pipeline_events WHERE timestamp < ?
|
|
173
|
+
`);
|
|
174
|
+
const result = stmt.run(beforeTimestamp);
|
|
175
|
+
return result.changes;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* 关闭数据库连接
|
|
179
|
+
*/
|
|
180
|
+
close() {
|
|
181
|
+
this.db.close();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=event-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-store.js","sourceRoot":"","sources":["../../src/pipeline/event-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AAGpC,MAAM,OAAO,UAAU;IACb,EAAE,CAAoB;IAE9B,YAAY,MAAc;QACxB,IAAI,CAAC,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,CAAC,UAAU,EAAE,CAAC;IACpB,CAAC;IAED;;OAEG;IACK,UAAU;QAChB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;KAmBZ,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,MAAM,CAAI,KAAiD;QACzD,MAAM,SAAS,GAAqB;YAClC,EAAE,EAAE,MAAM,EAAE;YACZ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,GAAG,KAAK;SACT,CAAC;QAEF,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAG5B,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CACN,SAAS,CAAC,EAAE,EACZ,SAAS,CAAC,UAAU,EACpB,SAAS,CAAC,IAAI,EACd,SAAS,CAAC,SAAS,EACnB,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,EACjC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,CACnC,CAAC;QAEF,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,UAAkB,EAAE,OAI7B;QACC,IAAI,GAAG,GAAG;;;;KAIT,CAAC;QAEF,MAAM,MAAM,GAAU,CAAC,UAAU,CAAC,CAAC;QAEnC,IAAI,OAAO,EAAE,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/C,GAAG,IAAI,iBAAiB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAClE,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QAED,IAAI,OAAO,EAAE,KAAK,EAAE,CAAC;YACnB,GAAG,IAAI,oBAAoB,CAAC;YAC5B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QAED,GAAG,IAAI,yBAAyB,CAAC;QAEjC,IAAI,OAAO,EAAE,KAAK,EAAE,CAAC;YACnB,GAAG,IAAI,UAAU,CAAC;YAClB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAO7B,CAAC;QAEH,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACtB,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,UAAU,EAAE,GAAG,CAAC,WAAW;YAC3B,IAAI,EAAE,GAAG,CAAC,IAAyB;YACnC,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;YAChC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;SACnC,CAAC,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,iBAAiB;QACf,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;KAI5B,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAoC,CAAC;QAC1D,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC1C,CAAC;IAED;;OAEG;IACH,eAAe,CAAC,UAAkB,EAAE,KAAa;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;;;KAM5B,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAOrC,CAAC;QAEH,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChC,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,UAAU,EAAE,GAAG,CAAC,WAAW;YAC3B,IAAI,EAAE,GAAG,CAAC,IAAyB;YACnC,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;YAChC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;SACnC,CAAC,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,oBAAoB,CAAC,UAAkB,EAAE,IAAuB;QAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;;;KAM5B,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAOxB,CAAC;QAEd,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QAEtB,OAAO;YACL,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,UAAU,EAAE,GAAG,CAAC,WAAW;YAC3B,IAAI,EAAE,GAAG,CAAC,IAAyB;YACnC,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;YAChC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;SACnC,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,UAAkB,EAAE,OAG/B;QACC,IAAI,GAAG,GAAG,qEAAqE,CAAC;QAChF,MAAM,MAAM,GAAU,CAAC,UAAU,CAAC,CAAC;QAEnC,IAAI,OAAO,EAAE,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/C,GAAG,IAAI,iBAAiB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAClE,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QAED,IAAI,OAAO,EAAE,KAAK,EAAE,CAAC;YACnB,GAAG,IAAI,oBAAoB,CAAC;YAC5B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAsB,CAAC;QACxD,OAAO,MAAM,CAAC,KAAK,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,eAAuB;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;KAE5B,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC,OAAO,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;CACF"}
|