package main import ( "context" "errors" "log" "time" ) func (s *Server) SyncRoster(ctx context.Context) error { client, ok := s.st.(*Client) if !ok { return errors.New("sync requires a real client") } since, err := s.store.LastSync() if err != nil { return err } // Take the timestamp before fetching, so anything modified mid-sync // is picked up next time rather than skipped. started := time.Now().Unix() users, err := client.ListUsers(ctx, since) if err != nil { return err } if err := s.store.UpsertPeople(users, s.eligible); err != nil { return err } noDept := 0 for _, u := range users { if u.Eligible(s.eligible) && normalizeDept(u.Department) == "" { noDept++ } } if noDept > 0 { log.Printf("%d eligible users synced with no department; they cannot be assigned", noDept) } log.Printf("synced %d users (since=%d)", len(users), since) return s.store.SetLastSync(started) } // syncIfStale runs a delta sync unless one completed within maxAge (1 min) // Serialized so a burst of runs triggers one sync, not one each. func (s *Server) syncIfStale(ctx context.Context, maxAge time.Duration) error { s.syncMu.Lock() defer s.syncMu.Unlock() last, err := s.store.LastSync() if err != nil { return err } if time.Since(time.Unix(last, 0)) < maxAge { return nil } return s.SyncRoster(ctx) }