From b1725cbdf95d3a626b7c04858af1cea7ce392896 Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Tue, 26 Aug 2025 20:42:52 +0000 Subject: [PATCH] fix(task): Implement core Task execution flow, buffering and lifecycle; update README with generics and buffer docs --- .../document_symbols_cache_v23-06-25.pkl | Bin 29235 -> 65421 bytes changelog.md | 11 + readme.md | 316 ++++++++++++++++++ ts/00_commitinfo_data.ts | 2 +- 4 files changed, 328 insertions(+), 1 deletion(-) diff --git a/.serena/cache/typescript/document_symbols_cache_v23-06-25.pkl b/.serena/cache/typescript/document_symbols_cache_v23-06-25.pkl index 656196ce9c720d4595a488bcb429738ec2cec05b..ea45ceb297ffae3ad9e9590632b9032f6d93977c 100644 GIT binary patch literal 65421 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 TqQHi`{{?zk_jvPov!3~1A{o|~ delta 34 mcmeDE&%F5wqd)`8RE;7AFsPlP(W5-MQB-!LE=v(psU85r8wwHt diff --git a/changelog.md b/changelog.md index 1e71858..69f61d0 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,16 @@ # Changelog +## 2025-08-26 - 3.1.10 - fix(task) +Implement core Task execution flow, buffering and lifecycle; update README with generics and buffer docs + +- Implement Task.runTask including preTask/afterTask chaining, touched-task cycle prevention and error handling. +- Add Task helpers: extractTask, isTask, isTaskTouched and emptyTaskFunction (resolved promise). +- Introduce task lifecycle coordination: finished promise, resolveFinished, and blockingTasks to await dependent tasks. +- Support taskSetup/setupValue, execDelay handling, and wait-for-blocking-tasks before execution. +- Wire up trigger() to choose buffered vs unbuffered execution (triggerBuffered / triggerUnBuffered) and integrate BufferRunner. +- Improve logging and safer promise handling (caught errors are logged). +- Update README with extended TypeScript generics examples and expanded buffer behavior and strategies documentation. + ## 2025-08-26 - 3.1.9 - fix(tests) Update CI workflows, fix tests and refresh README/package metadata diff --git a/readme.md b/readme.md index 1c676ba..260a246 100644 --- a/readme.md +++ b/readme.md @@ -72,6 +72,322 @@ const myTask = new Task({ const result = await myTask.trigger(); ``` +## TypeScript Generics Support 🔬 + +TaskBuffer leverages TypeScript's powerful generics system for complete type safety across your task chains and workflows. + +### Generic Task Functions + +Tasks support generic type parameters for both input and output types: + +```typescript +import { Task, ITaskFunction } from '@push.rocks/taskbuffer'; + +// Define typed interfaces +interface UserData { + id: string; + name: string; + email: string; +} + +interface ProcessedUser { + userId: string; + displayName: string; + normalized: boolean; +} + +// Create strongly typed tasks +const processUserTask = new Task({ + name: 'ProcessUser', + taskFunction: async (user: UserData): Promise => { + return { + userId: user.id, + displayName: user.name.toUpperCase(), + normalized: true + }; + } +}); + +// Type safety enforced at compile time +const result: ProcessedUser = await processUserTask.trigger({ + id: '123', + name: 'John Doe', + email: 'john@example.com' +}); +``` + +### Generic Setup Values + +Tasks can accept setup values through generics, perfect for configuration: + +```typescript +interface TaskConfig { + apiEndpoint: string; + retryCount: number; + timeout: number; +} + +const configuredTask = new Task({ + name: 'ConfiguredTask', + taskSetup: async () => ({ + apiEndpoint: 'https://api.example.com', + retryCount: 3, + timeout: 5000 + }), + taskFunction: async (data: any, setupValue: TaskConfig) => { + // setupValue is fully typed! + for (let i = 0; i < setupValue.retryCount; i++) { + try { + return await fetchWithTimeout( + setupValue.apiEndpoint, + setupValue.timeout + ); + } catch (error) { + if (i === setupValue.retryCount - 1) throw error; + } + } + } +}); +``` + +### Type-Safe Task Chains + +Chain tasks with preserved type flow: + +```typescript +// Each task knows its input and output types +const fetchTask = new Task({ + name: 'FetchUsers', + taskFunction: async (): Promise => { + return await api.getUsers(); + } +}); + +const filterTask = new Task({ + name: 'FilterActive', + taskFunction: async (users: UserData[]): Promise => { + return users.filter(user => user.isActive); + } +}); + +const mapTask = new Task({ + name: 'MapToProcessed', + taskFunction: async (users: UserData[]): Promise => { + return users.map(transformUser); + } +}); + +// Type safety flows through the chain +const chain = new Taskchain({ + name: 'UserPipeline', + taskArray: [fetchTask, filterTask, mapTask] +}); + +const finalResult: ProcessedUser[] = await chain.trigger(); +``` + +## Buffer Behavior Deep Dive 🌊 + +The buffer system in TaskBuffer provides intelligent control over concurrent executions, preventing system overload while maximizing throughput. + +### How Buffering Works + +When a task is buffered, TaskBuffer manages a queue of executions: + +```typescript +const bufferedTask = new Task({ + name: 'BufferedOperation', + taskFunction: async (data) => { + console.log(`Processing: ${data}`); + await simulateWork(); + return `Processed: ${data}`; + }, + buffered: true, + bufferMax: 3 // Maximum 3 concurrent executions +}); + +// Trigger 10 executions rapidly +for (let i = 0; i < 10; i++) { + bufferedTask.trigger(`Item ${i}`); +} + +// What happens: +// 1. First 3 tasks start immediately +// 2. Items 4-10 are queued +// 3. As each task completes, next queued item starts +// 4. Never more than 3 tasks running simultaneously +``` + +### Buffer Truncation Behavior + +When buffer limit is reached, new calls are intelligently managed: + +```typescript +const truncatingTask = new Task({ + name: 'TruncatingBuffer', + taskFunction: async (data) => { + await processData(data); + }, + buffered: true, + bufferMax: 5 // Maximum 5 in buffer +}); + +// Rapid fire 100 calls +for (let i = 0; i < 100; i++) { + truncatingTask.trigger(`Data ${i}`); +} + +// Buffer behavior: +// - First 5 calls: Added to buffer and start processing +// - Calls 6-100: Each overwrites the 5th buffer slot +// - Result: Only processes items 0,1,2,3, and 99 (last one) +// - This prevents memory overflow in high-frequency scenarios +``` + +### Advanced Buffer Strategies + +#### 1. **Sliding Window Buffer** +Perfect for real-time data processing where only recent items matter: + +```typescript +const slidingWindowTask = new Task({ + name: 'SlidingWindow', + taskFunction: async (data) => { + return await analyzeRecentData(data); + }, + buffered: true, + bufferMax: 10, // Keep last 10 items + execDelay: 100 // Process every 100ms +}); + +// In a real-time stream scenario +dataStream.on('data', (chunk) => { + slidingWindowTask.trigger(chunk); + // Older items automatically dropped when buffer full +}); +``` + +#### 2. **Throttled Buffer** +Combine buffering with execution delays for rate limiting: + +```typescript +const apiRateLimiter = new Task({ + name: 'RateLimitedAPI', + taskFunction: async (request) => { + return await api.call(request); + }, + buffered: true, + bufferMax: 10, // Max 10 queued requests + execDelay: 1000 // 1 second between executions +}); + +// Requests are queued and executed at 1/second +// Prevents API rate limit violations +``` + +#### 3. **Priority Buffer** (Custom Implementation) +Implement priority queuing with buffer management: + +```typescript +class PriorityBufferedTask extends Task { + private priorityQueue: Array<{data: any, priority: number}> = []; + + constructor(options) { + super({ + ...options, + taskFunction: async (item) => { + // Process based on priority + return await this.processByPriority(item); + } + }); + } + + triggerWithPriority(data: any, priority: number) { + if (this.priorityQueue.length >= this.bufferMax) { + // Remove lowest priority item if buffer full + this.priorityQueue.sort((a, b) => b.priority - a.priority); + this.priorityQueue.pop(); + } + this.priorityQueue.push({data, priority}); + this.priorityQueue.sort((a, b) => b.priority - a.priority); + return this.trigger(this.priorityQueue.shift()); + } +} +``` + +### Buffer Monitoring + +Track buffer utilization and performance: + +```typescript +const monitoredTask = new Task({ + name: 'MonitoredBuffer', + taskFunction: async (data) => { + const startTime = Date.now(); + const result = await processData(data); + console.log(`Processing time: ${Date.now() - startTime}ms`); + console.log(`Buffer utilization: ${monitoredTask.bufferRunner.bufferCounter}/${monitoredTask.bufferMax}`); + return result; + }, + buffered: true, + bufferMax: 20 +}); + +// Monitor buffer saturation +setInterval(() => { + const utilization = (monitoredTask.bufferRunner.bufferCounter / monitoredTask.bufferMax) * 100; + if (utilization > 80) { + console.warn(`Buffer near capacity: ${utilization.toFixed(1)}%`); + } +}, 1000); +``` + +### Buffer Best Practices + +1. **Choose appropriate buffer sizes**: + - I/O operations: 5-10 concurrent + - CPU-intensive: Number of cores + - API calls: Based on rate limits + +2. **Handle buffer overflow gracefully**: + ```typescript + const task = new Task({ + taskFunction: async (data) => { + try { + return await process(data); + } catch (error) { + if (error.code === 'BUFFER_OVERFLOW') { + // Implement backoff strategy + await delay(1000); + return task.trigger(data); + } + throw error; + } + }, + buffered: true, + bufferMax: 10 + }); + ``` + +3. **Monitor and adjust dynamically**: + ```typescript + // Adjust buffer size based on system load + const adaptiveTask = new Task({ + name: 'AdaptiveBuffer', + taskFunction: async (data) => { + const cpuLoad = await getSystemLoad(); + if (cpuLoad > 0.8) { + adaptiveTask.bufferMax = Math.max(2, adaptiveTask.bufferMax - 1); + } else if (cpuLoad < 0.5) { + adaptiveTask.bufferMax = Math.min(20, adaptiveTask.bufferMax + 1); + } + return await process(data); + }, + buffered: true, + bufferMax: 10 + }); + ``` + ### Buffered Execution (Rate Limiting) Perfect for API calls or database operations that need throttling: diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 2cd3e7e..608ab29 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@push.rocks/taskbuffer', - version: '3.1.9', + version: '3.1.10', description: 'A flexible task management library supporting TypeScript, allowing for task buffering, scheduling, and execution with dependency management.' }