Files
taskbuffer/readme.hints.md

9.0 KiB

Taskbuffer Hints

Task Constraint System (v5.0.0+) — Breaking Changes

  • TaskRunner removed — replaced by TaskManager + TaskConstraintGroup
  • blockingTasks removed from Task — use TaskConstraintGroup with maxConcurrent: 1
  • execDelay removed from Task — use TaskConstraintGroup with cooldownMs
  • finished promise removed from Task — no longer needed
  • Task generic signature: Task<T, TSteps, TData> (3rd param added for typed data)

Task.data

  • Task constructor accepts optional data?: TData (defaults to {})
  • Typed data bag accessible as task.data

TaskConstraintGroup

  • new TaskConstraintGroup<TData>({ name, constraintKeyForExecution, maxConcurrent?, cooldownMs?, shouldExecute?, rateLimit?, resultSharingMode? })
  • constraintKeyForExecution(task, input?) returns a string key (constraint applies) or null (skip). Receives both task and runtime input.
  • shouldExecute(task, input?) — optional pre-execution check. Returns false to skip (deferred resolves undefined). Can be async.
  • maxConcurrent (default: Infinity) — max concurrent tasks per key
  • cooldownMs (default: 0) — minimum ms gap between completions per key
  • rateLimit (optional) — { maxPerWindow: number, windowMs: number } sliding window rate limiter. Counts both running + completed tasks in window.
  • resultSharingMode (default: 'none') — 'none' | 'share-latest'. When 'share-latest', queued tasks for the same key resolve with the first task's result without executing.
  • Methods: getConstraintKey(task, input?), checkShouldExecute(task, input?), canRun(key), acquireSlot(key), releaseSlot(key), getCooldownRemaining(key), getRateLimitDelay(key), getNextAvailableDelay(key), getRunningCount(key), recordResult(key, result), getLastResult(key), hasResultSharing(), reset()
  • ITaskExecution<TData> type exported from index — { task, input } tuple

Rate Limiting (v6.1.0+)

  • Sliding window rate limiter: rateLimit: { maxPerWindow: N, windowMs: ms }
  • Counts running + completed tasks against the window cap
  • Per-key independence: saturating key A doesn't block key B
  • Composable with maxConcurrent and cooldownMs
  • getNextAvailableDelay(key) returns Math.max(cooldownRemaining, rateLimitDelay) — unified "how long until I can run" answer
  • Drain timer auto-schedules based on shortest delay across all constraints

