@pilllesss/yorn 1.0.182 → 1.0.183

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.

Potentially problematic release.


This version of @pilllesss/yorn might be problematic. Click here for more details.

Files changed (45) hide show
  1. package/README.md +1 -1
  2. package/dist/providers/data/.manifest.json +1 -1
  3. package/dist/skills/code-review/LICENSE +21 -0
  4. package/dist/skills/code-review/SKILL.md +233 -0
  5. package/dist/skills/code-review/assets/pr-review-template.md +137 -0
  6. package/dist/skills/code-review/assets/review-checklist.md +123 -0
  7. package/dist/skills/code-review/reference/angular.md +768 -0
  8. package/dist/skills/code-review/reference/architecture-review-guide.md +472 -0
  9. package/dist/skills/code-review/reference/c.md +890 -0
  10. package/dist/skills/code-review/reference/code-quality-universal.md +488 -0
  11. package/dist/skills/code-review/reference/code-review-best-practices.md +136 -0
  12. package/dist/skills/code-review/reference/common-bugs-checklist.md +302 -0
  13. package/dist/skills/code-review/reference/cpp.md +893 -0
  14. package/dist/skills/code-review/reference/cross-cutting/async-concurrency-patterns.md +515 -0
  15. package/dist/skills/code-review/reference/cross-cutting/error-handling-principles.md +492 -0
  16. package/dist/skills/code-review/reference/cross-cutting/n-plus-one-queries.md +309 -0
  17. package/dist/skills/code-review/reference/cross-cutting/sql-injection-prevention.md +308 -0
  18. package/dist/skills/code-review/reference/cross-cutting/xss-prevention.md +264 -0
  19. package/dist/skills/code-review/reference/csharp.md +525 -0
  20. package/dist/skills/code-review/reference/css-less-sass.md +661 -0
  21. package/dist/skills/code-review/reference/dart.md +670 -0
  22. package/dist/skills/code-review/reference/django.md +985 -0
  23. package/dist/skills/code-review/reference/fastapi.md +580 -0
  24. package/dist/skills/code-review/reference/go.md +993 -0
  25. package/dist/skills/code-review/reference/java.md +409 -0
  26. package/dist/skills/code-review/reference/java8.md +586 -0
  27. package/dist/skills/code-review/reference/kotlin.md +1018 -0
  28. package/dist/skills/code-review/reference/nestjs.md +593 -0
  29. package/dist/skills/code-review/reference/performance-review-guide.md +816 -0
  30. package/dist/skills/code-review/reference/php.md +684 -0
  31. package/dist/skills/code-review/reference/python.md +1073 -0
  32. package/dist/skills/code-review/reference/qt.md +757 -0
  33. package/dist/skills/code-review/reference/react.md +871 -0
  34. package/dist/skills/code-review/reference/ruby.md +964 -0
  35. package/dist/skills/code-review/reference/rust.md +846 -0
  36. package/dist/skills/code-review/reference/security-review-guide.md +494 -0
  37. package/dist/skills/code-review/reference/svelte.md +1064 -0
  38. package/dist/skills/code-review/reference/swift.md +936 -0
  39. package/dist/skills/code-review/reference/typescript.md +1016 -0
  40. package/dist/skills/code-review/reference/vue.md +924 -0
  41. package/dist/skills/code-review/reference/zig.md +440 -0
  42. package/dist/skills/code-review/scripts/pr-analyzer.py +435 -0
  43. package/dist/skills/code-review/scripts/test_pr_analyzer.py +380 -0
  44. package/dist/yorn.cjs +628 -628
  45. package/package.json +2 -2
@@ -0,0 +1,515 @@
1
+ # 异步与并发模式 — 跨语言通用指南
2
+
3
+ > 本文档覆盖并发模型对比、常见陷阱、跨语言最佳实践和结构化并发模式。
4
+
5
+ ## 目录
6
+
7
+ - [并发模型对比](#并发模型对比)
8
+ - [常见陷阱](#常见陷阱)
9
+ - [最佳实践](#最佳实践)
10
+ - [跨语言代码示例](#跨语言代码示例)
11
+ - [Review Checklist](#review-checklist)
12
+
13
+ ---
14
+
15
+ ## 并发模型对比
16
+
17
+ | 模型 | 语言 | 核心概念 | 优点 | 缺点 |
18
+ |------|------|----------|------|------|
19
+ | **Goroutines + Channels** | Go | 轻量级协程 + CSP 通信 | 极简语法、低开销 | 手动取消传播 |
20
+ | **async/await + Event Loop** | Python, TypeScript | 单线程协作式多任务 | 无锁、易推理 | 不能阻塞事件循环 |
21
+ | **async/await + Tokio** | Rust | Futures + 运行时调度 | 零成本抽象、编译期安全 | 学习曲线陡 |
22
+ | **Coroutines + Flow** | Kotlin | 挂起函数 + 结构化并发 | 自动取消、生命周期绑定 | Dispatchers 选择复杂 |
23
+ | **async/await + Actors** | Swift | 结构化并发 + Actor 隔离 | 编译期数据竞争检查 | Swift 6 迁移成本 |
24
+ | **async/await + TPL** | C# | Task + 线程池 | 成熟生态、ConfigureAwait | 隐式线程切换 |
25
+ | **Threads + Mutexes** | C++, Java, 所有 | OS 线程 + 共享内存 | 真正并行 | 锁管理复杂、死锁风险 |
26
+
27
+ ### 何时选择什么
28
+
29
+ ```
30
+ I/O 密集型(网络、数据库、文件):
31
+ → async/await(Python, TS, Rust, Swift, C#)
32
+ → goroutines(Go)
33
+ → coroutines(Kotlin)
34
+
35
+ CPU 密集型(计算、图像处理):
36
+ → 线程池(Java, C++, C#)
37
+ → multiprocessing(Python)
38
+ → spawn_blocking(Rust tokio)
39
+ → Dispatchers.Default(Kotlin)
40
+
41
+ 混合型:
42
+ → async + spawn_blocking(Rust)
43
+ → async + run_in_executor(Python)
44
+ → goroutines + sync.Mutex(Go)
45
+ ```
46
+
47
+ ---
48
+
49
+ ## 常见陷阱
50
+
51
+ ### 陷阱 1: 竞态条件(Race Condition)
52
+
53
+ 多个并发任务读写共享状态,结果依赖执行顺序。
54
+
55
+ ```
56
+ // 通用伪代码
57
+ counter = 0
58
+
59
+ task1: counter += 1 // 读 counter=0, 写 counter=1
60
+ task2: counter += 1 // 读 counter=0, 写 counter=1
61
+ // 期望 counter=2, 实际 counter=1
62
+ ```
63
+
64
+ **解决方案**:互斥锁、原子操作、或将共享状态封装在 Actor 中。
65
+
66
+ ### 陷阱 2: 死锁(Deadlock)
67
+
68
+ 两个或多个任务互相等待对方持有的锁。
69
+
70
+ ```
71
+ task1: lock(A); lock(B); // 持有 A,等待 B
72
+ task2: lock(B); lock(A); // 持有 B,等待 A
73
+ // 两者永远等待
74
+ ```
75
+
76
+ **解决方案**:
77
+ - 一致的锁获取顺序
78
+ - 超时锁(tryLock with timeout)
79
+ - 避免嵌套锁
80
+
81
+ ### 陷阱 3: Starvation
82
+
83
+ 低优先级任务永远得不到执行机会。
84
+
85
+ ```
86
+ // 高优先级任务持续到达,低优先级任务永远排队
87
+ ```
88
+
89
+ **解决方案**:公平锁、任务优先级队列、限制并发数。
90
+
91
+ ### 陷阱 4: Goroutine / Task 泄漏
92
+
93
+ 启动并发任务但没有确保其退出。
94
+
95
+ ```go
96
+ // ❌ Go: goroutine 泄漏
97
+ func process() {
98
+ ch := make(chan int)
99
+ go func() {
100
+ result := <-ch // 如果没有人发送,goroutine 永远阻塞
101
+ }()
102
+ // 函数返回,但 goroutine 仍在等待
103
+ }
104
+ ```
105
+
106
+ ```python
107
+ # ❌ Python: Task 泄漏
108
+ async def process():
109
+ task = asyncio.create_task(long_running())
110
+ # 函数返回,但 task 仍在运行
111
+ ```
112
+
113
+ **解决方案**:使用 context/done channel (Go)、TaskGroup (Python)、structured concurrency (Kotlin/Swift)。
114
+
115
+ ### 陷阱 5: 在异步上下文中阻塞
116
+
117
+ ```python
118
+ # ❌ Python: 在 async 函数中使用同步 I/O 阻塞事件循环
119
+ async def handle():
120
+ result = requests.get(url) # 阻塞!整个事件循环停滞
121
+ return result
122
+
123
+ # ✅ 使用异步 I/O 或将阻塞操作放到线程池
124
+ async def handle():
125
+ result = await aiohttp.get(url) # 非阻塞
126
+ return result
127
+
128
+ # 或将同步代码放到线程池
129
+ async def handle():
130
+ result = await asyncio.to_thread(requests.get, url)
131
+ return result
132
+ ```
133
+
134
+ ```rust
135
+ // ❌ Rust: 在 async 函数中阻塞
136
+ async fn handle() {
137
+ let result = std::fs::read_to_string("large.txt"); // 阻塞 tokio 运行时
138
+ }
139
+
140
+ // ✅ 使用 spawn_blocking
141
+ async fn handle() {
142
+ let result = tokio::task::spawn_blocking(|| {
143
+ std::fs::read_to_string("large.txt")
144
+ }).await?;
145
+ }
146
+ ```
147
+
148
+ ---
149
+
150
+ ## 最佳实践
151
+
152
+ ### 1. 结构化并发
153
+
154
+ 确保并发任务的生命周期与创建它们的 scope 绑定。父任务取消时,子任务自动取消。
155
+
156
+ ```kotlin
157
+ // ✅ Kotlin: coroutineScope 确保子协程在 scope 结束时全部完成
158
+ suspend fun processItems(items: List<Item>) = coroutineScope {
159
+ items.forEach { item ->
160
+ launch { processItem(item) } // 子协程
161
+ }
162
+ // scope 结束时等待所有子协程完成
163
+ }
164
+
165
+ // 如果 processItems 被取消,所有子协程自动取消
166
+ ```
167
+
168
+ ```swift
169
+ // ✅ Swift: async let + TaskGroup
170
+ func processItems() async throws {
171
+ async let resultA = fetchA() // 并发执行
172
+ async let resultB = fetchB()
173
+ let combined = try await (resultA, resultB) // 等待两者
174
+ }
175
+ ```
176
+
177
+ ```python
178
+ # ✅ Python 3.11+: TaskGroup
179
+ async def process_items():
180
+ async with asyncio.TaskGroup() as tg:
181
+ for item in items:
182
+ tg.create_task(process_item(item))
183
+ # TaskGroup 退出时等待所有任务完成
184
+ # 如果一个任务失败,其余任务自动取消
185
+ ```
186
+
187
+ ### 2. 取消传播
188
+
189
+ 确保取消信号能正确传播到所有子任务。
190
+
191
+ ```go
192
+ // ✅ Go: context 传播取消
193
+ func processAll(ctx context.Context, items []Item) error {
194
+ g, ctx := errgroup.WithContext(ctx)
195
+ for _, item := range items {
196
+ item := item
197
+ g.Go(func() error {
198
+ return processItem(ctx, item)
199
+ })
200
+ }
201
+ return g.Wait() // 任一失败,context 取消,其余任务收到信号
202
+ }
203
+ ```
204
+
205
+ ```rust
206
+ // ✅ Rust: tokio::select! + JoinHandle
207
+ async fn process_with_timeout(item: Item) -> Result<Data> {
208
+ tokio::select! {
209
+ result = process(item) => result,
210
+ _ = tokio::time::sleep(Duration::from_secs(30)) => {
211
+ Err(anyhow!("processing timed out"))
212
+ }
213
+ }
214
+ }
215
+ ```
216
+
217
+ ### 3. Backpressure(反压)
218
+
219
+ 当生产者速度远超消费者时,需要限制队列大小,防止内存膨胀。
220
+
221
+ ```go
222
+ // ✅ Go: 有缓冲 channel 作为自然反压
223
+ func process(items <-chan Item) <-chan Result {
224
+ results := make(chan Result, 10) // 缓冲 10 个结果
225
+ go func() {
226
+ for item := range items {
227
+ results <- processItem(item) // 缓冲满时阻塞
228
+ }
229
+ close(results)
230
+ }()
231
+ return results
232
+ }
233
+ ```
234
+
235
+ ```kotlin
236
+ // ✅ Kotlin: Flow 自带反压
237
+ fun itemsFlow(): Flow<Item> = flow {
238
+ for (item in fetchAll()) {
239
+ emit(item) // collector 未准备好时挂起
240
+ }
241
+ }
242
+ // 使用 buffer() 控制缓冲策略
243
+ itemsFlow()
244
+ .buffer(capacity = 10, onBufferOverflow = BufferOverflow.SUSPEND)
245
+ .collect { process(it) }
246
+ ```
247
+
248
+ ### 4. 限制并发数
249
+
250
+ 防止同时启动过多任务导致资源耗尽。
251
+
252
+ ```python
253
+ # ✅ Python: Semaphore 限制并发
254
+ async def fetch_all(urls: list[str], max_concurrent: int = 10):
255
+ semaphore = asyncio.Semaphore(max_concurrent)
256
+
257
+ async def fetch_one(url: str):
258
+ async with semaphore:
259
+ return await aiohttp.get(url)
260
+
261
+ return await asyncio.gather(*[fetch_one(url) for url in urls])
262
+ ```
263
+
264
+ ```go
265
+ // ✅ Go: errgroup + semaphore
266
+ func fetchAll(ctx context.Context, urls []string, maxConcurrent int) error {
267
+ g, ctx := errgroup.WithContext(ctx)
268
+ sem := make(chan struct{}, maxConcurrent)
269
+
270
+ for _, url := range urls {
271
+ url := url
272
+ g.Go(func() error {
273
+ sem <- struct{}{} // 获取信号量
274
+ defer func() { <-sem }() // 释放信号量
275
+ return fetch(ctx, url)
276
+ })
277
+ }
278
+ return g.Wait()
279
+ }
280
+ ```
281
+
282
+ ---
283
+
284
+ ## 跨语言代码示例
285
+
286
+ ### Go: Goroutines + Channels + Context
287
+
288
+ ```go
289
+ // ✅ 完整模式: context 取消 + errgroup + 有界并发
290
+ func processBatch(ctx context.Context, items []Item) ([]Result, error) {
291
+ g, ctx := errgroup.WithContext(ctx)
292
+ results := make([]Result, len(items))
293
+ sem := make(chan struct{}, 10) // 最多 10 个并发
294
+
295
+ for i, item := range items {
296
+ i, item := i, item
297
+ g.Go(func() error {
298
+ select {
299
+ case sem <- struct{}{}:
300
+ case <-ctx.Done():
301
+ return ctx.Err()
302
+ }
303
+ defer func() { <-sem }()
304
+
305
+ result, err := process(ctx, item)
306
+ if err != nil {
307
+ return fmt.Errorf("item %d: %w", i, err)
308
+ }
309
+ results[i] = result
310
+ return nil
311
+ })
312
+ }
313
+
314
+ if err := g.Wait(); err != nil {
315
+ return nil, err
316
+ }
317
+ return results, nil
318
+ }
319
+ ```
320
+
321
+ ### Python: asyncio + TaskGroup
322
+
323
+ ```python
324
+ # ✅ Python 3.11+: 结构化并发 + 有界并发 + 超时
325
+ import asyncio
326
+
327
+ async def process_batch(items: list[Item], max_concurrent: int = 10) -> list[Result]:
328
+ semaphore = asyncio.Semaphore(max_concurrent)
329
+
330
+ async def process_one(item: Item) -> Result:
331
+ async with semaphore:
332
+ return await process(item)
333
+
334
+ async with asyncio.TaskGroup() as tg:
335
+ tasks = [tg.create_task(process_one(item)) for item in items]
336
+
337
+ return [task.result() for task in tasks]
338
+ ```
339
+
340
+ ### Rust: tokio + select + spawn_blocking
341
+
342
+ ```rust
343
+ // ✅ 有界并发 + 超时 + 阻塞操作隔离
344
+ use tokio::sync::Semaphore;
345
+ use std::sync::Arc;
346
+
347
+ async fn process_batch(items: Vec<Item>, max_concurrent: usize) -> Result<Vec<Output>> {
348
+ let sem = Arc::new(Semaphore::new(max_concurrent));
349
+ let mut handles = Vec::new();
350
+
351
+ for item in items {
352
+ let permit = sem.clone().acquire_owned().await?;
353
+ handles.push(tokio::spawn(async move {
354
+ let _permit = permit; // drop on completion
355
+ tokio::select! {
356
+ result = process(item) => result,
357
+ _ = tokio::time::sleep(Duration::from_secs(30)) => {
358
+ Err(anyhow!("timeout"))
359
+ }
360
+ }
361
+ }));
362
+ }
363
+
364
+ let mut results = Vec::new();
365
+ for handle in handles {
366
+ results.push(handle.await??);
367
+ }
368
+ Ok(results)
369
+ }
370
+ ```
371
+
372
+ ### Kotlin: Coroutines + Flow + Dispatchers
373
+
374
+ ```kotlin
375
+ // ✅ 结构化并发 + 有界并发 + 取消安全
376
+ suspend fun processBatch(items: List<Item>, maxConcurrent: Int = 10): List<Result> {
377
+ val semaphore = Semaphore(maxConcurrent)
378
+
379
+ return coroutineScope {
380
+ items.map { item ->
381
+ async(Dispatchers.IO) {
382
+ semaphore.withPermit {
383
+ process(item)
384
+ }
385
+ }
386
+ }.awaitAll()
387
+ }
388
+ }
389
+
390
+ // ✅ Flow: 流式处理 + 反压
391
+ fun itemStream(): Flow<Result> = flow {
392
+ for (item in fetchAllItems()) {
393
+ emit(process(item))
394
+ }
395
+ }
396
+ .flowOn(Dispatchers.IO)
397
+ .buffer(capacity = 10)
398
+ .catch { e -> logger.error("stream failed", e) }
399
+ ```
400
+
401
+ ### Swift: async/await + TaskGroup + Actors
402
+
403
+ ```swift
404
+ // ✅ 结构化并发 + actor 隔离
405
+ actor ResultCollector {
406
+ private var results: [Result] = []
407
+ func add(_ result: Result) { results.append(result) }
408
+ func all() -> [Result] { results }
409
+ }
410
+
411
+ func processBatch(items: [Item], maxConcurrent: Int = 10) async throws -> [Result] {
412
+ let collector = ResultCollector()
413
+
414
+ try await withThrowingTaskGroup(of: Void.self) { group in
415
+ var active = 0
416
+ for item in items {
417
+ if active >= maxConcurrent {
418
+ try await group.next()
419
+ active -= 1
420
+ }
421
+ group.addTask {
422
+ let result = try await process(item)
423
+ await collector.add(result)
424
+ }
425
+ active += 1
426
+ }
427
+ }
428
+
429
+ return await collector.all()
430
+ }
431
+ ```
432
+
433
+ ### C#: async/await + SemaphoreSlim + CancellationToken
434
+
435
+ ```csharp
436
+ // ✅ 有界并发 + 取消 + 异常处理
437
+ async Task<List<Result>> ProcessBatchAsync(
438
+ List<Item> items,
439
+ int maxConcurrent = 10,
440
+ CancellationToken ct = default)
441
+ {
442
+ using var semaphore = new SemaphoreSlim(maxConcurrent);
443
+ var tasks = items.Select(async item =>
444
+ {
445
+ await semaphore.WaitAsync(ct);
446
+ try
447
+ {
448
+ return await ProcessAsync(item, ct);
449
+ }
450
+ finally
451
+ {
452
+ semaphore.Release();
453
+ }
454
+ });
455
+
456
+ var results = await Task.WhenAll(tasks);
457
+ return results.ToList();
458
+ }
459
+ ```
460
+
461
+ ### TypeScript: Worker-pool 并发限制
462
+
463
+ ```typescript
464
+ // ✅ Worker-pool pattern: 固定数量 worker 竞争任务队列
465
+ // 结果按原始索引赋值,保证输出顺序与输入一致。
466
+ async function processWithLimit<T, R>(
467
+ items: T[],
468
+ fn: (item: T) => Promise<R>,
469
+ limit: number,
470
+ ): Promise<R[]> {
471
+ const results: R[] = [];
472
+ let index = 0;
473
+
474
+ const workers = Array.from({ length: limit }, async () => {
475
+ while (index < items.length) {
476
+ const i = index++;
477
+ results[i] = await fn(items[i]);
478
+ }
479
+ });
480
+
481
+ await Promise.all(workers);
482
+ return results;
483
+ }
484
+ ```
485
+
486
+ ---
487
+
488
+ ## Review Checklist
489
+
490
+ ### 基本检查
491
+ - [ ] 并发任务有明确的退出机制(不会泄漏)
492
+ - [ ] 共享状态有适当保护(mutex、actor、channel)
493
+ - [ ] 没有在异步上下文中执行阻塞操作
494
+ - [ ] 取消信号正确传播到所有子任务
495
+
496
+ ### 架构检查
497
+ - [ ] 使用结构化并发(TaskGroup / coroutineScope / errgroup)
498
+ - [ ] 并发数有上限(semaphore / bounded channel)
499
+ - [ ] 长时间运行的任务支持超时
500
+ - [ ] 背压机制防止内存膨胀
501
+
502
+ ### 性能检查
503
+ - [ ] 并发粒度合理(不过细也不过粗)
504
+ - [ ] I/O 密集使用 async,CPU 密集使用线程/进程
505
+ - [ ] 锁的持有时间最小化
506
+ - [ ] 没有不必要的 await(可并行的操作串行执行)
507
+
508
+ ### 语言特定
509
+ - [ ] Go: context 传播、errgroup 使用、channel 缓冲合理
510
+ - [ ] Python: 事件循环不阻塞、TaskGroup 管理生命周期
511
+ - [ ] Rust: spawn_blocking 隔离阻塞操作、select! 处理超时
512
+ - [ ] Kotlin: coroutineScope 结构化并发、Dispatchers 选择正确
513
+ - [ ] Swift: @MainActor 保护 UI、actor 隔离可变状态
514
+ - [ ] C#: CancellationToken 传播、ConfigureAwait(false) 在库代码中
515
+ - [ ] TypeScript: Promise.all + 并发限制、AbortController 取消