Skip to content

TaskListProcessor is a .NET utility for managing and monitoring asynchronous tasks, providing concurrent execution, result tracking, and detailed telemetry.

License

Notifications You must be signed in to change notification settings

markhazleton/TaskListProcessor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

33 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸš€ TaskListProcessor

.NET License Build Status NuGet

A modern, enterprise-grade .NET 9.0 library for orchestrating asynchronous operations with comprehensive telemetry, circuit breakers, dependency injection, and advanced scheduling capabilities.


πŸ“‘ Table of Contents


✨ Overview

TaskListProcessor is a production-ready .NET 9.0 library designed to solve complex asynchronous orchestration challenges in modern applications. Built with enterprise-grade patterns including dependency injection, circuit breakers, task scheduling, and comprehensive telemetry, it provides a robust foundation for high-throughput, fault-tolerant systems.

🎯 Why TaskListProcessor?

The Problem: Modern applications require sophisticated coordination of multiple async operationsβ€”API calls, database queries, file I/O, microservice interactionsβ€”while maintaining resilience, observability, and performance under varying loads.

The Solution: TaskListProcessor provides a battle-tested, enterprise-ready framework with:

  • πŸ›‘οΈ Fault Isolation: Circuit breakers and individual task failure isolation
  • πŸ“Š Enterprise Observability: OpenTelemetry integration with rich metrics and tracing
  • ⚑ Advanced Scheduling: Priority-based, dependency-aware task execution
  • 🎯 Type Safety: Strongly-typed results with comprehensive error categorization
  • πŸ”§ Dependency Injection: Native .NET DI integration with decorator pattern support
  • πŸ—οΈ Interface Segregation: Clean, focused interfaces following SOLID principles

πŸ”₯ Key Features

Core Processing Capabilities

  • πŸš€ Concurrent Execution: Parallel task processing with configurable concurrency limits and load balancing
  • πŸ›‘οΈ Circuit Breaker Pattern: Automatic failure detection and cascading failure prevention
  • πŸ“Š Rich Telemetry: Comprehensive timing, success rates, error tracking, and OpenTelemetry integration
  • 🎯 Type Safety: Strongly-typed results with full IntelliSense support and error categorization
  • ⏱️ Timeout & Cancellation: Built-in support for graceful shutdown and per-task timeouts
  • πŸ”„ Task Dependencies: Dependency resolution with topological sorting and execution ordering

Enterprise Architecture Features

  • πŸ—οΈ Dependency Injection: Native .NET DI integration with fluent configuration API
  • 🎨 Interface Segregation: Clean, focused interfaces following SOLID principles
  • οΏ½ Decorator Pattern: Pluggable cross-cutting concerns (logging, metrics, circuit breakers)
  • πŸ“ˆ Advanced Scheduling: Priority-based, FIFO, LIFO, and custom scheduling strategies
  • 🧡 Thread Safety: Lock-free concurrent collections and thread-safe operations
  • πŸ’Ύ Memory Optimization: Object pooling and efficient memory management

Developer Experience

  • οΏ½ Structured Logging: Integration with Microsoft.Extensions.Logging and Serilog
  • πŸ” Health Checks: Built-in health monitoring and diagnostic capabilities
  • οΏ½ Streaming Results: Async enumerable support for real-time result processing
  • πŸ§ͺ Testing Support: Comprehensive test helpers and mock-friendly interfaces
  • πŸ“– Rich Documentation: Extensive XML documentation and practical examples

πŸ—οΈ Architecture

TaskListProcessor implements a modern, enterprise-ready architecture with clear separation of concerns:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Dependency Injection Layer                  β”‚
β”‚        services.AddTaskListProcessor().WithAllDecorators()     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
                                β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      Decorator Chain                            β”‚
β”‚  LoggingDecorator β†’ MetricsDecorator β†’ CircuitBreakerDecorator  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
                                β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Interface Segregation Layer                 β”‚
β”‚  ITaskProcessor β”‚ ITaskBatchProcessor β”‚ ITaskStreamProcessor   β”‚
β”‚              ITaskTelemetryProvider                           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
                                β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Core Processing Engine                       β”‚
