63 lines
1.3 KiB
Go
63 lines
1.3 KiB
Go
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)
|
|
}
|
|
|