A high-performance, thread-safe distributed task scheduling system with priority queues, retry mechanisms, and comprehensive metrics. Built with enterprise-level design patterns and best practices.
- Priority-Based Scheduling - Tasks executed based on configurable priority levels (CRITICAL, HIGH, MEDIUM, LOW)
- Concurrent Execution - Multi-threaded task processing with configurable worker pool size
- Automatic Retry - Configurable retry logic with exponential backoff for failed tasks
- Task Cancellation - Cancel scheduled tasks before execution
- Cron-like Scheduling - Support for recurring tasks using cron expressions
- Real-time Metrics - Comprehensive performance and execution metrics
- Thread-Safe Design - Fully concurrent-safe using Java's concurrent utilities
- Strategy Pattern - Pluggable task execution strategies
- Decorator Pattern - Metrics collection through wrapping
- Builder Pattern - Fluent task construction
- Observer Pattern - Task lifecycle hooks
- Factory Pattern - Thread creation and management
┌─────────────────────────────────────────────────────┐
│ MetricsTaskScheduler │
│ (Decorator) │
└─────────────────────┬───────────────────────────────┘
│
┌─────────────────────▼───────────────────────────────┐
│ DistributedTaskScheduler │
│ ┌─────────────┐ ┌──────────────┐ │
│ │ TaskQueue │ │ TaskExecutor │ │
│ │ (Priority) │ │ (Strategy) │ │
│ └─────────────┘ └──────────────┘ │
│ ↓ ↓ │
│ ┌─────────────────────────────────────┐ │
│ │ Executor Service (Thread Pool) │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
- Java 23 or higher
- Maven 3.8+
- Clone the repository:
git clone https://github.com/jwirick06/Taskd.git
cd Taskd- Build the project:
mvn clean install- Run tests:
mvn test- Run the demo:
mvn exec:java -Dexec.mainClass="com.taskscheduler.TaskSchedulerDemo"// Create scheduler components
PriorityTaskQueue queue = new PriorityTaskQueue();
SimpleTaskExecutor executor = new SimpleTaskExecutor();
DistributedTaskScheduler scheduler = new DistributedTaskScheduler(queue, executor);
// Start the scheduler
scheduler.start();
// Create and schedule a task
Task task = Task.builder()
.name("Data Processing Task")
.description("Process user data")
.priority(Priority.HIGH)
.action(() -> {
// Your task logic here
System.out.println("Processing data...");
})
.build();
CompletableFuture<TaskResult> future = scheduler.scheduleTask(task);
// Wait for result
TaskResult result = future.get();
System.out.println("Task completed: " + result.isSuccess());
// Shutdown gracefully
scheduler.shutdown();// Wrap scheduler with metrics
MetricsTaskScheduler scheduler = new MetricsTaskScheduler(baseScheduler);
scheduler.start();
// Schedule multiple tasks
for (int i = 0; i < 100; i++) {
Task task = createTask("Task " + i);
scheduler.scheduleTask(task);
}
// Get metrics
TaskMetrics metrics = scheduler.getMetrics();
System.out.println("Success Rate: " + metrics.getSuccessRate() + "%");
System.out.println("Average Execution Time: " + metrics.getAverageExecutionTimeMs() + "ms");Task resilientTask = Task.builder()
.name("Flaky Network Call")
.priority(Priority.CRITICAL)
.maxRetries(3)
.action(() -> {
// Code that might fail
if (networkUnavailable()) {
throw new RuntimeException("Network error");
}
processData();
})
.build();
scheduler.scheduleTask(resilientTask);// Create a task that runs every Monday at 9:00 AM
Task recurringTask = Task.builder()
.name("Weekly Report")
.priority(Priority.MEDIUM)
.cronExpression("0 9 * * MON")
.action(() -> generateWeeklyReport())
.build();
scheduler.scheduleTask(recurringTask);Task longTask = Task.builder()
.name("Long Running Analysis")
.priority(Priority.LOW)
.action(() -> performAnalysis())
.build();
CompletableFuture<TaskResult> future = scheduler.scheduleTask(longTask);
// Cancel if needed
boolean cancelled = scheduler.cancelTask(longTask.getId());
if (cancelled) {
System.out.println("Task cancelled successfully");
}Immutable task representation with metadata, priority, and execution context. Built using the Builder pattern for flexibility.
Key Properties:
id- Unique identifiername- Human-readable namepriority- Execution priority (CRITICAL, HIGH, MEDIUM, LOW)action- Runnable containing task logicstatus- Current lifecycle stateretryCount/maxRetries- Retry configurationcronExpression- Optional cron schedule
Core interface for scheduling operations. Implementations handle task queuing, execution, and lifecycle management.
Main Operations:
scheduleTask(Task)- Submit task for executioncancelTask(String)- Cancel a scheduled taskstart()/shutdown()- Lifecycle management
Thread-safe priority queue using PriorityBlockingQueue. Tasks ordered by:
- Priority level (CRITICAL > HIGH > MEDIUM > LOW)
- Scheduled time (earlier first for same priority)
Strategy interface for task execution with lifecycle hooks:
beforeExecution(Task)- Pre-execution hookexecute(Task)- Main executionafterExecution(Task)- Success hookonExecutionFailure(Task, Throwable)- Failure handler
Thread-safe metrics collection using atomic operations:
- Tasks scheduled/completed/failed/cancelled
- Execution time statistics
- Success rate calculation
- Average execution time
The project includes a comprehensive test suite with 90%+ code coverage:
- Unit Tests - Individual component testing
- Integration Tests - End-to-end scheduler testing
- Concurrency Tests - Thread-safety validation
- Performance Tests - Load and stress testing
Run all tests:
mvn testRun with coverage:
mvn test jacoco:report- Throughput: 1000+ tasks/second (4 worker threads, simple tasks)
- Latency: Sub-millisecond scheduling overhead
- Memory: O(n) where n is number of queued tasks
- Thread-Safety: Lock-free where possible, fine-grained locking elsewhere
// Default: Runtime.getRuntime().availableProcessors()
DistributedTaskScheduler scheduler = new DistributedTaskScheduler(queue, executor, 8);Task task = Task.builder()
.maxRetries(5) // Default: 3
.build();PriorityTaskQueue queue = new PriorityTaskQueue(1000); // Initial capacitypublic class LoggingTaskExecutor implements TaskExecutor {
@Override
public void execute(Task task) throws Exception {
logger.info("Executing: " + task.getName());
task.getAction().run();
}
@Override
public void onExecutionFailure(Task task, Throwable throwable) {
logger.error("Failed: " + task.getName(), throwable);
alerting.sendAlert(task, throwable);
}
}CompletableFuture<TaskResult> future = scheduler.scheduleTask(task);
future.thenAccept(result -> {
if (result.isSuccess()) {
System.out.println("Completed in " + result.getDuration().toMillis() + "ms");
} else {
result.getError().ifPresent(error ->
System.err.println("Failed: " + error.getMessage())
);
}
});- SLF4J (2.0.12) - Logging facade
- Jackson (2.17.0) - JSON processing
- JUnit Jupiter (5.10.2) - Testing framework
- Mockito (5.11.0) - Mocking framework
- Awaitility (4.2.1) - Async testing utilities
- SOLID Principles - Single responsibility, interface segregation, dependency inversion
- Immutability - Task objects are immutable for thread-safety
- Defensive Copying - Protecting internal state
- Fail-Fast - Early validation and clear error messages
- Clean Code - Readable, well-documented, maintainable
- Comprehensive Testing - Unit, integration, and concurrency tests
- Proper Resource Management - Graceful shutdown and cleanup
- Thread-Safety - Proper use of concurrent collections and synchronization
- Persistent task storage (database/Redis)
- REST API for remote task submission
- Web dashboard for monitoring
- Task dependency graphs (DAG execution)
- Dead letter queue for failed tasks
- Rate limiting per task type
- Task timeout configuration