β”‚            TaskListProcessorEnhanced (Backward Compatible)     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚                 β”‚                 β”‚
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”
    β”‚ TaskDefinition   β”‚ β”‚TaskTelemetryβ”‚ β”‚TaskProgress  β”‚
    β”‚ + Dependencies   β”‚ β”‚ + Metrics   β”‚ β”‚ + Reporting  β”‚
    β”‚ + Priority       β”‚ β”‚ + Tracing   β”‚ β”‚ + Streaming  β”‚
    β”‚ + Scheduling     β”‚ β”‚ + Health    β”‚ β”‚ + Estimates  β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Core Components

  • Interface Layer: Clean, focused interfaces for different processing scenarios
  • Decorator Layer: Cross-cutting concerns (logging, metrics, circuit breakers)
  • Processing Engine: Thread-safe orchestration with advanced scheduling
  • Telemetry System: Comprehensive observability and health monitoring
  • Dependency Resolution: Topological sorting and execution ordering
  • Circuit Breaker: Cascading failure prevention and automatic recovery

⚑ Quick Start

Installation

# Clone the repository
git clone https://github.com/markhazleton/TaskListProcessor.git
cd TaskListProcessor

# Build the solution
dotnet build

# Run the demo
dotnet run --project examples/TaskListProcessor.Console

Basic Usage (Direct Instantiation)

using TaskListProcessing.Core;
using Microsoft.Extensions.Logging;

// Set up logging (optional but recommended)
using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
var logger = loggerFactory.CreateLogger<Program>();

// Create the processor
using var processor = new TaskListProcessorEnhanced("My Tasks", logger);

// Define your tasks using the factory pattern
var taskFactories = new Dictionary<string, Func<CancellationToken, Task<object?>>>
{
    ["Weather Data"] = async ct => await GetWeatherAsync("London"),
    ["Stock Prices"] = async ct => await GetStockPricesAsync("MSFT"),
    ["User Data"] = async ct => await GetUserDataAsync(userId)
};

// Execute all tasks concurrently
await processor.ProcessTasksAsync(taskFactories, cancellationToken);

// Access results and telemetry
foreach (var result in processor.TaskResults)
{
    Console.WriteLine($"{result.Name}: {(result.IsSuccessful ? "βœ…" : "❌")}");
}

Dependency Injection Usage (Recommended)

using TaskListProcessing.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

// Program.cs
var builder = Host.CreateApplicationBuilder(args);

// Configure TaskListProcessor with decorators
builder.Services.AddTaskListProcessor(options =>
{
    options.MaxConcurrentTasks = 10;
    options.EnableDetailedTelemetry = true;
    options.CircuitBreakerOptions = new() { FailureThreshold = 3 };
})
.WithLogging()
.WithMetrics()
.WithCircuitBreaker();

var host = builder.Build();

// Usage in your services
public class MyService
{
    private readonly ITaskBatchProcessor _processor;
    
    public MyService(ITaskBatchProcessor processor)
    {
        _processor = processor;
    }
    
    public async Task ProcessDataAsync()
    {
        var tasks = new Dictionary<string, Func<CancellationToken, Task<object?>>>
        {
            ["API Call"] = async ct => await CallApiAsync(ct),
            ["DB Query"] = async ct => await QueryDatabaseAsync(ct)
        };
        
        await _processor.ProcessTasksAsync(tasks);
    }
}

πŸ“– Comprehensive Examples

Travel Dashboard (Real-world Scenario)

This example demonstrates fetching weather and activities data for multiple cities:

using var processor = new TaskListProcessorEnhanced("Travel Dashboard", logger);
using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(2));

var cities = new[] { "London", "Paris", "Tokyo", "New York" };
var taskFactories = new Dictionary<string, Func<CancellationToken, Task<object?>>>();

// Create tasks for each city
foreach (var city in cities)
{
    taskFactories[$"{city} Weather"] = ct => weatherService.GetWeatherAsync(city, ct);
    taskFactories[$"{city} Activities"] = ct => activitiesService.GetActivitiesAsync(city, ct);
}

