package api import ( "context" "net/http" ) // detailFillBatchSize bounds how many activities' details/splits are fetched // per sync trigger, matching the sequential rate-limited fetch in // internal/sync.Service.FillPendingDetails. const detailFillBatchSize = 50 func (s *Server) handleSyncRun(w http.ResponseWriter, r *http.Request) { ok := s.backgroundSync(func(ctx context.Context) error { if err := s.Sync.IncrementalSync(ctx); err != nil { return err } return s.Sync.FillPendingDetails(ctx, detailFillBatchSize) }) if !ok { writeError(w, http.StatusConflict, "a sync is already in progress") return } writeJSON(w, http.StatusAccepted, map[string]string{"status": "started"}) } func (s *Server) handleSyncBackfill(w http.ResponseWriter, r *http.Request) { ok := s.backgroundSync(func(ctx context.Context) error { if err := s.Sync.Backfill(ctx); err != nil { return err } return s.Sync.FillPendingDetails(ctx, detailFillBatchSize) }) if !ok { writeError(w, http.StatusConflict, "a sync is already in progress") return } writeJSON(w, http.StatusAccepted, map[string]string{"status": "started"}) } func (s *Server) handleSyncRuns(w http.ResponseWriter, r *http.Request) { runs, err := s.DB.ListSyncRuns(r.Context(), 20) if err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } writeJSON(w, http.StatusOK, runs) } func (s *Server) handleSyncStatus(w http.ResponseWriter, r *http.Request) { run, ok, err := s.DB.LatestSyncRun(r.Context()) if err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } remaining, err := s.DB.CountActivitiesMissingDetails(r.Context()) if err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } s.mu.Lock() inProgress := s.syncRunning s.mu.Unlock() progress := s.Sync.Progress() resp := map[string]any{ "in_progress": inProgress, "detail_fill_progress": progress, "activities_pending_details": remaining, } if ok { resp["last_run"] = run } writeJSON(w, http.StatusOK, resp) }