Ana içeriğe geç
Versiyon: 1.0.1

Introduction

Milvaion is a distributed job scheduling system built on .NET 10. It separates the scheduler (API that decides when jobs run) from the workers (processes that execute jobs), connected via Redis and RabbitMQ.

What Problem Does Milvaion Solve?

Most job schedulers run jobs inside the same process as the scheduling logic. This works fine until:

  • A long-running job blocks other jobs from executing
  • A crashing job takes down the entire scheduler
  • You need different hardware for different job types (e.g., GPU for ML jobs)
  • You want to scale job execution independently from the API

Milvaion solves these problems by completely separating scheduling from execution:

┌─────────────────┐        ┌─────────────────┐       ┌─────────────────┐
│ Milvaion API │ │ RabbitMQ │ │ Workers │
│ (Scheduler) │──────▶│ (Job Queue) │──────▶│ (Executors) │
│ │ │ │ │ │
│ • REST API │ │ • Job messages │ │ • IJob classes │
│ • Dashboard │ │ • Status queues │ │ • Retry logic │
│ • Cron parsing │ │ • Log streams │ │ • DI support │
└─────────────────┘ └─────────────────┘ └─────────────────┘

When Should You Use Milvaion?

Good Fit ✅

ScenarioWhy Milvaion Works
Scheduled background jobsCron-based scheduling with Redis ZSET for precision
High-volume job processingHorizontal scaling with RabbitMQ distribution
Long-running jobs (hours)Workers isolated from API, no timeout issues
Multi-tenant systemsRoute jobs to specific worker groups
Jobs needing different resourcesGPU workers, high-memory workers, etc.
Compliance/audit requirementsFull execution history with logs stored in PostgreSQL

Not a Good Fit ❌

ScenarioBetter Alternative
Simple in-process background tasksUse BackgroundService or Hangfire
Real-time event processingUse dedicated event streaming (Kafka, Azure Event Hubs)
Sub-second job schedulingMilvaion polls every 1 second minimum
Single-server deploymentsOverhead of Redis + RabbitMQ not justified
Workflow orchestration with branchingUse Temporal, Elsa, or Azure Durable Functions

Core Concepts

ConceptWhat It Is
Scheduler (API)REST API + background service that reads cron schedules and dispatches jobs
WorkerA process that consumes jobs from RabbitMQ and executes them
JobRepresents recurring or one time execution definition
Worker JobC# class implementing IJob or IAsyncJob interface
Occurrence/ExecutionSingle execution of a job (has status, logs, duration)
JobDataJSON payload passed to the job at execution time

How It Works

  1. Worker Auto Disvovery service will auto discover your worker and containing worker jobs.
  2. You create a job according to worker job via REST API or Dashboard (e.g., "Send daily report at 9 AM")
  3. Scheduler stores it in PostgreSQL and adds to Redis ZSET with next run time
  4. Dispatcher checks Redis for due jobs
  5. Due jobs are published to RabbitMQ with routing key (e.g., sendreport.*)
  6. Worker consumes the message, executes your IAsyncJob code
  7. Worker reports back via RabbitMQ (status updates, logs)
  8. Scheduler persists results and notifies Dashboard via SignalR

Key Features

Reliability

  • At-least-once delivery via RabbitMQ manual ACK
  • Automatic retries with exponential backoff
  • Dead Letter Queue for failed jobs after max retries
  • Zombie detection recovers stuck jobs
  • Auto disable always failing jobs (configurable failed execution count).

Scalability

  • Horizontal worker scaling - add more workers for more throughput
  • Job-type routing - route specific jobs to specialized workers
  • Independent scaling - scale API and workers separately

Observability

  • Real-time dashboard with SignalR updates
  • Execution logs
    • User Friendly Logs -> It is stored within the occurrence to be displayed in the user interface.
    • Technical Logs -> Logs are sent to Seq.
  • Worker health monitoring via heartbeats
  • OpenTelemetry support for metrics and tracing

Developer Experience

  • Simple IAsyncJob interface - implement one method
  • Full DI support - inject services into jobs
  • Auto-discovery - jobs registered automatically
  • Cancellation support - graceful shutdown

Comparison with Alternatives

FeatureMilvaionHangfireQuartz.NET
ArchitectureDistributed (API + Workers)MonolithicEmbedded
Worker IsolationSeparate processesSame processSame process
Horizontal ScalingIndependentLimitedComplex
Job DispatchingRabbitMQDatabase pollingDatabase polling
Real-time DashboardBuilt-inBuilt-inNone
Log StreamingReal-time via RabbitMQConsole pluginNone
Offline ResilienceSQLite fallbackNoneNone
Best ForDistributed systemsSimple .NET appsEmbedded scheduling

Next Steps