Mercurial > code > home > repos > gcalendarwatch
comparison calsync/gcalclient/gcalclient.go @ 54:3a12a3ac9164
refactor. run 30s forever. doesn't work on 2+ cals
author | drewp@bigasterisk.com |
---|---|
date | Tue, 20 Aug 2024 12:18:46 -0700 |
parents | f248f018a663 |
children | 627c815f83bb |
comparison
equal
deleted
inserted
replaced
53:f248f018a663 | 54:3a12a3ac9164 |
---|---|
9 | 9 |
10 "bigasterisk.com/go/gcalendarwatch/mongoclient" | 10 "bigasterisk.com/go/gcalendarwatch/mongoclient" |
11 "google.golang.org/api/calendar/v3" | 11 "google.golang.org/api/calendar/v3" |
12 ) | 12 ) |
13 | 13 |
14 const urlBase = "http://bigasterisk.com/calendar/" | |
15 | |
14 type GCalClient struct { | 16 type GCalClient struct { |
15 ctx context.Context | 17 ctx context.Context |
16 srv *calendar.Service | 18 srv *calendar.Service |
17 } | 19 } |
18 | 20 |
22 CalendarUrl string | 24 CalendarUrl string |
23 EventUrl string | 25 EventUrl string |
24 } | 26 } |
25 | 27 |
26 func MakeCalUrl(calId string) string { | 28 func MakeCalUrl(calId string) string { |
27 return "http://bigasterisk.com/calendar/" + url.QueryEscape(calId) | 29 return urlBase + url.QueryEscape(calId) |
28 } | 30 } |
29 | 31 |
30 func MakeEventUrl(calUrl string, evId string) string { | 32 func MakeEventUrl(calUrl string, evId string) string { |
31 return calUrl + "/" + url.QueryEscape(evId) | 33 return calUrl + "/" + url.QueryEscape(evId) |
32 } | 34 } |
70 // calendar. After that point, all events will be updates (including | 72 // calendar. After that point, all events will be updates (including |
71 // deletes). | 73 // deletes). |
72 initialFillStart, initialFillEnd time.Time, | 74 initialFillStart, initialFillEnd time.Time, |
73 out chan *FindEventsMessage, | 75 out chan *FindEventsMessage, |
74 ) error { | 76 ) error { |
75 | |
76 cals, err := mc.GetAllCals() | 77 cals, err := mc.GetAllCals() |
77 if err != nil { | 78 if err != nil { |
78 return err | 79 return err |
79 } | 80 } |
80 log.Println("reading", len(cals), "calendars") | 81 log.Println("reading", len(cals), "calendars") |
81 for calNum, cal := range cals { | 82 for calNum, cal := range cals { |
82 t := time.Now() | 83 go calRoutine(calNum, cal, initialFillStart, initialFillEnd, gc, out) |
83 log.Println(" cal", calNum, cal.Url) | 84 } |
84 log.Println(" cal", calNum, "readEventsInRange", "from", initialFillStart, "to", initialFillEnd) | 85 |
85 syncToken, err := gc.readEventsInRange(&cal, initialFillStart, initialFillEnd, out) | 86 return nil |
87 } | |
88 | |
89 func calRoutine(calNum int, cal mongoclient.MongoCal, initialFillStart time.Time, initialFillEnd time.Time, gc *GCalClient, out chan *FindEventsMessage) bool { | |
90 t := time.Now() | |
91 log.Println(" cal", calNum, cal.Url) | |
92 log.Println(" cal", calNum, "readEventsInRange", "from", initialFillStart, "to", initialFillEnd) | |
93 syncToken, err := gc.readEventsInRange(&cal, initialFillStart, initialFillEnd, out) | |
94 if err != nil { | |
95 log.Panicln(err) | |
96 return true | |
97 } | |
98 | |
99 out <- &FindEventsMessage{nil, cal.GoogleId, t} | |
100 | |
101 ew := gc.NewEventWatch(&cal, t, syncToken, out) | |
102 | |
103 for loop := 0; ; loop++ { | |
104 log.Println("") | |
105 log.Println("tail loop", loop, "for", cal.Url) | |
106 err := ew.GetMoreEvents() | |
86 if err != nil { | 107 if err != nil { |
87 return err | 108 log.Panicln(err) |
88 } | 109 return true |
89 | 110 } |
90 out <- &FindEventsMessage{nil, cal.GoogleId, t} | 111 time.Sleep(10 * time.Minute) |
91 | 112 } |
92 ew := gc.NewEventWatch(&cal, t, syncToken, out) | 113 |
93 | |
94 for loop := 0; loop < 30; loop++ { | |
95 log.Println("") | |
96 log.Println("tail loop", loop, "for", cal.Url) | |
97 err := ew.GetMoreEvents() | |
98 if err != nil { | |
99 return err | |
100 } | |
101 time.Sleep(2 * time.Second) | |
102 } | |
103 } | |
104 | |
105 return nil | |
106 } | 114 } |
107 | 115 |
108 // Synchronous. | 116 // Synchronous. |
109 func (gc *GCalClient) readEventsInRange( | 117 func (gc *GCalClient) readEventsInRange(cal *mongoclient.MongoCal, t1, t2 time.Time, out chan *FindEventsMessage) (string, error) { |
110 cal *mongoclient.MongoCal, | 118 log.Println(" get initial events for", cal.Url, "between", t1, "and", t2) |
111 initialFillStart, initialFillEnd time.Time, | |
112 out chan *FindEventsMessage, | |
113 ) (string, error) { | |
114 log.Println( | |
115 " get initial events for", cal.Url, "between", | |
116 initialFillStart, "and", initialFillEnd) | |
117 | 119 |
118 pageToken := "" | 120 pageToken := "" |
119 syncToken := "" | 121 syncToken := "" |
120 | 122 var err error |
123 var done bool | |
121 for { | 124 for { |
122 log.Println(" getting another page", pageToken) | 125 done, syncToken, pageToken, err = readEventsPage(gc, cal, t1, t2, pageToken, out) |
123 events, err := rangedEventsCall(gc.srv, cal.GoogleId, initialFillStart, initialFillEnd, pageToken).Do() | |
124 if err != nil { | 126 if err != nil { |
125 return "", err | 127 return "", err |
126 } | 128 } |
127 | 129 if done { |
128 log.Println(" got", len(events.Items), "events, sync=", events.NextSyncToken) | |
129 if len(events.Items) == 0 { | |
130 break | 130 break |
131 } | 131 } |
132 | |
133 sendEvents(events, cal, out) | |
134 | |
135 syncToken = events.NextSyncToken | |
136 if events.NextPageToken == "" { | |
137 break | |
138 } | |
139 pageToken = events.NextPageToken | |
140 } | 132 } |
141 return syncToken, nil | 133 return syncToken, nil |
134 } | |
135 | |
136 func readEventsPage(gc *GCalClient, cal *mongoclient.MongoCal, t1, t2 time.Time, pageToken string, out chan *FindEventsMessage) (done bool, syncToken, nextPageToken string, err error) { | |
137 log.Println(" getting another page", pageToken) | |
138 events, err := rangedEventsCall(gc.srv, cal.GoogleId, t1, t2, pageToken).Do() | |
139 if err != nil { | |
140 return | |
141 } | |
142 | |
143 log.Println(" got", len(events.Items), "events, sync=", events.NextSyncToken) | |
144 if len(events.Items) == 0 { | |
145 done = true | |
146 return | |
147 } | |
148 | |
149 sendEvents(events, cal, out) | |
150 | |
151 syncToken = events.NextSyncToken | |
152 if events.NextPageToken == "" { | |
153 done = true | |
154 return | |
155 } | |
156 nextPageToken = events.NextPageToken | |
157 syncToken = events.NextSyncToken | |
158 return | |
142 } | 159 } |
143 | 160 |
144 // Send a page of calendar.Events over a channel, as CalendarEvent structs. | 161 // Send a page of calendar.Events over a channel, as CalendarEvent structs. |
145 func sendEvents(events *calendar.Events, cal *mongoclient.MongoCal, out chan *FindEventsMessage) { | 162 func sendEvents(events *calendar.Events, cal *mongoclient.MongoCal, out chan *FindEventsMessage) { |
146 for _, event := range events.Items { | 163 for _, event := range events.Items { |
176 } | 193 } |
177 | 194 |
178 // Call this when there are likely new changes to sync. | 195 // Call this when there are likely new changes to sync. |
179 func (w *eventWatch) GetMoreEvents() error { | 196 func (w *eventWatch) GetMoreEvents() error { |
180 call := syncEventsCall(w.gc.srv, w.cal.GoogleId) | 197 call := syncEventsCall(w.gc.srv, w.cal.GoogleId) |
198 | |
181 log.Println("listing events on", w.cal.GoogleId, "with") | 199 log.Println("listing events on", w.cal.GoogleId, "with") |
182 | |
183 if w.nextPageToken != "" { | 200 if w.nextPageToken != "" { |
184 call = call.PageToken(w.nextPageToken) | 201 call = call.PageToken(w.nextPageToken) |
185 log.Println(" pageToken", w.nextPageToken) | 202 log.Println(" pageToken", w.nextPageToken) |
186 } else if w.nextSyncToken != "" { | 203 } else if w.nextSyncToken != "" { |
187 call = call.SyncToken(w.nextSyncToken) | 204 call = call.SyncToken(w.nextSyncToken) |
188 log.Println(" syncToken", w.nextSyncToken) | 205 log.Println(" syncToken", w.nextSyncToken) |
189 } else { | 206 } else { |
190 call = call.UpdatedMin((w.modSince.Format(time.RFC3339))) | 207 call = call.UpdatedMin((w.modSince.Format(time.RFC3339))) |
191 log.Println(" updatedMin", w.modSince.Format(time.RFC3339)) | 208 log.Println(" updatedMin", w.modSince.Format(time.RFC3339)) |
192 } | 209 } |
193 ret, err := call.Do() | 210 events, err := call.Do() |
194 if err != nil { | 211 if err != nil { |
195 return err | 212 return err |
196 } | 213 } |
197 w.nextSyncToken = ret.NextSyncToken | 214 w.nextSyncToken = events.NextSyncToken |
198 w.nextPageToken = ret.NextPageToken | 215 w.nextPageToken = events.NextPageToken |
199 log.Println(len(ret.Items), "more events received") | 216 log.Println(len(events.Items), "more events received") |
200 sendEvents(ret, w.cal, w.out) | 217 sendEvents(events, w.cal, w.out) |
201 log.Println("got nextSyncToken=", w.nextSyncToken) | 218 log.Println("got nextSyncToken=", w.nextSyncToken, " nextPageToken=", w.nextPageToken) |
202 log.Println("got nextPageToken=", w.nextPageToken) | |
203 return err | 219 return err |
204 } | 220 } |