refactor: remove automatic background incremental sync
Garmin's rate-limiting means every unattended sync attempt risks a ban; syncing should only ever happen when explicitly triggered via "Sync now" (POST /api/sync/run), never on an unattended timer. Removes the periodic background loop (main.go's runIncrementalSyncLoop, api.Server.RunIncrementalSyncForAllUsers), its GENIUSRUN_INCREMENTAL_SYNC_EVERY config, and store.DB.ListUsers (which existed solely to feed it). The manual "Sync now" flow (Backfill/IncrementalSync/FillPendingDetails via FullSync) is untouched.
This commit is contained in:
@@ -62,8 +62,6 @@ func main() {
|
|||||||
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
||||||
defer stop()
|
defer stop()
|
||||||
|
|
||||||
go runIncrementalSyncLoop(ctx, server, cfg.IncrementalSyncEvery)
|
|
||||||
|
|
||||||
httpServer := &http.Server{Addr: cfg.Addr, Handler: server.Router()}
|
httpServer := &http.Server{Addr: cfg.Addr, Handler: server.Router()}
|
||||||
go func() {
|
go func() {
|
||||||
log.Printf("geniusrund listening on %s", cfg.Addr)
|
log.Printf("geniusrund listening on %s", cfg.Addr)
|
||||||
@@ -80,19 +78,3 @@ func main() {
|
|||||||
log.Printf("http server shutdown: %v", err)
|
log.Printf("http server shutdown: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// runIncrementalSyncLoop periodically syncs new activities for every
|
|
||||||
// provisioned user in the background so the frontend doesn't need to
|
|
||||||
// trigger every sync manually.
|
|
||||||
func runIncrementalSyncLoop(ctx context.Context, server *api.Server, every time.Duration) {
|
|
||||||
ticker := time.NewTicker(every)
|
|
||||||
defer ticker.Stop()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
case <-ticker.C:
|
|
||||||
server.RunIncrementalSyncForAllUsers(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -264,31 +264,6 @@ func (s *Server) removeGarminClient(userID int64) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunIncrementalSyncForAllUsers is called on a timer (see main.go) to sync
|
|
||||||
// every provisioned user in turn, replacing the old single-global-Service
|
|
||||||
// background loop.
|
|
||||||
func (s *Server) RunIncrementalSyncForAllUsers(ctx context.Context) {
|
|
||||||
users, err := s.DB.ListUsers(ctx)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("api: list users for incremental sync: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, u := range users {
|
|
||||||
svc, err := s.syncFor(ctx, u.ID)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("api: sync service for user %d: %v", u.ID, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := svc.IncrementalSync(ctx); err != nil {
|
|
||||||
log.Printf("api: incremental sync for user %d: %v", u.ID, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := svc.FillPendingDetails(ctx, 50); err != nil {
|
|
||||||
log.Printf("api: fill pending details for user %d: %v", u.ID, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var requestIDCounter atomic.Int64
|
var requestIDCounter atomic.Int64
|
||||||
|
|
||||||
// requestLoggingMiddleware logs one JSON line per HTTP request (method,
|
// requestLoggingMiddleware logs one JSON line per HTTP request (method,
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ type Config struct {
|
|||||||
GarminTokenStoreRoot string
|
GarminTokenStoreRoot string
|
||||||
|
|
||||||
MinConfidence float64
|
MinConfidence float64
|
||||||
IncrementalSyncEvery time.Duration
|
|
||||||
// LogLevel controls internal/applog's JSON logger ("debug"|"info"|"warn"|"error").
|
// LogLevel controls internal/applog's JSON logger ("debug"|"info"|"warn"|"error").
|
||||||
LogLevel string
|
LogLevel string
|
||||||
|
|
||||||
@@ -76,7 +75,6 @@ func Load() (Config, error) {
|
|||||||
GarminPythonPath: getEnvDefault("GARMIN_WRAPPER_PYTHON", "python3"),
|
GarminPythonPath: getEnvDefault("GARMIN_WRAPPER_PYTHON", "python3"),
|
||||||
GarminTokenStoreRoot: os.Getenv("GARMIN_TOKENSTORE"),
|
GarminTokenStoreRoot: os.Getenv("GARMIN_TOKENSTORE"),
|
||||||
MinConfidence: getEnvFloat("GENIUSRUN_MIN_CONFIDENCE", 0.6),
|
MinConfidence: getEnvFloat("GENIUSRUN_MIN_CONFIDENCE", 0.6),
|
||||||
IncrementalSyncEvery: getEnvDuration("GENIUSRUN_INCREMENTAL_SYNC_EVERY", 6*time.Hour),
|
|
||||||
LogLevel: getEnvDefault("GENIUSRUN_LOG_LEVEL", "info"),
|
LogLevel: getEnvDefault("GENIUSRUN_LOG_LEVEL", "info"),
|
||||||
BackendURL: strings.TrimRight(os.Getenv("GENIUSRUN_BACKEND_URL"), "/"),
|
BackendURL: strings.TrimRight(os.Getenv("GENIUSRUN_BACKEND_URL"), "/"),
|
||||||
OIDCIssuerURL: os.Getenv("GENIUSRUN_OIDC_ISSUER_URL"),
|
OIDCIssuerURL: os.Getenv("GENIUSRUN_OIDC_ISSUER_URL"),
|
||||||
|
|||||||
@@ -32,26 +32,6 @@ func (db *DB) GetUserBySub(ctx context.Context, oidcSub string) (User, bool, err
|
|||||||
return u, true, nil
|
return u, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListUsers returns every provisioned user, for the background incremental
|
|
||||||
// sync loop to iterate.
|
|
||||||
func (db *DB) ListUsers(ctx context.Context) ([]User, error) {
|
|
||||||
rows, err := db.QueryContext(ctx, `SELECT id, oidc_sub, display_name, created_at FROM users ORDER BY id`)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("list users: %w", err)
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
users := []User{}
|
|
||||||
for rows.Next() {
|
|
||||||
var u User
|
|
||||||
if err := rows.Scan(&u.ID, &u.OIDCSub, &u.DisplayName, &u.CreatedAt); err != nil {
|
|
||||||
return nil, fmt.Errorf("scan user row: %w", err)
|
|
||||||
}
|
|
||||||
users = append(users, u)
|
|
||||||
}
|
|
||||||
return users, rows.Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
// neverMatchRule is the placeholder every fresh install's rule-engine kinds
|
// neverMatchRule is the placeholder every fresh install's rule-engine kinds
|
||||||
// start with -- every activity lands in needs_review until the user tunes
|
// start with -- every activity lands in needs_review until the user tunes
|
||||||
// real rules.
|
// real rules.
|
||||||
|
|||||||
Reference in New Issue
Block a user