Skip to content

feature/external scheduler support#2

Merged
bugrakosen merged 7 commits intomasterfrom
feature/external-scheduler-support
Feb 4, 2026
Merged

feature/external scheduler support#2
bugrakosen merged 7 commits intomasterfrom
feature/external-scheduler-support

Conversation

@bugrakosen
Copy link
Copy Markdown
Member

Description

Add external scheduler integration support for Quartz.NET and Hangfire. This allows users to keep their existing scheduler while gaining Milvaion's powerful monitoring, dashboards, and alerting capabilities without changing their job execution infrastructure.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Performance improvement
  • Code refactoring
  • Test update

Changes Made

New SDK Packages

  • Milvasoft.Milvaion.Sdk.Worker.Quartz - Quartz.NET integration package

    • MilvaionJobListener - Tracks job execution lifecycle (start, complete, fail)
    • MilvaionSchedulerListener - Registers jobs when scheduled, manages heartbeats
    • ExternalJobPublisher - Publishes job events to RabbitMQ
    • QuartzMilvaionExtensions - AddMilvaionQuartzIntegration() and UseMilvaion() extension methods
  • Milvasoft.Milvaion.Sdk.Worker.Hangfire - Hangfire integration package

    • MilvaionJobFilter - Implements IServerFilter, IElectStateFilter, IClientFilter for job tracking
    • HangfireWorkerStartupService - Scans recurring jobs from storage using IStorageConnection and registers them
    • ExternalJobPublisher - Publishes job events to RabbitMQ
    • HangfireMilvaionExtensions - AddMilvaionHangfireIntegration() and UseMilvaion() extension methods

Shared Infrastructure

  • ExternalJobRegistry - Unified job registry used by both Quartz and Hangfire SDKs (consolidated from separate registries)
  • MilvaionExternalSchedulerOptions - Configuration options with Source property

Sample Workers

  • SampleQuartzWorker - Demo Quartz worker with SampleLogJob and SendEmailJob
  • SampleHangfireWorker - Demo Hangfire worker with SampleLogJob and SendEmailJob
    • Both demonstrate log publishing to Milvaion using ILogPublisher and PerformContext/IJobExecutionContext

Server-side Changes

  • ExternalJobTrackerService - Consumes external job messages from RabbitMQ

    • Creates/updates ScheduledJob records with IsExternal = true
    • Creates JobOccurrence records for each execution
    • Updates status, duration, result, and exception
  • RedisSchedulerService - Fixed null value handling in CacheJobDetailsAsync

    • ExternalJobId ?? string.Empty to prevent ArgumentException in Redis HashEntry
    • JobNameInWorker ?? string.Empty for null safety
  • JobDispatcherService - Added !j.IsExternal filter to exclude external jobs from internal dispatch

GitHub Actions

  • Added quartzworker-docker-build.yml workflow
  • Added hangfireworker-docker-build.yml workflow
  • Updated sdk-nuget-publish.yml with Quartz and Hangfire SDK publish jobs

Documentation

  • Updated docs/portaldocs/18-external-scheduler.md with complete Hangfire integration guide
  • Added "How Hangfire Jobs Are Tracked" section with detailed flow diagrams
  • Updated supported schedulers table (Hangfire now ✅ Available)
  • Updated README.md with External Scheduler Integration section
  • Created packagereadme.md files for both SDK packages

Testing

  • Unit tests pass
  • Integration tests pass
  • Manual testing performed

Test Configuration:

  • OS: Windows 11
  • .NET Version: .NET 10

Manual Testing:

  1. Started SampleQuartzWorker with Milvaion stack
  2. Verified jobs appear in dashboard with "External" badge
  3. Verified job executions are tracked with correct status
  4. Verified logs are published and visible in occurrence detail
  5. Started SampleHangfireWorker with Milvaion stack
  6. Verified recurring jobs are scanned from Hangfire storage on startup
  7. Verified job registration messages are published to RabbitMQ
  8. Verified occurrence events (Starting, Completed, Failed, Cancelled) are tracked correctly

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published

Breaking Changes

None. This is an additive feature that doesn't affect existing Milvaion workers.

Migration Guide

No migration needed. Existing users can optionally add Quartz/Hangfire integration

- Add IsExternal/ExternalJobId fields to jobs/occurrences for external scheduler mapping
- Implement ExternalJobTrackerService to upsert and track external jobs via RabbitMQ
- Extend Redis scheduler for external job ID mapping and bulk ops
- Add Milvasoft.Milvaion.Sdk.Worker.Quartz project: provides Quartz listeners, publisher, and registry for automatic job registration and monitoring in Milvaion
- Update DTOs, validation, and UI to display and restrict external jobs/workers (badges, disable edit/trigger/delete)
- Add configuration for external scheduler integration
- Provide sample worker with Dockerfile, config, and documentation
- Improve error handling, logging, and test code for external job support
- Add ExternalOccurrenceId support for precise job tracking
- Fix bug: use correct property for external occurrence mapping
- NACK failed RabbitMQ messages for reliable processing
- Improve logging and debug output for external job tracking
- Update UI: label external job ID as "EXTERNAL ID"
- Refactor code for readability (multi-line args, cleanup)
- Ensure MilvaionExternalSchedulerOptions is properly bound
- Add comprehensive Quartz integration documentation
- Clean up sample job and scheduling examples
- Remove unused usings and improve comments throughout
Remove ConcurrentDictionary for correlation IDs and store/retrieve them directly in JobDataMap. Simplifies code and reduces state management by leveraging existing job context.
Introduce a GitHub Actions workflow to automate building and pushing
the SampleQuartzWorker Docker image to Docker Hub. The workflow is
triggered on changes to relevant source files or manual dispatch,
reads the version from a new VERSION file (initialized to 1.0.0),
and tags images with both "latest" and the specific version.
- Introduced full support for Hangfire as an external scheduler in Milvaion, including new documentation, dashboard updates, and Docker workflows.
- Added `Milvasoft.Milvaion.Sdk.Worker.Hangfire` package with job filters, publisher, registry, and startup service for seamless Hangfire job monitoring.
- Created `SampleHangfireWorker` project with sample jobs, configuration, Dockerfile, and README for demonstration and deployment.
- Refactored job registry logic to use a unified `ExternalJobRegistry` for both Quartz and Hangfire integrations.
- Improved internal/external job request handling and updated related command handlers and documentation.
- Updated solution, build workflows, and project files for NuGet packaging and platform targeting.
@bugrakosen bugrakosen merged commit 7d60e37 into master Feb 4, 2026
2 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant