front-cpu 0.1.1
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 +475 -0
- package/README.zh-CN.md +474 -0
- package/dist/Pipeline.d.ts +119 -0
- package/dist/Pipeline.d.ts.map +1 -0
- package/dist/Pipeline.js +373 -0
- package/dist/Pipeline.js.map +1 -0
- package/dist/debug.d.ts +3 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +12 -0
- package/dist/debug.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces.d.ts +49 -0
- package/dist/interfaces.d.ts.map +1 -0
- package/dist/interfaces.js +8 -0
- package/dist/interfaces.js.map +1 -0
- package/dist/isa/index.d.ts +20 -0
- package/dist/isa/index.d.ts.map +1 -0
- package/dist/isa/index.js +26 -0
- package/dist/isa/index.js.map +1 -0
- package/dist/isa/types.d.ts +144 -0
- package/dist/isa/types.d.ts.map +1 -0
- package/dist/isa/types.js +10 -0
- package/dist/isa/types.js.map +1 -0
- package/dist/logging/CPUConsole.d.ts +105 -0
- package/dist/logging/CPUConsole.d.ts.map +1 -0
- package/dist/logging/CPUConsole.js +471 -0
- package/dist/logging/CPUConsole.js.map +1 -0
- package/dist/logging/CPUDebugger.d.ts +91 -0
- package/dist/logging/CPUDebugger.d.ts.map +1 -0
- package/dist/logging/CPUDebugger.js +166 -0
- package/dist/logging/CPUDebugger.js.map +1 -0
- package/dist/logging/CPUEventCollector.d.ts +90 -0
- package/dist/logging/CPUEventCollector.d.ts.map +1 -0
- package/dist/logging/CPUEventCollector.js +353 -0
- package/dist/logging/CPUEventCollector.js.map +1 -0
- package/dist/logging/CPULogger.d.ts +150 -0
- package/dist/logging/CPULogger.d.ts.map +1 -0
- package/dist/logging/CPULogger.js +336 -0
- package/dist/logging/CPULogger.js.map +1 -0
- package/dist/logging/index.d.ts +10 -0
- package/dist/logging/index.d.ts.map +1 -0
- package/dist/logging/index.js +16 -0
- package/dist/logging/index.js.map +1 -0
- package/dist/logging/runtime.d.ts +37 -0
- package/dist/logging/runtime.d.ts.map +1 -0
- package/dist/logging/runtime.js +42 -0
- package/dist/logging/runtime.js.map +1 -0
- package/dist/logging/stack-parser.d.ts +22 -0
- package/dist/logging/stack-parser.d.ts.map +1 -0
- package/dist/logging/stack-parser.js +144 -0
- package/dist/logging/stack-parser.js.map +1 -0
- package/dist/logging/types.d.ts +73 -0
- package/dist/logging/types.d.ts.map +1 -0
- package/dist/logging/types.js +47 -0
- package/dist/logging/types.js.map +1 -0
- package/dist/scheduling/ResourceStrategyRegistry.d.ts +61 -0
- package/dist/scheduling/ResourceStrategyRegistry.d.ts.map +1 -0
- package/dist/scheduling/ResourceStrategyRegistry.js +109 -0
- package/dist/scheduling/ResourceStrategyRegistry.js.map +1 -0
- package/dist/scheduling/index.d.ts +6 -0
- package/dist/scheduling/index.d.ts.map +1 -0
- package/dist/scheduling/index.js +5 -0
- package/dist/scheduling/index.js.map +1 -0
- package/dist/scheduling/types.d.ts +44 -0
- package/dist/scheduling/types.d.ts.map +1 -0
- package/dist/scheduling/types.js +5 -0
- package/dist/scheduling/types.js.map +1 -0
- package/dist/stages/EX.d.ts +17 -0
- package/dist/stages/EX.d.ts.map +1 -0
- package/dist/stages/EX.js +95 -0
- package/dist/stages/EX.js.map +1 -0
- package/dist/stages/IF.d.ts +41 -0
- package/dist/stages/IF.d.ts.map +1 -0
- package/dist/stages/IF.js +83 -0
- package/dist/stages/IF.js.map +1 -0
- package/dist/stages/RES.d.ts +17 -0
- package/dist/stages/RES.d.ts.map +1 -0
- package/dist/stages/RES.js +37 -0
- package/dist/stages/RES.js.map +1 -0
- package/dist/stages/SCH.d.ts +77 -0
- package/dist/stages/SCH.d.ts.map +1 -0
- package/dist/stages/SCH.js +270 -0
- package/dist/stages/SCH.js.map +1 -0
- package/dist/stages/WB.d.ts +19 -0
- package/dist/stages/WB.d.ts.map +1 -0
- package/dist/stages/WB.js +102 -0
- package/dist/stages/WB.js.map +1 -0
- package/dist/types.d.ts +111 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +26 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/InstructionCancellation.d.ts +31 -0
- package/dist/utils/InstructionCancellation.d.ts.map +1 -0
- package/dist/utils/InstructionCancellation.js +53 -0
- package/dist/utils/InstructionCancellation.js.map +1 -0
- package/dist/utils/abortable.d.ts +30 -0
- package/dist/utils/abortable.d.ts.map +1 -0
- package/dist/utils/abortable.js +76 -0
- package/dist/utils/abortable.js.map +1 -0
- package/dist/utils/request.d.ts +27 -0
- package/dist/utils/request.d.ts.map +1 -0
- package/dist/utils/request.js +96 -0
- package/dist/utils/request.js.map +1 -0
- package/package.json +74 -0
- package/src/Pipeline.ts +475 -0
- package/src/debug.ts +15 -0
- package/src/index.ts +67 -0
- package/src/interfaces.ts +53 -0
- package/src/isa/index.ts +34 -0
- package/src/isa/types.ts +178 -0
- package/src/logging/CPUConsole.md +843 -0
- package/src/logging/CPUConsole.ts +631 -0
- package/src/logging/CPUDebugger.ts +235 -0
- package/src/logging/CPUEventCollector.ts +418 -0
- package/src/logging/CPULogger.ts +435 -0
- package/src/logging/CPU_LOGGING_DESIGN.md +1319 -0
- package/src/logging/USAGE_GUIDE.md +505 -0
- package/src/logging/index.ts +21 -0
- package/src/logging/runtime.ts +96 -0
- package/src/logging/stack-parser.ts +168 -0
- package/src/logging/types.ts +101 -0
- package/src/scheduling/ResourceStrategyRegistry.ts +124 -0
- package/src/scheduling/index.ts +13 -0
- package/src/scheduling/types.ts +47 -0
- package/src/stages/EX.ts +121 -0
- package/src/stages/IF.ts +103 -0
- package/src/stages/RES.ts +46 -0
- package/src/stages/SCH.ts +331 -0
- package/src/stages/WB.ts +127 -0
- package/src/types.ts +118 -0
- package/src/utils/InstructionCancellation.ts +73 -0
- package/src/utils/abortable.ts +89 -0
- package/src/utils/request.ts +125 -0
package/README.md
ADDED
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
# FrontCPU
|
|
2
|
+
|
|
3
|
+
## The Async Nightmare in Frontend
|
|
4
|
+
|
|
5
|
+
Every frontend developer has been through this:
|
|
6
|
+
|
|
7
|
+
**Console.log Hell**
|
|
8
|
+
```javascript
|
|
9
|
+
// Your code is littered with these
|
|
10
|
+
console.log('starting request...')
|
|
11
|
+
console.log('params:', params)
|
|
12
|
+
console.log('response:', response)
|
|
13
|
+
console.log('did this run?')
|
|
14
|
+
console.log('why didnt this run???')
|
|
15
|
+
console.log('fuck')
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**Race Conditions**
|
|
19
|
+
```javascript
|
|
20
|
+
// User rapidly switches tabs
|
|
21
|
+
fetchTabData('tab1') // Request sent, takes 500ms
|
|
22
|
+
fetchTabData('tab2') // Request sent, takes 200ms
|
|
23
|
+
fetchTabData('tab3') // Request sent, takes 300ms
|
|
24
|
+
// Result: tab2 returns first, then tab3, finally tab1
|
|
25
|
+
// User sees tab1 data, but they clicked tab3
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Request Chaos**
|
|
29
|
+
```javascript
|
|
30
|
+
// Simultaneous updates to the same resource
|
|
31
|
+
updateUser({ id: 1, name: 'Alice' }) // Request A
|
|
32
|
+
updateUser({ id: 1, name: 'Bob' }) // Request B
|
|
33
|
+
// Request B reaches server first, then A
|
|
34
|
+
// Database has 'Alice', but user expects 'Bob'
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Zero Observability**
|
|
38
|
+
- Did the request even fire?
|
|
39
|
+
- Where is it stuck?
|
|
40
|
+
- Why is this request slower than that one?
|
|
41
|
+
- Did the optimistic update roll back?
|
|
42
|
+
- How do I even reproduce this bug?
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## The Solution: Think Like a CPU
|
|
47
|
+
|
|
48
|
+
Modern CPUs don't execute instructions one by one. They:
|
|
49
|
+
- Analyze dependencies between instructions
|
|
50
|
+
- Execute independent operations in parallel
|
|
51
|
+
- Queue conflicting operations automatically
|
|
52
|
+
- Track every instruction's state throughout its lifecycle
|
|
53
|
+
|
|
54
|
+
**Your frontend should do the same.**
|
|
55
|
+
|
|
56
|
+
FrontCPU brings real CPU out-of-order execution architecture to the frontend:
|
|
57
|
+
- Automatic resource conflict detection
|
|
58
|
+
- Automatic parallel vs. serial execution decisions
|
|
59
|
+
- Complete lifecycle tracking for every operation
|
|
60
|
+
- **World-class debugging with zero code**
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Debugging: Before vs. After
|
|
65
|
+
|
|
66
|
+
### Before: Console.log Hell
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
async function updateTask(id, data) {
|
|
70
|
+
console.log('[updateTask] start', { id, data })
|
|
71
|
+
try {
|
|
72
|
+
console.log('[updateTask] sending request...')
|
|
73
|
+
const response = await fetch(`/api/tasks/${id}`, {
|
|
74
|
+
method: 'PUT',
|
|
75
|
+
body: JSON.stringify(data)
|
|
76
|
+
})
|
|
77
|
+
console.log('[updateTask] status:', response.status)
|
|
78
|
+
const result = await response.json()
|
|
79
|
+
console.log('[updateTask] result:', result)
|
|
80
|
+
store.tasks[id] = result
|
|
81
|
+
console.log('[updateTask] state updated')
|
|
82
|
+
return result
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error('[updateTask] failed:', error)
|
|
85
|
+
throw error
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Console output:
|
|
91
|
+
```
|
|
92
|
+
[updateTask] start {id: 1, data: {name: 'test'}}
|
|
93
|
+
[updateTask] sending request...
|
|
94
|
+
[updateTask] status: 200
|
|
95
|
+
[updateTask] result: {id: 1, name: 'test'}
|
|
96
|
+
[updateTask] state updated
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Problems:
|
|
100
|
+
- Writing tons of log code manually
|
|
101
|
+
- No timing information
|
|
102
|
+
- No idea where the call originated
|
|
103
|
+
- Multiple request logs get mixed together
|
|
104
|
+
- Have to remove all logs before production
|
|
105
|
+
|
|
106
|
+
### After: Zero Code, World-Class Debugging
|
|
107
|
+
|
|
108
|
+
```javascript
|
|
109
|
+
// Define instruction - not a single log statement
|
|
110
|
+
registerISA({
|
|
111
|
+
'task.update': {
|
|
112
|
+
meta: {
|
|
113
|
+
description: 'Update task',
|
|
114
|
+
resourceIdentifier: (p) => [`task:${p.id}`],
|
|
115
|
+
},
|
|
116
|
+
request: {
|
|
117
|
+
method: 'PUT',
|
|
118
|
+
url: (p) => `/api/tasks/${p.id}`,
|
|
119
|
+
body: (p) => p.data,
|
|
120
|
+
},
|
|
121
|
+
commit: async (result) => {
|
|
122
|
+
store.tasks[result.id] = result
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
// Use it
|
|
128
|
+
pipeline.dispatch('task.update', { id: 1, data: { name: 'test' } })
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Console automatically outputs:
|
|
132
|
+
```
|
|
133
|
+
[Created] 14:32:15.123 task.update 📍 src/views/TaskList.vue:42
|
|
134
|
+
├─ Instruction ID: instr-1760629698922-11
|
|
135
|
+
├─ Correlation ID: corr_1760629698922_f_M_sBit6A
|
|
136
|
+
└─ Payload: { id: 1, data: { name: 'test' } }
|
|
137
|
+
|
|
138
|
+
[Success] 14:32:15.456 task.update 333ms 📍 src/views/TaskList.vue:42
|
|
139
|
+
├─ 📝 Payload: { id: 1, data: { name: 'test' } }
|
|
140
|
+
├─ 📥 Response: { id: 1, name: 'test', updatedAt: '...' }
|
|
141
|
+
├─ 💾 WB Stage: commit() executed successfully
|
|
142
|
+
└─ Pipeline Stages:
|
|
143
|
+
IF→SCH 0ms
|
|
144
|
+
SCH→EX 2ms
|
|
145
|
+
EX→WB ██████ 331ms
|
|
146
|
+
Total: 333ms
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Zero debugging code, automatically get:**
|
|
150
|
+
- Millisecond-precision timestamps
|
|
151
|
+
- Source file and line number (clickable)
|
|
152
|
+
- Request payload and response
|
|
153
|
+
- Visual timing breakdown for each pipeline stage
|
|
154
|
+
- Unique instruction ID and correlation ID for tracing
|
|
155
|
+
|
|
156
|
+
### Failures Auto-Expand with Smart Suggestions
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
[Failed] 14:32:16.789 task.update 1502ms 📍 src/views/TaskList.vue:42
|
|
160
|
+
├─ Reason: Request timeout
|
|
161
|
+
├─ 📝 Payload: { id: 1, data: { name: 'test' } }
|
|
162
|
+
├─ 🔄 Optimistic update rolled back
|
|
163
|
+
├─ Pipeline Stages:
|
|
164
|
+
│ IF→SCH 0ms
|
|
165
|
+
│ SCH→EX 1ms
|
|
166
|
+
│ EX→WB ████████████████████ 1501ms
|
|
167
|
+
│ Total: 1502ms
|
|
168
|
+
├─ 💡 Suggestions:
|
|
169
|
+
│ • Request timed out - consider increasing timeout or optimizing backend
|
|
170
|
+
│ • Execution took 1502ms (>1s) - check for performance issues
|
|
171
|
+
└─ Error Stack: ...
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## The New Development Paradigm
|
|
177
|
+
|
|
178
|
+
With FrontCPU, you only need to do four things:
|
|
179
|
+
|
|
180
|
+
### 1. UI Layer: Keep It the Same
|
|
181
|
+
|
|
182
|
+
Whatever framework you use for UI, keep using it. Vue, React, Svelte - all work.
|
|
183
|
+
|
|
184
|
+
```vue
|
|
185
|
+
<template>
|
|
186
|
+
<div v-for="task in tasks" :key="task.id">
|
|
187
|
+
{{ task.name }}
|
|
188
|
+
<button @click="completeTask(task.id)">Complete</button>
|
|
189
|
+
</div>
|
|
190
|
+
</template>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### 2. Define Your Instruction Set
|
|
194
|
+
|
|
195
|
+
Declare each operation: what it does, how to call the API, how to update state, whether it needs queuing.
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
registerISA({
|
|
199
|
+
'task.complete': {
|
|
200
|
+
meta: {
|
|
201
|
+
description: 'Complete a task',
|
|
202
|
+
category: 'task',
|
|
203
|
+
resourceIdentifier: (p) => [`task:${p.id}`], // Resource ID for conflict detection
|
|
204
|
+
schedulingStrategy: 'serial', // Same-task operations run serially
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
// Optimistic update: show completion immediately
|
|
208
|
+
optimistic: {
|
|
209
|
+
enabled: true,
|
|
210
|
+
apply: (payload) => {
|
|
211
|
+
const task = store.tasks.find(t => t.id === payload.id)
|
|
212
|
+
const snapshot = { ...task }
|
|
213
|
+
task.completed = true
|
|
214
|
+
return snapshot
|
|
215
|
+
},
|
|
216
|
+
rollback: (snapshot) => {
|
|
217
|
+
Object.assign(store.tasks.find(t => t.id === snapshot.id), snapshot)
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
// HTTP request
|
|
222
|
+
request: {
|
|
223
|
+
method: 'POST',
|
|
224
|
+
url: (p) => `/api/tasks/${p.id}/complete`,
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
// Update state after server confirms
|
|
228
|
+
commit: async (result, payload) => {
|
|
229
|
+
Object.assign(store.tasks.find(t => t.id === payload.id), result)
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
})
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### 3. Dispatch Instructions from Components
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
function completeTask(id: string) {
|
|
239
|
+
pipeline.dispatch('task.complete', { id })
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
That's it. Everything below is handled automatically:
|
|
244
|
+
- Instruction lifecycle tracking (no manual logs)
|
|
245
|
+
- HTTP request execution
|
|
246
|
+
- Request deduplication
|
|
247
|
+
- Optimistic updates & rollback on failure
|
|
248
|
+
- Resource conflict detection
|
|
249
|
+
- Concurrency control
|
|
250
|
+
|
|
251
|
+
### 4. (Optional) Register Interrupt Handlers
|
|
252
|
+
|
|
253
|
+
For SSE, WebSocket, Web Workers, and other external events:
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
pipeline.registerInterruptHandler('sse', {
|
|
257
|
+
onMessage: (event) => {
|
|
258
|
+
// Unified handling for all external interrupts
|
|
259
|
+
pipeline.dispatch('data.sync', event.data)
|
|
260
|
+
},
|
|
261
|
+
})
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Scheduling Strategies
|
|
267
|
+
|
|
268
|
+
Different scenarios need different concurrency control:
|
|
269
|
+
|
|
270
|
+
### out-of-order (default): Maximum Parallelism
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
// Different tasks can run in parallel
|
|
274
|
+
pipeline.dispatch('task.fetch', { id: 1 })
|
|
275
|
+
pipeline.dispatch('task.fetch', { id: 2 })
|
|
276
|
+
pipeline.dispatch('task.fetch', { id: 3 })
|
|
277
|
+
// All three requests fire simultaneously
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### serial: Strict Ordering
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
meta: { schedulingStrategy: 'serial' }
|
|
284
|
+
|
|
285
|
+
// Same-task operations must queue
|
|
286
|
+
pipeline.dispatch('task.update', { id: 1, name: 'A' })
|
|
287
|
+
pipeline.dispatch('task.update', { id: 1, name: 'B' })
|
|
288
|
+
// B waits for A to complete, guaranteeing order
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### latest: Keep Only the Newest (Search Scenarios)
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
meta: { schedulingStrategy: 'latest' }
|
|
295
|
+
|
|
296
|
+
// User types quickly
|
|
297
|
+
pipeline.dispatch('search', { query: 'h' })
|
|
298
|
+
pipeline.dispatch('search', { query: 'he' })
|
|
299
|
+
pipeline.dispatch('search', { query: 'hel' })
|
|
300
|
+
pipeline.dispatch('search', { query: 'hello' })
|
|
301
|
+
// First three auto-cancel, only 'hello' executes
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### read-write: Reader-Writer Locks
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
meta: { schedulingStrategy: 'read-write' }
|
|
308
|
+
|
|
309
|
+
// Multiple reads can run in parallel
|
|
310
|
+
pipeline.dispatch('user.get', { id: 1 })
|
|
311
|
+
pipeline.dispatch('user.get', { id: 1 })
|
|
312
|
+
|
|
313
|
+
// Writes are exclusive
|
|
314
|
+
pipeline.dispatch('user.update', { id: 1, name: 'test' })
|
|
315
|
+
// Waits for all reads to complete, blocks subsequent reads until write finishes
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## 5-Stage Pipeline Architecture
|
|
321
|
+
|
|
322
|
+
```
|
|
323
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
324
|
+
│ │
|
|
325
|
+
│ dispatch('task.complete', { id: 1 }) │
|
|
326
|
+
│ │ │
|
|
327
|
+
│ ▼ │
|
|
328
|
+
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
|
329
|
+
│ │ IF │ → │ SCH │ → │ EX │ → │ RES │ → │ WB │ │
|
|
330
|
+
│ │ Fetch │ │Schedule │ │ Execute │ │Response │ │Writeback│ │
|
|
331
|
+
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
|
|
332
|
+
│ │ │ │ │ │ │
|
|
333
|
+
│ Generate ID Detect conflicts Run request Process result Commit │
|
|
334
|
+
│ Capture source Parallel/wait Optimistic Error handling Release │
|
|
335
|
+
│ Create aborter Issue instr Timeout Normalize Rollback │
|
|
336
|
+
│ │
|
|
337
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## Installation
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
npm install front-cpu
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
## Quick Start
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
import { Pipeline, setHttpClient, registerISA } from 'front-cpu'
|
|
352
|
+
|
|
353
|
+
// 1. Configure HTTP client
|
|
354
|
+
setHttpClient({
|
|
355
|
+
get: (url, config) => fetch(url, config).then(r => r.json()),
|
|
356
|
+
post: (url, data, config) =>
|
|
357
|
+
fetch(url, { method: 'POST', body: JSON.stringify(data), ...config })
|
|
358
|
+
.then(r => r.json()),
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
// 2. Define instruction set
|
|
362
|
+
registerISA({
|
|
363
|
+
'user.fetch': {
|
|
364
|
+
meta: {
|
|
365
|
+
description: 'Fetch user info',
|
|
366
|
+
resourceIdentifier: (p) => [`user:${p.id}`],
|
|
367
|
+
},
|
|
368
|
+
request: {
|
|
369
|
+
method: 'GET',
|
|
370
|
+
url: (p) => `/api/users/${p.id}`,
|
|
371
|
+
},
|
|
372
|
+
commit: async (result) => {
|
|
373
|
+
store.user = result
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
// 3. Create and start pipeline
|
|
379
|
+
const pipeline = new Pipeline({ maxConcurrency: 10 })
|
|
380
|
+
pipeline.start()
|
|
381
|
+
|
|
382
|
+
// 4. Dispatch instructions
|
|
383
|
+
const user = await pipeline.dispatch('user.fetch', { id: 1 })
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## Enable Debugging (Optional)
|
|
387
|
+
|
|
388
|
+
The core package excludes debugging code to minimize bundle size. When you need debugging:
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
import { Pipeline, cpuConsole, ConsoleLevel } from 'front-cpu/debug'
|
|
392
|
+
|
|
393
|
+
// Set log level
|
|
394
|
+
cpuConsole.setLevel(ConsoleLevel.VERBOSE)
|
|
395
|
+
|
|
396
|
+
// Filter specific instructions
|
|
397
|
+
cpuConsole.setFilter(['task.update', 'task.complete'])
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Log levels:
|
|
401
|
+
- `SILENT` - No output
|
|
402
|
+
- `MINIMAL` - Success/failure only
|
|
403
|
+
- `NORMAL` - Key stages
|
|
404
|
+
- `VERBOSE` - All details + pipeline timing visualization
|
|
405
|
+
- `DEBUG` - Full payload and call stack
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## API Reference
|
|
410
|
+
|
|
411
|
+
### Pipeline
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
const pipeline = new Pipeline({
|
|
415
|
+
maxConcurrency: 10, // Max parallel executions
|
|
416
|
+
tickInterval: 16, // Scheduler tick interval (ms)
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
pipeline.start() // Start
|
|
420
|
+
pipeline.stop() // Pause
|
|
421
|
+
pipeline.reset() // Reset
|
|
422
|
+
|
|
423
|
+
// Dispatch instruction
|
|
424
|
+
const result = await pipeline.dispatch('type', payload, options)
|
|
425
|
+
|
|
426
|
+
// Cancellation
|
|
427
|
+
pipeline.flush('tag') // Cancel by tag
|
|
428
|
+
pipeline.getInstructionsByTags(['tag']) // Query by tags
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### Instruction Definition
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
registerISA({
|
|
435
|
+
'instruction.type': {
|
|
436
|
+
meta: {
|
|
437
|
+
description: string,
|
|
438
|
+
category: 'task' | 'debug' | 'schedule' | 'system' | 'area',
|
|
439
|
+
resourceIdentifier: (payload) => string[],
|
|
440
|
+
priority?: number, // 0-10
|
|
441
|
+
timeout?: number, // milliseconds
|
|
442
|
+
schedulingStrategy?: 'out-of-order' | 'serial' | 'latest' | 'read-write',
|
|
443
|
+
},
|
|
444
|
+
|
|
445
|
+
request?: { method, url, body }, // HTTP request
|
|
446
|
+
execute?: (payload, context) => any, // Or custom logic
|
|
447
|
+
|
|
448
|
+
optimistic?: { enabled, apply, rollback },
|
|
449
|
+
commit?: (result, payload, context, snapshot) => void,
|
|
450
|
+
},
|
|
451
|
+
})
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
## Development
|
|
457
|
+
|
|
458
|
+
```bash
|
|
459
|
+
pnpm install # Install dependencies
|
|
460
|
+
pnpm dev # Start playground (localhost:3000)
|
|
461
|
+
pnpm build # Build
|
|
462
|
+
pnpm test # Test
|
|
463
|
+
pnpm bench # Benchmark
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
## Documentation
|
|
467
|
+
|
|
468
|
+
- [API Reference](./docs/API.md)
|
|
469
|
+
- [Architecture Deep Dive](./docs/ARCHITECTURE.md)
|
|
470
|
+
- [ISA Development Guide](./docs/ISA_GUIDE.md)
|
|
471
|
+
- [中文文档](./README.zh-CN.md)
|
|
472
|
+
|
|
473
|
+
## License
|
|
474
|
+
|
|
475
|
+
MIT
|