package classes import ( "context" "time" "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/conga" "git.golem15.com/golem15/summercms/modules/lagoon" "git.golem15.com/golem15/summercms/modules/phrasebook" "gorm.io/gorm" ) // RebuildLabelKey is the phrase key of the rebuild job's label. const RebuildLabelKey = "golem15.sitemap::lang.jobs.rebuild" // buildingWindow bounds the "rebuilding now" state of the settings screen: // a request older than this without a finished rebuild (no worker runs) // is no longer shown as running. const buildingWindow = time.Hour // RequestRebuild records that a rebuild was asked for (the settings // screen's files.building state) and dispatches the rebuild job once db's // transaction commits, so the job reads what the transaction wrote. A // queue error is logged and never fails the caller. func RequestRebuild(ctx context.Context, app *backpack.App, db *gorm.DB) error { if app == nil || db == nil { return ErrNoDatabase } if err := db.Exec(`UPDATE golem15_sitemap_settings SET rebuild_requested_at = ? WHERE id = 1`, time.Now().UTC()).Error; err != nil { return err } lagoon.AfterCommit(ctx, db, func(ctx context.Context, _ *gorm.DB) { if _, err := DispatchRebuild(ctx, app); err != nil { pluginLog.Warn("golem15.sitemap: queue rebuild", "error", err) } }) return nil } // DispatchRebuild dispatches the rebuild job now, with a summer_jobs row // labelled in the request locale, and returns the row id. func DispatchRebuild(ctx context.Context, app *backpack.App) (uint, error) { db, ok := app.Lookup[*gorm.DB]() if !ok || db == nil { return 0, ErrNoDatabase } m, err := conga.From(app) if err != nil { return 0, err } label := RebuildLabelKey if tr, ok := app.Lookup[*phrasebook.Translator](); ok && tr != nil { label = tr.Get(ctx, RebuildLabelKey, nil) } return m.Dispatch(ctx, db.WithContext(ctx), RebuildArgs{}, conga.DispatchOpts{Label: label}) } // Building reports whether a rebuild asked for from the admin has not // finished yet (within buildingWindow). func Building(requested, built *time.Time, now time.Time) bool { if requested == nil || now.Sub(*requested) > buildingWindow { return false } return built == nil || built.Before(*requested) }