// Execute and handle results
try 
{
    await processor.ProcessTasksAsync(taskFactories, cts.Token);
    
    // Group results by city
    var cityData = processor.TaskResults
        .GroupBy(r => r.Name.Split(' ')[0])
        .ToDictionary(g => g.Key, g => g.ToList());
    
    // Display results with rich formatting
    foreach (var (city, results) in cityData)
    {
        Console.WriteLine($"\n🌍 {city}:");
        foreach (var result in results)
        {
            var status = result.IsSuccessful ? "βœ…" : "❌";
            Console.WriteLine($"  {status} {result.Name.Split(' ')[1]}");
        }
    }
}
catch (OperationCanceledException)
{
    logger.LogWarning("Operation timed out after 2 minutes");
}

Individual Task Execution

For scenarios requiring fine-grained control:

// Execute a single task with full telemetry
var result = await processor.ExecuteTaskAsync(
    "Critical API Call", 
    httpClient.GetStringAsync("https://api.example.com/data"),
    cancellationToken);

if (result.IsSuccessful)
{
    var data = result.Data;
    logger.LogInformation("Received {DataLength} characters", data?.Length ?? 0);
}
else
{
    logger.LogError("API call failed: {Error}", result.ErrorMessage);
}

πŸ”§ Advanced Usage

Task Dependencies & Scheduling

using TaskListProcessing.Models;
using TaskListProcessing.Scheduling;

// Configure with dependency resolution
var options = new TaskListProcessorOptions
{
    DependencyResolver = new TopologicalTaskDependencyResolver(),
    SchedulingStrategy = TaskSchedulingStrategy.Priority,
    MaxConcurrentTasks = Environment.ProcessorCount * 2
};

using var processor = new TaskListProcessorEnhanced("Advanced Tasks", logger, options);

// Define tasks with dependencies and priorities
var taskDefinitions = new[]
{
    new TaskDefinition
    {
        Name = "Initialize",
        Factory = async ct => await InitializeAsync(ct),
        Priority = TaskPriority.High
    },
    new TaskDefinition
    {
        Name = "Process Data",
        Factory = async ct => await ProcessDataAsync(ct),
        Dependencies = new[] { "Initialize" },
        Priority = TaskPriority.Medium
    },
    new TaskDefinition
    {
        Name = "Generate Report",
        Factory = async ct => await GenerateReportAsync(ct),
        Dependencies = new[] { "Process Data" },
        Priority = TaskPriority.Low
    }
};

await processor.ProcessTaskDefinitionsAsync(taskDefinitions);

Circuit Breaker Configuration

var options = new TaskListProcessorOptions
{
    CircuitBreakerOptions = new CircuitBreakerOptions
    {
        FailureThreshold = 5,
        RecoveryTimeout = TimeSpan.FromMinutes(2),
        MinimumThroughput = 10
    }
};

using var processor = new TaskListProcessorEnhanced("Resilient Tasks", logger, options);

// Tasks will automatically trigger circuit breaker on repeated failures
var taskFactories = new Dictionary<string, Func<CancellationToken, Task<object?>>>
{
    ["Resilient API"] = async ct => await CallExternalApiAsync(ct),
    ["Fallback Service"] = async ct => await CallFallbackServiceAsync(ct)
};

await processor.ProcessTasksAsync(taskFactories);

// Check circuit breaker status
var cbStats = processor.CircuitBreakerStats;
if (cbStats?.State == CircuitBreakerState.Open)
{
    Console.WriteLine($"Circuit breaker opened at {cbStats.OpenedAt}");
}

Streaming Results

using TaskListProcessing.Interfaces;

// Inject the stream processor
public class StreamingService
{
    private readonly ITaskStreamProcessor _streamProcessor;
    
    public StreamingService(ITaskStreamProcessor streamProcessor)
    {
        _streamProcessor = streamProcessor;
    }
    
    public async Task ProcessWithStreamingAsync()
    {
        var tasks = CreateLongRunningTasks();
        
        // Process results as they complete
        await foreach (var result in _streamProcessor.ProcessTasksStreamAsync(tasks))
        {
            Console.WriteLine($"Completed: {result.Name} - {result.IsSuccessful}");
            
            // Process result immediately without waiting for all tasks
            await HandleResultAsync(result);
        }
    }
}

