Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 76
feat: implement persistent job queue with bbolt and maintenance worker#375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base:main
Are you sure you want to change the base?
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -23,6 +23,11 @@ | ||
| # Else if using npm | ||
| FRONTEND_ORIGIN_DEV="http://localhost:5173" | ||
| CONTAINER_ORIGIN="http://localhost:8080/" | ||
| # Job Queue Configuration (Optional) | ||
| CLEANUP_CRON_SCHEDULE="0 0 * * *" | ||
its-me-abhishek marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| CLEANUP_RETENTION_DAYS="7" | ||
| QUEUE_DB_PATH="/app/data/queue.db" | ||
| ``` | ||
| Common pitfall: use the value | ||
| @@ -85,6 +90,28 @@ | ||
| - **Production with nginx on same server**: Not needed (loopback is trusted) | ||
| - **Production with external load balancer**: Set to your load balancer's IP/range | ||
| ## Persistent Job Queue | ||
| The backend includes a persistent job queue system that ensures task operations survive server restarts and provides automatic cleanup of old job logs. | ||
| ### Features | ||
| - **Persistence**: Jobs are stored in a bbolt database and survive backend restarts | ||
| - **Automatic Cleanup**: Old completed and failed job logs are automatically cleaned up | ||
| - **Configurable**: Cleanup schedule and retention period can be customized | ||
| ### Configuration | ||
| The job queue system uses the following environment variables: | ||
| - `CLEANUP_CRON_SCHEDULE`: Cron schedule for cleanup job (default: "0 0 * * *" - daily at midnight) | ||
| - `CLEANUP_RETENTION_DAYS`: Number of days to keep job logs (default: 7) | ||
| - `QUEUE_DB_PATH`: Path to the queue database file (default: "/app/data/queue.db") | ||
| ### Database Location | ||
| The queue database is stored at `/app/data/queue.db` inside the container, which is mounted to `./backend/data/queue.db` on the host system via Docker volume. The `QUEUE_DB_PATH` environment variable can be used to customize this location if needed. | ||
| - Run the application: | ||
| ```bash | ||
its-me-abhishek marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. |
its-me-abhishek marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. |
ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added required dependencies for bbolt and cron |
ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added required dependencies for bbolt and cron |
its-me-abhishek marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. |
its-me-abhishek marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| package utils | ||
| import ( | ||
| "os" | ||
| "strconv" | ||
| "github.com/robfig/cron/v3" | ||
| ) | ||
| type MaintenanceWorker struct { | ||
| cron *cron.Cron | ||
| queue PersistentJobQueue | ||
| } | ||
| func NewMaintenanceWorker(queue PersistentJobQueue) *MaintenanceWorker { | ||
| return &MaintenanceWorker{ | ||
| cron: cron.New(), | ||
| queue: queue, | ||
| } | ||
| } | ||
| func (mw *MaintenanceWorker) Start() error { | ||
| // CLEANUP_CRON_SCHEDULE: Cron expression for cleanup schedule | ||
| // Format: "minute hour day month weekday" | ||
| // Examples: | ||
| // "0 0 * * *" - Daily at midnight (default) | ||
| // "0 */6 * * *" - Every 6 hours | ||
| // "0 2 * * *" - Daily at 2 AM | ||
| // "0 0 * * 0" - Weekly on Sunday | ||
| schedule := os.Getenv("CLEANUP_CRON_SCHEDULE") | ||
| if schedule == "" { | ||
| schedule = "0 0 * * *" | ||
its-me-abhishek marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } | ||
| // CLEANUP_RETENTION_DAYS: Number of days to keep completed/failed job logs | ||
| // Default: 7 days | ||
| // Set to higher value to keep logs longer, lower to cleanup more frequently | ||
| retentionDaysStr := os.Getenv("CLEANUP_RETENTION_DAYS") | ||
| retentionDays := 7 | ||
| if retentionDaysStr != "" { | ||
| if days, err := strconv.Atoi(retentionDaysStr); err == nil { | ||
| retentionDays = days | ||
| } | ||
| } | ||
| _, err := mw.cron.AddFunc(schedule, func() { | ||
| Logger.Infof("Starting job cleanup, retention: %d days", retentionDays) | ||
| if err := mw.queue.CleanupOldJobs(retentionDays); err != nil { | ||
| Logger.Errorf("Failed to cleanup old jobs: %v", err) | ||
| } else { | ||
| Logger.Infof("Job cleanup completed successfully") | ||
| } | ||
| }) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| mw.cron.Start() | ||
| Logger.Infof("Maintenance worker started with schedule: %s", schedule) | ||
| return nil | ||
| } | ||
| func (mw *MaintenanceWorker) Stop() { | ||
| mw.cron.Stop() | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.