kotlin example

package com.taskmanager.examples

import com.taskmanager.*
import java.time.Duration
import java.util.concurrent.ConcurrentHashMap

// ============================================================================
// Example 1: Basic Usage
// ============================================================================

fun basicExample() {
    val tasks = TaskManager {
        concurrency = 4
        threadNamePrefix = "my-app"
    }

    // Simple heartbeat task - every 5 seconds
    tasks.task("heartbeat", every = Duration.ofSeconds(5)) {
        println("[${System.currentTimeMillis()}] heartbeat #$executionCount")
    }

    // Cron task - every minute
    tasks.task("cleanup", cron = "0 * * * * ?") {
        println("[${System.currentTimeMillis()}] Running cleanup...")
        // Simulate cleanup work
        Thread.sleep(1000)
        println("Cleanup complete")
    }

    // Manual task (no schedule)
    tasks.task("on-demand") {
        println("Manual task executed")
        "Task completed successfully"
    }

    tasks.start()

    // Let tasks run for a while
    Thread.sleep(15000)

    // Manually trigger task
    val result = tasks.runBlocking("on-demand")
    println("Result: $result")

    tasks.shutdown()
}

// ============================================================================
// Example 2: With Context
// ============================================================================

class Database {
    fun cleanup() = println("Database cleanup executed")
    fun backup() = println("Database backup executed")
}

fun contextExample() {
    val db = Database()

    val tasks = TaskManager {
        concurrency = 2
        context["db"] = db
        context["environment"] = "production"
    }

    tasks.task("db-cleanup", cron = "0 0 * * * ?") {
        val database = get<Database>("db")
        val env = get<String>("environment")
        
        println("Running cleanup in $env environment")
        database.cleanup()
    }

    tasks.task("db-backup", every = Duration.ofHours(6)) {
        val database = get<Database>("db")
        database.backup()
    }

    tasks.start()
    Thread.sleep(5000)
    tasks.shutdown()
}

// ============================================================================
// Example 3: With Monitoring
// ============================================================================

class TaskMonitor {
    private val stats = ConcurrentHashMap<String, TaskStats>()

    data class TaskStats(
        var totalExecutions: Long = 0,
        var successCount: Long = 0,
        var failureCount: Long = 0,
        var lastExecutionTime: Long? = null,
        var lastDuration: Long? = null,
        var lastError: String? = null,
        val durations: MutableList<Long> = mutableListOf()
    ) {
        val averageDuration: Long
            get() = if (durations.isEmpty()) 0 else durations.average().toLong()
        
        val successRate: Double
            get() = if (totalExecutions == 0L) 0.0 
                    else (successCount * 100.0 / totalExecutions)
    }

    fun record(execution: TaskExecution) {
        val stat = stats.getOrPut(execution.taskName) { TaskStats() }

        stat.totalExecutions++
        stat.lastExecutionTime = execution.endTime
        stat.lastDuration = execution.duration

        if (execution.isSuccess) {
            stat.successCount++
        } else {
            stat.failureCount++
            stat.lastError = execution.error?.message
        }

        // Keep last 100 durations
        stat.durations.add(execution.duration)
        if (stat.durations.size > 100) {
            stat.durations.removeAt(0)
        }
    }

    fun getStats(taskName: String) = stats[taskName]
    fun getAllStats() = stats.toMap()

    fun printStats() {
        println("\n=== Task Statistics ===")
        stats.forEach { (name, stat) ->
            println("""
                Task: $name
                  Total Executions: ${stat.totalExecutions}
                  Success Rate: ${"%.2f".format(stat.successRate)}%
                  Average Duration: ${stat.averageDuration}ms
                  Last Execution: ${stat.lastExecutionTime}
                  ${if (stat.lastError != null) "Last Error: ${stat.lastError}" else ""}
            """.trimIndent())
        }
    }
}

fun monitoringExample() {
    val monitor = TaskMonitor()

    val tasks = TaskManager {
        concurrency = 4

        onTaskStart = { event ->
            println("[START] ${event.taskName} (execution #${event.executionCount})")
        }

        onTaskComplete = { exec ->
            monitor.record(exec)
            
            if (exec.isSuccess) {
                println("[SUCCESS] ${exec.taskName} completed in ${exec.duration}ms")
            } else {
                println("[FAILURE] ${exec.taskName} failed: ${exec.error?.message}")
            }
        }
    }

    // Task that always succeeds
    tasks.task("stable-task", every = Duration.ofSeconds(2)) {
        Thread.sleep(100)
        "success"
    }

    // Task that sometimes fails
    tasks.task("flaky-task", every = Duration.ofSeconds(3)) {
        if (Math.random() < 0.3) {
            throw RuntimeException("Random failure!")
        }
        Thread.sleep(50)
        "success"
    }

    tasks.start()

    // Let tasks run
    Thread.sleep(15000)

    monitor.printStats()

    tasks.shutdown()
}

// ============================================================================
// Example 4: Advanced Scheduling
// ============================================================================

fun advancedSchedulingExample() {
    val tasks = TaskManager()

    // Fixed rate (execute every 5 seconds from start time)
    tasks.task("fixed-rate", Schedule.FixedRate(Duration.ofSeconds(5))) {
        println("[${System.currentTimeMillis()}] Fixed rate task")
        Thread.sleep(2000) // Even if this takes time, next execution is at start+5s
    }

    // Fixed delay (wait 5 seconds after completion)
    tasks.task("fixed-delay", Schedule.FixedDelay(Duration.ofSeconds(5))) {
        println("[${System.currentTimeMillis()}] Fixed delay task")
        Thread.sleep(2000) // Next execution will be at completion+5s
    }

    // With initial delay
    tasks.task(
        "delayed-start",
        Schedule.WithInitialDelay(
            Duration.ofSeconds(10),
            Schedule.FixedRate(Duration.ofSeconds(3))
        )
    ) {
        println("[${System.currentTimeMillis()}] Delayed start task")
    }

    tasks.start()
    Thread.sleep(30000)
    tasks.shutdown()
}

// ============================================================================
// Example 5: Task Control
// ============================================================================

fun taskControlExample() {
    val tasks = TaskManager()

    tasks.task("controllable", every = Duration.ofSeconds(2)) {
        println("[${System.currentTimeMillis()}] Task executing")
    }

    tasks.start()

    // Run for 5 seconds
    Thread.sleep(5000)
    println("\n>>> Disabling task <<<\n")
    
    tasks.disable("controllable")
    Thread.sleep(5000)
    
    println("\n>>> Enabling task <<<\n")
    tasks.enable("controllable")
    Thread.sleep(5000)

    tasks.shutdown()
}

// ============================================================================
// Example 6: Query API
// ============================================================================

fun queryExample() {
    val tasks = TaskManager()

    tasks.task("task1", every = Duration.ofSeconds(10)) { }
    tasks.task("task2", cron = "0 * * * * ?") { }
    tasks.task("task3") { } // Manual task

    tasks.start()

    // List all tasks
    println("Registered tasks: ${tasks.listTaskNames()}")

    // Get task definitions
    tasks.listTaskNames().forEach { name ->
        val def = tasks.getTaskDefinition(name)
        println("""
            Task: ${def?.name}
            Schedule: ${def?.scheduleDescription ?: "Manual"}
            Enabled: ${def?.enabled}
            Allow Concurrent: ${def?.allowConcurrent}
        """.trimIndent())
    }

    tasks.disable("task1")
    println("\nAfter disabling task1:")
    println("task1 enabled: ${tasks.getTaskDefinition("task1")?.enabled}")

    tasks.shutdown()
}

// ============================================================================
// Example 7: Concurrent Control
// ============================================================================

fun concurrentControlExample() {
    val tasks = TaskManager()

    // Task that doesn't allow concurrent execution
    tasks.task("exclusive-task", every = Duration.ofSeconds(2), allowConcurrent = false) {
        println("[${System.currentTimeMillis()}] Exclusive task started")
        Thread.sleep(5000) // Takes longer than interval
        println("[${System.currentTimeMillis()}] Exclusive task finished")
    }

    // Task that allows concurrent execution
    tasks.task("parallel-task", every = Duration.ofSeconds(2), allowConcurrent = true) {
        println("[${System.currentTimeMillis()}] Parallel task started")
        Thread.sleep(5000)
        println("[${System.currentTimeMillis()}] Parallel task finished")
    }

    tasks.start()
    Thread.sleep(15000)
    tasks.shutdown(awaitTermination = true)
}

// ============================================================================
// Example 8: Dynamic Context Injection
// ============================================================================

fun dynamicContextExample() {
    val tasks = TaskManager {
        onTaskStart = { event ->
            // Dynamically inject context based on task
            when {
                event.taskName.startsWith("db-") -> {
                    event.context["connection"] = "db-connection-${event.executionCount}"
                }
                event.taskName.startsWith("api-") -> {
                    event.context["token"] = "api-token-${System.currentTimeMillis()}"
                }
            }
        }
    }

    tasks.task("db-sync", every = Duration.ofSeconds(3)) {
        val conn = getOrNull<String>("connection")
        println("Using connection: $conn")
    }

    tasks.task("api-call", every = Duration.ofSeconds(4)) {
        val token = getOrNull<String>("token")
        println("Using token: $token")
    }

    tasks.start()
    Thread.sleep(10000)
    tasks.shutdown()
}

// ============================================================================
// Main
// ============================================================================

fun main() {
    println("=== Example 1: Basic Usage ===")
    basicExample()
    
    println("\n=== Example 2: With Context ===")
    contextExample()
    
    println("\n=== Example 3: With Monitoring ===")
    monitoringExample()
    
    println("\n=== Example 4: Advanced Scheduling ===")
    advancedSchedulingExample()
    
    println("\n=== Example 5: Task Control ===")
    taskControlExample()
    
    println("\n=== Example 6: Query API ===")
    queryExample()
    
    println("\n=== Example 7: Concurrent Control ===")
    concurrentControlExample()
    
    println("\n=== Example 8: Dynamic Context ===")
    dynamicContextExample()
}