Health Monitoring

var options = new TaskListProcessorOptions
{
    HealthCheckOptions = new HealthCheckOptions
    {
        MinSuccessRate = 0.8, // 80% success rate threshold
        MaxAverageExecutionTime = TimeSpan.FromSeconds(5),
        IncludeCircuitBreakerState = true
    }
};

using var processor = new TaskListProcessorEnhanced("Health Monitored", logger, options);

// After processing tasks
var healthResult = processor.PerformHealthCheck();
if (!healthResult.IsHealthy)
{
    Console.WriteLine($"Health check failed: {healthResult.Message}");
}

// Get detailed telemetry
var telemetrySummary = processor.GetTelemetrySummary();
Console.WriteLine($"Success rate: {telemetrySummary.SuccessRate:F1}%");
Console.WriteLine($"Average execution time: {telemetrySummary.AverageExecutionTime:F0}ms");

πŸ“Š Performance & Telemetry

TaskListProcessor provides comprehensive telemetry out of the box:

Built-in Metrics

// Access telemetry after execution
var telemetry = processor.Telemetry;
var successRate = telemetry.Count(t => t.IsSuccessful) / (double)telemetry.Count * 100;
var averageTime = telemetry.Average(t => t.DurationMs);
var throughput = telemetry.Count / telemetry.Max(t => t.DurationMs) * 1000;

Console.WriteLine($"πŸ“Š Success Rate: {successRate:F1}%");
Console.WriteLine($"⏱️ Average Time: {averageTime:F0}ms");
Console.WriteLine($"πŸš€ Throughput: {throughput:F1} tasks/second");

Sample Telemetry Output

=== πŸ“Š TELEMETRY SUMMARY ===
πŸ“ˆ Total Tasks: 16
βœ… Successful: 13 (81.2%)
❌ Failed: 3
⏱️ Average Time: 1,305ms
πŸƒ Fastest: 157ms | 🐌 Slowest: 2,841ms
⏰ Total Execution Time: 20,884ms

=== πŸ“‹ DETAILED TELEMETRY ===
βœ… Successful Tasks (sorted by execution time):
  πŸš€ London Things To Do: 157ms
  πŸš€ Dallas Things To Do: 339ms
  ⚑ Chicago Things To Do: 557ms
  πŸƒ London Weather: 1,242ms
  ...

❌ Failed Tasks:
  πŸ’₯ Sydney Things To Do: ArgumentException after 807ms
  πŸ’₯ Tokyo Things To Do: ArgumentException after 424ms

πŸ› οΈ API Reference

Core Interfaces

Interface Description Key Methods
ITaskProcessor Single task execution ExecuteTaskAsync<T>()
ITaskBatchProcessor Batch processing ProcessTasksAsync(), ProcessTaskDefinitionsAsync()
ITaskStreamProcessor Streaming results ProcessTasksStreamAsync()
ITaskTelemetryProvider Telemetry & health GetTelemetrySummary(), PerformHealthCheck()

TaskListProcessorEnhanced (Backward Compatible)

Method Description Returns
ProcessTasksAsync(taskFactories, progress, ct) Execute multiple tasks concurrently Task
ProcessTaskDefinitionsAsync(definitions, progress, ct) Execute tasks with dependencies Task
ExecuteTaskAsync<T>(name, task, ct) Execute single task with telemetry Task<EnhancedTaskResult<T>>
ProcessTasksStreamAsync(taskFactories, ct) Stream results as they complete IAsyncEnumerable<EnhancedTaskResult<object>>
GetTelemetrySummary() Get comprehensive telemetry TelemetrySummary
PerformHealthCheck() Check processor health HealthCheckResult

Configuration Options

Option Type Default Description
MaxConcurrentTasks int Environment.ProcessorCount * 2 Maximum concurrent tasks
DefaultTaskTimeout TimeSpan 5 minutes Default task timeout
EnableDetailedTelemetry bool true Enable comprehensive telemetry
CircuitBreakerOptions CircuitBreakerOptions? null Circuit breaker configuration
SchedulingStrategy TaskSchedulingStrategy FirstInFirstOut Task scheduling strategy
DependencyResolver ITaskDependencyResolver? null Dependency resolution

