view calsync/event_sync.go @ 60:3b0595c2bf03

logging and small refactors
author drewp@bigasterisk.com
date Fri, 06 Sep 2024 16:41:48 -0700
parents 6c7151126a0b
children 8aee4f5c4bdd
line wrap: on
line source

package main

import (
	"log"
	"time"

	"bigasterisk.com/go/gcalendarwatch/convert"
	"bigasterisk.com/go/gcalendarwatch/gcalclient"
	"bigasterisk.com/go/gcalendarwatch/mongoclient"
	M "bigasterisk.com/go/gcalendarwatch/mongoclienttypes"
)

// Each calendar syncs like this:
//  1. Full sync of events taking place between `now-keepHistory` to `now+syncAhead`.
//  2. Garbage-collect all events last-modified before `now-keepHistory`
//  3. Continuous watch of each calendar to catch updates.
func updateMongoEventsToMatchGoogleForever(
	mc *mongoclient.MongoClient,
	gc *gcalclient.GCalClient,
	keepHistory time.Duration,
	syncAhead time.Duration) error {
	log.Println("starting updateMongoEventsToMatchGoogleForever")

	now := time.Now()
	syncStart := now.Add(-keepHistory)
	syncEnd := now.Add(syncAhead)
	// Note that we could receive updates outside this interval.

	cals, err := mc.GetAllCals()
	if err != nil {
		return err
	}
	log.Println("syncing events from", len(cals), "calendars")

	for _, cal := range cals {
		rd := newCalEventsReader(mc, gc, cal, syncStart, syncEnd)
		go rd.updateForever()
	}
	return nil
}

type calEventsReader struct {
	mc        *mongoclient.MongoClient
	gc        *gcalclient.GCalClient
	cal       M.MongoCal
	t1, t2    time.Time
	syncToken string
}

func newCalEventsReader(mc *mongoclient.MongoClient, gc *gcalclient.GCalClient, cal M.MongoCal, t1, t2 time.Time) *calEventsReader {
	return &calEventsReader{mc, gc, cal, t1, t2, ""}
}

func (r *calEventsReader) updateForever() {
	err := r.updateInitialRange()
	if err != nil {
		log.Fatal(err)
	}

	for {
		log.Println("syncing", r.cal.Summary, "with sync", r.syncToken)
		err = r.sync()
		if err != nil {
			log.Fatal(err)
		}

		time.Sleep(10 * time.Second)
	}
}

func (r *calEventsReader) updateInitialRange() error {
	events, nextSyncToken, err := r.gc.ListEventsInRange(r.cal, r.t1, r.t2)
	r.syncToken = nextSyncToken
	if err != nil {
		return err
	}
	for _, ev := range events {
		r.mc.UpsertOneEvent(convert.MongoEventFromGoogleEvent(&ev, time.Now() /*todo*/))
	}

	return r.mc.DeleteEventsUpdatedBefore(r.cal, r.t1)
}

func (r *calEventsReader) sync() error {
	events, nextSyncToken, err := r.gc.ListEventUpdates(r.cal, r.syncToken)
	if err != nil {
		return err
	}
	r.syncToken = nextSyncToken
	for _, ev := range events {
		r.mc.UpsertOneEvent(convert.MongoEventFromGoogleEvent(&ev, time.Now() /*todo*/))
	}

	return nil
}