From 242029f2e5014f350af2b9e2e21657acb70ff4f9 Mon Sep 17 00:00:00 2001 From: max Date: Tue, 4 Apr 2023 14:37:23 -0500 Subject: [PATCH] Initial task scheduler implementation --- app/app.go | 7 ++--- app/schedule.go | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 app/schedule.go diff --git a/app/app.go b/app/app.go index df1aef2..53db2ec 100644 --- a/app/app.go +++ b/app/app.go @@ -8,7 +8,8 @@ import ( // App contains and supplies available configurations and connections type App struct { - Config config.Configuration // Configuration file - Db *sql.DB // Database connection - Res *embed.FS // Resources from the embedded filesystem + Config config.Configuration // Configuration file + Db *sql.DB // Database connection + Res *embed.FS // Resources from the embedded filesystem + ScheduledTasks Scheduled // Scheduled contains a struct of all scheduled functions } diff --git a/app/schedule.go b/app/schedule.go new file mode 100644 index 0000000..3ff8d86 --- /dev/null +++ b/app/schedule.go @@ -0,0 +1,69 @@ +package app + +import "time" + +type Scheduled struct { + EveryReboot []func(app *App) + EverySecond []func(app *App) + EveryMinute []func(app *App) + EveryHour []func(app *App) + EveryDay []func(app *App) + EveryWeek []func(app *App) + EveryMonth []func(app *App) + EveryYear []func(app *App) +} + +type Task struct { + Interval time.Duration + Funcs []func(app *App) +} + +func RunScheduledTasks(app *App, poolSize int, stop <-chan struct{}) { + // Run every time the server starts + for _, f := range app.ScheduledTasks.EveryReboot { + f(app) + } + + tasks := []Task{ + {Interval: time.Second, Funcs: app.ScheduledTasks.EverySecond}, + {Interval: time.Minute, Funcs: app.ScheduledTasks.EveryMinute}, + {Interval: time.Hour, Funcs: app.ScheduledTasks.EveryHour}, + {Interval: 24 * time.Hour, Funcs: app.ScheduledTasks.EveryDay}, + {Interval: 7 * 24 * time.Hour, Funcs: app.ScheduledTasks.EveryWeek}, + {Interval: 30 * 24 * time.Hour, Funcs: app.ScheduledTasks.EveryMonth}, + {Interval: 365 * 24 * time.Hour, Funcs: app.ScheduledTasks.EveryYear}, + } + + // Set up task runners + runners := make([]chan bool, len(tasks)) + for i, task := range tasks { + runner := make(chan bool, poolSize) + runners[i] = runner + go func(task Task, runner chan bool) { + ticker := time.NewTicker(task.Interval) + defer ticker.Stop() + for { + select { + case <-ticker.C: + for _, f := range task.Funcs { + runner <- true + go func(f func(app *App)) { + defer func() { <-runner }() + f(app) + }(f) + } + case <-stop: + return + } + } + }(task, runner) + } + + // Wait for termination + for _, runner := range runners { + for i := 0; i < cap(runner); i++ { + runner <- false + } + close(runner) + } +}