Data Models

Model Description Key Properties
EnhancedTaskResult<T> Task execution result Data, IsSuccessful, ErrorMessage, ErrorCategory
TaskTelemetry Telemetry data TaskName, ElapsedMilliseconds, IsSuccessful
TaskProgress Progress information CompletedTasks, TotalTasks, CurrentTask
TaskDefinition Task with metadata Name, Factory, Dependencies, Priority
CircuitBreakerStats Circuit breaker state State, FailureCount, OpenedAt
TelemetrySummary Aggregated telemetry SuccessRate, AverageExecutionTime, TotalTasks

πŸ§ͺ Testing

Run the comprehensive test suite:

# Run all tests
dotnet test

# Run with coverage
dotnet test --collect:"XPlat Code Coverage"

# Run specific test category
dotnet test --filter Category=Integration

Test Coverage

  • βœ… Unit Tests: Core functionality and edge cases
  • βœ… Integration Tests: End-to-end scenarios
  • βœ… Performance Tests: Throughput and latency validation
  • βœ… Stress Tests: High-concurrency scenarios

πŸ—οΈ Project Structure

TaskListProcessor follows a clean architecture with clear separation of concerns:

TaskListProcessor/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ TaskListProcessing/                    # Core library
β”‚   β”‚   β”œβ”€β”€ Core/                             # Core implementations
β”‚   β”‚   β”‚   β”œβ”€β”€ TaskListProcessorEnhanced.cs  # Main orchestrator
β”‚   β”‚   β”‚   β”œβ”€β”€ TaskProcessor.cs              # Single task execution
β”‚   β”‚   β”‚   β”œβ”€β”€ TaskBatchProcessor.cs         # Batch processing
β”‚   β”‚   β”‚   β”œβ”€β”€ TaskStreamProcessor.cs        # Streaming results
β”‚   β”‚   β”‚   └── TaskTelemetryProvider.cs      # Telemetry collection
β”‚   β”‚   β”œβ”€β”€ Interfaces/                       # Interface segregation
β”‚   β”‚   β”‚   β”œβ”€β”€ ITaskProcessor.cs             # Single task interface
β”‚   β”‚   β”‚   β”œβ”€β”€ ITaskBatchProcessor.cs        # Batch processing interface
β”‚   β”‚   β”‚   β”œβ”€β”€ ITaskStreamProcessor.cs       # Streaming interface
β”‚   β”‚   β”‚   └── ITaskTelemetryProvider.cs     # Telemetry interface
β”‚   β”‚   β”œβ”€β”€ Extensions/                       # DI integration
β”‚   β”‚   β”‚   β”œβ”€β”€ ServiceCollectionExtensions.cs
β”‚   β”‚   β”‚   └── TaskProcessorBuilder.cs
β”‚   β”‚   β”œβ”€β”€ Models/                           # Data models
β”‚   β”‚   β”‚   β”œβ”€β”€ EnhancedTaskResult.cs
β”‚   β”‚   β”‚   β”œβ”€β”€ TaskDefinition.cs
β”‚   β”‚   β”‚   β”œβ”€β”€ TaskProgress.cs
β”‚   β”‚   β”‚   └── HealthCheckResult.cs
β”‚   β”‚   β”œβ”€β”€ Scheduling/                       # Task scheduling
β”‚   β”‚   β”‚   β”œβ”€β”€ TaskSchedulingStrategy.cs
β”‚   β”‚   β”‚   β”œβ”€β”€ AdvancedTaskScheduler.cs
β”‚   β”‚   β”‚   └── TopologicalTaskDependencyResolver.cs
β”‚   β”‚   β”œβ”€β”€ CircuitBreaker/                   # Circuit breaker pattern
β”‚   β”‚   β”‚   β”œβ”€β”€ CircuitBreaker.cs
β”‚   β”‚   β”‚   └── CircuitBreakerOptions.cs
β”‚   β”‚   β”œβ”€β”€ LoadBalancing/                    # Load balancing
β”‚   β”‚   β”‚   β”œβ”€β”€ LoadBalancingStrategy.cs
β”‚   β”‚   β”‚   └── LoadBalancingTaskDistributor.cs
β”‚   β”‚   β”œβ”€β”€ Telemetry/                        # Telemetry & metrics
β”‚   β”‚   β”‚   β”œβ”€β”€ TaskTelemetry.cs
β”‚   β”‚   β”‚   β”œβ”€β”€ TelemetrySummary.cs
β”‚   β”‚   β”‚   └── SchedulerStats.cs
β”‚   β”‚   β”œβ”€β”€ Options/                          # Configuration
β”‚   β”‚   β”‚   β”œβ”€β”€ TaskListProcessorOptions.cs
β”‚   β”‚   β”‚   β”œβ”€β”€ CircuitBreakerOptions.cs
β”‚   β”‚   β”‚   └── HealthCheckOptions.cs
β”‚   β”‚   β”œβ”€β”€ Decorators/                       # Cross-cutting concerns
β”‚   β”‚   β”‚   β”œβ”€β”€ LoggingTaskProcessorDecorator.cs
β”‚   β”‚   β”‚   └── MetricsTaskProcessorDecorator.cs
β”‚   β”‚   β”œβ”€β”€ Testing/                          # Test utilities
β”‚   β”‚   β”‚   └── TaskListProcessorTestHelpers.cs
β”‚   β”‚   └── Utilities/                        # Helper classes
β”‚   β”œβ”€β”€ CityWeatherService/                   # Example service
β”‚   β”‚   β”œβ”€β”€ WeatherService.cs
β”‚   β”‚   └── CityWeatherService.csproj
β”‚   └── CityThingsToDo/                       # Example service
β”‚       β”œβ”€β”€ CityThingsToDoService.cs
β”‚       └── CityThingsToDo.csproj
β”œβ”€β”€ examples/
β”‚   └── TaskListProcessor.Console/            # Demo application
β”‚       β”œβ”€β”€ Program.cs
β”‚       └── Utilities/
β”‚           β”œβ”€β”€ AppConfiguration.cs
β”‚           β”œβ”€β”€ OutputFormatter.cs
β”‚           β”œβ”€β”€ ResultsDisplay.cs
β”‚           └── TelemetryDisplay.cs
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ TaskListProcessing.Tests/             # Core library tests
β”‚   β”‚   β”œβ”€β”€ InterfaceSegregationTests.cs
β”‚   β”‚   └── TaskListProcessing.Tests.csproj
β”‚   β”œβ”€β”€ CityWeatherService.Tests/             # Service tests
β”‚   β”‚   β”œβ”€β”€ WeatherServiceTests.cs
β”‚   β”‚   └── CityWeatherService.Tests.csproj
β”‚   └── CityThingsToDo.Tests/                 # Service tests
β”‚       β”œβ”€β”€ CityThingsToDoServiceTests.cs
β”‚       └── CityThingsToDo.Tests.csproj
β”œβ”€β”€ docs/                                     # Documentation
β”‚   β”œβ”€β”€ PHASE1_README.md                      # Phase 1 features
β”‚   β”œβ”€β”€ MIGRATION_GUIDE.md                    # Migration guide
β”‚   └── CLEANUP_SUMMARY.md                    # Cleanup notes
└── README.md                                 # This file

