con un clic
async-concurrency
// Decision frameworks for async and concurrency. When to use async vs threading vs multiprocessing, and how to avoid common pitfalls.
// Decision frameworks for async and concurrency. When to use async vs threading vs multiprocessing, and how to avoid common pitfalls.
Comprehensive prompting guide for LTX-2 video generation model. Covers cinematic storytelling, camera language, character direction, dialogue formatting, visual styling, and audio descriptions. Master the art of crafting detailed, story-driven prompts that turn creative visions into stunning AI-generated videos.
Design and run A/B tests that produce valid, actionable results. Covers hypothesis design, sample size, metrics selection, and analysis.
Patterns for building LLM-powered agents that can reason, plan, and use tools. Covers agent architectures (ReAct, Plan-and-Execute), tool design, multi-agent systems, memory management, and production deployment considerations.
Decision frameworks for using AI Skills effectively. When to invoke skills, how to compose them, and integration patterns.
Set up analytics tracking that informs decisions. Covers GA4 implementation, event design, UTM strategy, and tracking plans.
REST API design principles and best practices. Use when designing new APIs, reviewing API contracts, or improving existing endpoints. Covers resource modeling, HTTP semantics, error handling, versioning, and documentation.
| name | async-concurrency |
| description | Decision frameworks for async and concurrency. When to use async vs threading vs multiprocessing, and how to avoid common pitfalls. |
| license | MIT |
| allowed-tools | Read Edit Bash |
| version | 2.0.0 |
| tags | ["async","concurrency","threading","parallelism","performance"] |
| category | development/patterns |
| variables | {"language":{"type":"string","description":"Programming language","enum":["python","javascript"],"default":"python"},"workload":{"type":"string","description":"Type of workload","enum":["io-bound","cpu-bound","mixed"],"default":"io-bound"}} |
| scope | {"triggers":["async","concurrent","parallel","threading","race condition"]} |
You help choose the right concurrency approach and avoid common pitfalls.
WHAT TYPE OF WORK?
I/O-bound (network, disk, database):
├── Python → asyncio (preferred) or threading
├── JavaScript → async/await (native)
└── Many concurrent connections → async always
CPU-bound (computation, data processing):
├── Python → multiprocessing (bypasses GIL)
├── JavaScript → Worker threads
└── Single heavy task → dedicated process/worker
Mixed workload:
├── Async for I/O + process pool for CPU
└── Don't block event loop with CPU work
| Workload | Python | JavaScript |
|---|---|---|
| API calls | asyncio + aiohttp | async/await + fetch |
| File I/O | asyncio or ThreadPoolExecutor | fs/promises |
| Database queries | Async driver (asyncpg, motor) | Async driver |
| Data processing | multiprocessing | Worker threads |
| Image/video | ProcessPoolExecutor | Worker or WASM |
{% if language == "python" %}
PYTHON DECISION TREE:
Need to wait for external resources?
├── Yes → asyncio (async/await)
└── No ↓
Need true parallelism for CPU work?
├── Yes → multiprocessing
└── No ↓
Calling blocking library that can't be async?
├── Yes → threading (or run_in_executor)
└── No → Single-threaded is fine
{% if workload == "io-bound" %}
When to use: HTTP clients, database queries, file I/O, websockets
Key patterns:
# Concurrent requests (don't await one by one)
results = await asyncio.gather(*[fetch(url) for url in urls])
# Rate limiting with semaphore
semaphore = asyncio.Semaphore(10)
async with semaphore:
result = await fetch(url)
# Timeout on external calls (always!)
result = await asyncio.wait_for(fetch(url), timeout=30.0)
# Handle partial failures
results = await asyncio.gather(*tasks, return_exceptions=True)
successes = [r for r in results if not isinstance(r, Exception)]
{% elif workload == "cpu-bound" %}
When to use: Data processing, image manipulation, ML inference, compression
Key patterns:
from concurrent.futures import ProcessPoolExecutor
# Process pool for CPU work
def process_item(item):
return heavy_computation(item)
with ProcessPoolExecutor() as executor:
results = list(executor.map(process_item, items))
# Combine with async (don't block event loop)
async def async_cpu_work(data):
loop = asyncio.get_event_loop()
return await loop.run_in_executor(process_pool, cpu_func, data)
{% elif workload == "mixed" %}
When to use: Web server that does both I/O and computation
# Async for I/O, executor for CPU
async def handle_request(data):
# I/O - async
external_data = await fetch_from_api(data['url'])
# CPU - offload to process pool
loop = asyncio.get_event_loop()
processed = await loop.run_in_executor(
process_pool,
heavy_computation,
external_data
)
return processed
{% endif %}
| Anti-Pattern | Problem | Fix |
|---|---|---|
time.sleep() in async | Blocks event loop | await asyncio.sleep() |
requests.get() in async | Blocking I/O | Use aiohttp |
| Fire-and-forget tasks | Task may be GC'd | Store in set, await later |
| Global mutable state with threads | Race conditions | Use locks or queues |
| Sharing objects between processes | Pickle overhead | Use shared memory or queues |
{% elif language == "javascript" %}
JAVASCRIPT DECISION TREE:
Waiting for network/disk?
├── Yes → async/await (native)
└── No ↓
CPU-intensive computation?
├── Yes → Worker threads (Node) or Web Workers (browser)
└── No → Synchronous is fine
Blocking the event loop?
├── Yes → Move to Worker
└── No → Keep in main thread
{% if workload == "io-bound" %}
Key patterns:
// Concurrent requests
const results = await Promise.all(urls.map(url => fetch(url)));
// Handle partial failures
const results = await Promise.allSettled(urls.map(url => fetch(url)));
const successes = results.filter(r => r.status === 'fulfilled');
// Rate limiting (batch processing)
async function batchProcess<T, R>(
items: T[],
fn: (item: T) => Promise<R>,
concurrency: number
): Promise<R[]> {
const results: R[] = [];
for (let i = 0; i < items.length; i += concurrency) {
const batch = items.slice(i, i + concurrency);
results.push(...await Promise.all(batch.map(fn)));
}
return results;
}
{% elif workload == "cpu-bound" %}
Node.js Worker Threads:
import { Worker, isMainThread, parentPort, workerData } from 'worker_threads';
// In worker file
if (!isMainThread) {
const result = heavyComputation(workerData);
parentPort?.postMessage(result);
}
// In main thread
function runInWorker(data: unknown): Promise<unknown> {
return new Promise((resolve, reject) => {
const worker = new Worker('./worker.js', { workerData: data });
worker.on('message', resolve);
worker.on('error', reject);
});
}
{% endif %}
| Anti-Pattern | Problem | Fix |
|---|---|---|
| Sync loops with await inside | Sequential, not parallel | Promise.all() outside loop |
| Unhandled promise rejections | Silent failures | Always catch or use allSettled |
| Long computation in main thread | Blocks UI/event loop | Move to Worker |
Missing AbortController | Can't cancel requests | Add abort signal |
{% endif %}
RACE CONDITION SCENARIOS:
Read-modify-write:
Thread A reads 0, Thread B reads 0
Both write 1, expected 2
Fix: Lock/mutex around operation
Check-then-act:
if (file.exists()) → file may be deleted before next line
Fix: Atomic operation or lock
Publish before ready:
Object shared before fully initialized
Fix: Immutable objects or initialization locks
Prevention strategies by language:
{% if language == "python" %}
| Strategy | Use Case | Code |
|---|---|---|
asyncio.Lock | Async shared state | async with lock: |
threading.Lock | Thread shared state | with lock: |
Queue | Thread-safe communication | queue.put(), queue.get() |
| Immutable data | Avoid mutation | @dataclass(frozen=True) |
| {% else %} | ||
| Strategy | Use Case | Code |
| ---------- | ---------- | ------ |
| Message passing | Workers | postMessage() / onmessage |
Atomics | SharedArrayBuffer | Atomics.add(view, 0, 1) |
| Single-threaded | Main thread | JS is already single-threaded |
| Mutex class | Async critical sections | Custom lock implementation |
| {% endif %} |
BACKPRESSURE DECISION:
Producer faster than consumer?
├── Bounded queue (block producer when full)
├── Drop oldest/newest items
└── Rate limit producer
Memory growing unbounded?
├── Set queue maxsize
└── Process in batches
{% if language == "python" %}
queue = asyncio.Queue(maxsize=100) # Blocks when full
{% else %}
// Process in controlled batches, not all at once
for (let i = 0; i < items.length; i += BATCH_SIZE) {
await processBatch(items.slice(i, i + BATCH_SIZE));
}
{% endif %}
SHUTDOWN SEQUENCE:
1. Stop accepting new work
2. Wait for in-flight work (with timeout)
3. Cancel remaining tasks
4. Clean up resources
{% if language == "python" %}
async def shutdown(tasks: set[asyncio.Task], timeout: float = 30):
for task in tasks:
task.cancel()
await asyncio.wait(tasks, timeout=timeout)
{% else %}
// AbortController for cancellation
const controller = new AbortController();
fetch(url, { signal: controller.signal });
// On shutdown:
controller.abort();
{% endif %}
| Symptom | Likely Cause | Debug Approach |
|---|---|---|
| Hangs indefinitely | Deadlock or await on never-resolving promise | Add timeouts, log task states |
| Inconsistent results | Race condition | Add locks, review shared state |
| Memory growth | Unbounded queues or fire-and-forget tasks | Track task count, set queue limits |
| Slow despite async | Blocking call in event loop | Profile, check for sync I/O |
{% if language == "python" %}
# Enable debug mode
asyncio.get_event_loop().set_debug(True)
# Shows: slow callbacks, unawaited coroutines, etc.
{% endif %}
error-handling - Exception handling in concurrent codeperformance-optimization - Profiling async code