Compare commits
2 Commits
b1c65f2ab1
...
ec9c1a8fb5
Author | SHA1 | Date | |
---|---|---|---|
|
ec9c1a8fb5 | ||
|
242029f2e5 |
@ -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
|
||||
}
|
||||
|
69
app/schedule.go
Normal file
69
app/schedule.go
Normal file
@ -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)
|
||||
}
|
||||
}
|
8
main.go
8
main.go
@ -53,6 +53,12 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Assign and run scheduled tasks
|
||||
appLoaded.ScheduledTasks = app.Scheduled{
|
||||
EveryReboot: []func(app *app.App){models.ScheduledSessionCleanup},
|
||||
EveryMinute: []func(app *app.App){models.ScheduledSessionCleanup},
|
||||
}
|
||||
|
||||
// Define Routes
|
||||
routes.GetRoutes(&appLoaded)
|
||||
routes.PostRoutes(&appLoaded)
|
||||
@ -70,6 +76,8 @@ func main() {
|
||||
// Wait for interrupt signal and shut down the server
|
||||
interrupt := make(chan os.Signal, 1)
|
||||
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)
|
||||
stop := make(chan struct{})
|
||||
go app.RunScheduledTasks(&appLoaded, 100, stop)
|
||||
<-interrupt
|
||||
log.Println("Interrupt signal received. Shutting down server...")
|
||||
|
||||
|
@ -21,10 +21,11 @@ const sessionColumns = "\"Id\", " + sessionColumnsNoId
|
||||
const sessionTable = "public.\"Session\""
|
||||
|
||||
const (
|
||||
selectSessionByAuthToken = "SELECT " + sessionColumns + " FROM " + sessionTable + " WHERE \"AuthToken\" = $1"
|
||||
selectAuthTokenIfExists = "SELECT EXISTS(SELECT 1 FROM " + sessionTable + " WHERE \"AuthToken\" = $1)"
|
||||
insertSession = "INSERT INTO " + sessionTable + " (" + sessionColumnsNoId + ") VALUES ($1, $2, $3) RETURNING \"Id\""
|
||||
deleteSessionByAuthToken = "DELETE FROM " + sessionTable + " WHERE \"AuthToken\" = $1"
|
||||
selectSessionByAuthToken = "SELECT " + sessionColumns + " FROM " + sessionTable + " WHERE \"AuthToken\" = $1"
|
||||
selectAuthTokenIfExists = "SELECT EXISTS(SELECT 1 FROM " + sessionTable + " WHERE \"AuthToken\" = $1)"
|
||||
insertSession = "INSERT INTO " + sessionTable + " (" + sessionColumnsNoId + ") VALUES ($1, $2, $3) RETURNING \"Id\""
|
||||
deleteSessionByAuthToken = "DELETE FROM " + sessionTable + " WHERE \"AuthToken\" = $1"
|
||||
deleteSessionsOlderThan30Days = "DELETE FROM " + sessionTable + " WHERE \"CreatedAt\" < NOW() - INTERVAL '30 days'"
|
||||
)
|
||||
|
||||
// CreateSession creates a new session for a user
|
||||
@ -112,3 +113,15 @@ func DeleteSessionByAuthToken(app *app.App, w http.ResponseWriter, authToken str
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ScheduledSessionCleanup deletes expired sessions from the database
|
||||
func ScheduledSessionCleanup(app *app.App) {
|
||||
// Delete sessions older than 30 days
|
||||
_, err := app.Db.Exec(deleteSessionsOlderThan30Days)
|
||||
if err != nil {
|
||||
log.Println("Error deleting expired sessions from database")
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
log.Println("Deleted expired sessions from database")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user