Key Architecture Principles

  • Interface Segregation: Clean, focused interfaces for different scenarios
  • Dependency Injection: Native .NET DI with fluent configuration
  • Single Responsibility: Each component has a clear, focused purpose
  • Extensibility: Decorator pattern for cross-cutting concerns
  • Testability: Mockable interfaces and comprehensive test coverage

πŸ”„ Migration Guide

From Legacy Processors to Modern Interfaces

Recommended Migration Path:

  1. Migrate to Dependency Injection (Recommended)
// Old approach
var processor = new TaskListProcessorEnhanced("Tasks", logger);

// New approach
services.AddTaskListProcessor(options =>
{
    options.MaxConcurrentTasks = 10;
    options.EnableDetailedTelemetry = true;
})
.WithLogging()
.WithMetrics();

// In your service
public class MyService
{
    private readonly ITaskBatchProcessor _processor;
    public MyService(ITaskBatchProcessor processor) => _processor = processor;
}
  1. Direct Interface Usage (Alternative)
// Single task processing
var taskProcessor = new TaskProcessor("SingleTasks", logger);
var result = await taskProcessor.ExecuteTaskAsync("task", someTask);

// Batch processing
var batchProcessor = new TaskBatchProcessor("BatchTasks", logger);
await batchProcessor.ProcessTasksAsync(taskFactories);