Result Sharing (v6.1.0+)

  • resultSharingMode: 'share-latest' — queued tasks for the same key get the first task's result without executing
  • Only successful results are shared (errors from catchErrors: true or thrown errors are NOT shared)
  • shouldExecute is NOT called for shared results (the task's purpose was already fulfilled)
  • lastResults persists until reset() — for time-bounded sharing, use shouldExecute to control staleness
  • Composable with rate limiting: rate-limited waiters get shared result without waiting for the window

TaskManager Constraint Integration

  • manager.addConstraintGroup(group) / manager.removeConstraintGroup(name)
  • triggerTaskByName(), triggerTask(), addExecuteRemoveTask(), cron callbacks all route through triggerTaskConstrained()
  • triggerTaskConstrained(task, input?) — evaluates constraints, queues if blocked, drains after completion
  • Cooldown-blocked entries auto-drain via timer

Exported from index.ts

  • TaskConstraintGroup class
  • ITaskConstraintGroupOptions, IRateLimitConfig, TResultSharingMode types

Error Handling (v3.6.0+)

  • Task now has catchErrors constructor option (default: false)
  • Default behavior: trigger() rejects when taskFunction throws (breaking change from pre-3.6)
  • Set catchErrors: true to swallow errors (old behavior) - returns undefined on error
  • Error state tracked via lastError?: Error, errorCount: number, clearError()
  • getMetadata() status uses all four values: 'idle' | 'running' | 'completed' | 'failed'
  • All peripheral classes (Taskchain, Taskparallel, BufferRunner, TaskDebounced, TaskManager) have proper error propagation/handling
  • console.log calls replaced with logger.log() throughout

Error Context Improvements

  • TaskChain: Errors now wrap the original with context: chain name, failing task name, and task index. Original error preserved via .cause
  • BufferRunner: When catchErrors: false, buffered task errors now reject the trigger promise (via CycleCounter.informOfCycleError) instead of silently resolving with undefined
  • TaskChain stubs completed: removeTask(task) returns boolean, shiftTask() returns Task | undefined

Task Labels (v4.1.0+)

  • Task constructor accepts optional labels?: Record<string, string>
  • Helper methods: setLabel(key, value), getLabel(key), removeLabel(key), hasLabel(key, value?)
  • getMetadata() includes labels (shallow copy)
  • TaskManager.getTasksByLabel(key, value) returns matching Task[]
  • TaskManager.getTasksMetadataByLabel(key, value) returns matching ITaskMetadata[]

Push-Based Events (v4.1.0+)

  • Task.eventSubject: rxjs Subject<ITaskEvent> emitting 'started', 'step', 'completed', 'failed' events
  • TaskManager.taskSubject: aggregated Subject<ITaskEvent> from all added tasks
  • TaskManager.removeTask(task) unsubscribes and removes from map
  • TaskManager.stop() cleans up all event subscriptions
  • Exported types: ITaskEvent, TTaskEventType

Project Structure

  • Source in ts/, web components in ts_web/
  • Tests in test/ - naming: *.node.ts, *.chromium.ts (preferred), *.both.ts
    • Note: *.browser.ts is deprecated, use *.chromium.ts for browser tests
  • Logger: ts/taskbuffer.logging.ts exports logger (ConsoleLog from smartlog)
  • Build: pnpm build (tsbuild tsfolders)
  • Test: pnpm test or tstest test/test.XX.name.ts --verbose

Web Components (ts_web/)

  • Uses @design.estate/dees-element with TC39 decorators
  • Decorators require the accessor keyword:
    @property({ type: String })
    accessor myProp = 'default';
    
    @state()
    accessor count = 0;
    

Service Lifecycle System (v7.0.0+)

Service

  • new Service<T>(name) or new Service<T>(options: IServiceOptions<T>)
  • Builder pattern: .critical(), .optional(), .dependsOn(...), .withStart(fn), .withStop(fn), .withHealthCheck(fn, config?), .withRetry(config), .withStartupTimeout(ms), .withLabels(labels)
  • Subclass pattern: override serviceStart(), serviceStop(), serviceHealthCheck()
  • State machine: stoppedstartingrunningdegradedfailedstopping
  • service.instance — stores the value returned from start() (e.g. a database pool)
  • withStop(fn) and withHealthCheck(fn) receive the instance as argument: (instance: T) => Promise<void>
  • waitForState(target, timeoutMs?), waitForRunning(timeoutMs?), waitForStopped(timeoutMs?) — programmatic readiness gates
  • Per-service startup timeout via withStartupTimeout(ms) or startupTimeoutMs in options
  • Labels: setLabel, getLabel, removeLabel, hasLabel, withLabels
  • Health checks: configurable via IHealthCheckConfig with intervalMs, timeoutMs, failuresBeforeDegraded, failuresBeforeFailed
  • Auto-restart on health failure: autoRestart: true in IHealthCheckConfig with maxAutoRestarts, autoRestartDelayMs, autoRestartBackoffFactor
  • Events via eventSubject: 'started', 'stopped', 'failed', 'degraded', 'recovered', 'retrying', 'healthCheck', 'autoRestarting'

ServiceManager

  • manager.addService(service) / manager.addServiceFromOptions(options) / manager.removeService(name)
  • Dependency-ordered startup via topological sort (Kahn's algorithm), level-by-level parallel
  • Critical service failure aborts startup with rollback; optional service failure continues
  • Retry with exponential backoff + jitter
  • Reverse-dependency-ordered shutdown with per-service timeout
  • restartService(name) — cascade stops dependents, restarts target, restarts dependents
  • getHealth() — aggregated 'healthy' | 'degraded' | 'unhealthy' status
  • getServicesByLabel(key, value) / getServicesStatusByLabel(key, value) — label-based queries
  • Circular dependency detection
  • Global startup timeout enforcement via startupTimeoutMs in IServiceManagerOptions

Dependencies (as of v7.0.0)

  • @design.estate/dees-element ^2.2.3 - TC39 decorators with accessor keyword
  • @push.rocks/lik ^6.3.1 - Data structures
  • @push.rocks/smartdelay ^3.0.5 - Delay utilities
  • @push.rocks/smartlog ^3.2.1 - Logging
  • @push.rocks/smartpromise ^4.2.3 - Promise utilities
  • @push.rocks/smartrx ^3.0.10 - RxJS wrapper
  • @push.rocks/smarttime ^4.2.3 - Time/cron utilities
  • @push.rocks/smartunique ^3.0.9 - Unique ID generation
  • @git.zone/tsbuild ^4.3.0 - Build tool
  • @git.zone/tsbundle ^2.9.1 - Bundler (for browser tests)
  • @git.zone/tsrun ^2.0.1 - TypeScript runner
  • @git.zone/tstest ^3.5.0 - Test runner (supports .chromium.ts files)
  • @types/node ^25.5.0 - Node.js type definitions