// Streaming results
var streamProcessor = new TaskStreamProcessor("StreamTasks", logger);
await foreach (var result in streamProcessor.ProcessTasksStreamAsync(tasks))
{
    // Process results as they complete
}
  1. Backward Compatibility (For existing code)
// TaskListProcessorEnhanced still works with all existing features
using var processor = new TaskListProcessorEnhanced("Legacy", logger);
await processor.ProcessTasksAsync(taskFactories);

New Features in Current Version

  • Interface Segregation: Clean, focused interfaces for different scenarios
  • Dependency Injection: Native .NET DI integration with fluent configuration
  • Task Dependencies: Topological sorting and dependency resolution
  • Circuit Breaker: Automatic failure detection and recovery
  • Advanced Scheduling: Priority-based, dependency-aware task execution
  • Streaming Results: Real-time result processing via async enumerables
  • Enhanced Telemetry: OpenTelemetry integration and health monitoring
  • Memory Optimization: Object pooling and efficient resource management

Breaking Changes

  1. Namespace Changes: Main classes moved to TaskListProcessing.Core
  2. Interface Requirements: New interfaces may require additional dependencies
  3. Configuration Options: Enhanced options structure with validation
  4. Result Types: Enhanced error categorization and telemetry data

🀝 Contributing

We welcome contributions! Here's how to get started:

Development Setup

# Clone and setup
git clone https://github.com/markhazleton/TaskListProcessor.git
cd TaskListProcessor

# Restore dependencies
dotnet restore

# Build solution  
dotnet build

# Run tests
dotnet test

Contribution Guidelines

  1. 🍴 Fork the repository
  2. 🌿 Create a feature branch (git checkout -b feature/amazing-feature)
  3. ✨ Make your changes with tests
  4. βœ… Verify all tests pass (dotnet test)
  5. πŸ“ Commit your changes (git commit -m 'Add amazing feature')
  6. πŸš€ Push to the branch (git push origin feature/amazing-feature)
  7. 🎯 Open a Pull Request

Code Standards

  • Follow C# Coding Conventions
  • Add XML documentation for public APIs
  • Include unit tests for new features
  • Maintain backward compatibility when possible

πŸ“œ License

This project is licensed under the MIT License - see the LICENSE file for details.

MIT License

Copyright (c) 2024 Mark Hazleton

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

πŸ”— Resources

πŸ“š Documentation & Articles

🎯 Examples & Demos

πŸ‘₯ Community & Support

πŸ”— Mark Hazleton Online


πŸš€ Get Started Today

Ready to supercharge your async operations? Get started with TaskListProcessor:

git clone https://github.com/markhazleton/TaskListProcessor.git
cd TaskListProcessor
dotnet run --project examples/TaskListProcessor.Console

See it in action with our interactive demo that showcases:

  • 🌍 Multi-city travel data aggregation with dependency resolution
  • ⚑ Concurrent API calls with circuit breaker protection
  • πŸ“Š Rich telemetry with OpenTelemetry integration
  • 🎯 Type-safe result processing with error categorization
  • ⏱️ Advanced scheduling with priority-based execution
  • πŸ”„ Streaming results via async enumerables
  • πŸ—οΈ Dependency injection with decorator pattern support

Built with ❀️ by Mark Hazleton β€’ Follow for more .NET content and best practices


πŸ“ˆ Project Stats

GitHub stars GitHub forks GitHub issues GitHub last commit

⭐ If this project helped you, please consider giving it a star!

About

TaskListProcessor is a .NET utility for managing and monitoring asynchronous tasks, providing concurrent execution, result tracking, and detailed telemetry.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published