( viewer: Viewer, calendarQuery: CalendarQuery, oldLastUpdate: number, )
| 241 | sessionUpdate: SessionUpdate, |
| 242 | }; |
| 243 | async function initializeSession( |
| 244 | viewer: Viewer, |
| 245 | calendarQuery: CalendarQuery, |
| 246 | oldLastUpdate: number, |
| 247 | ): Promise<SessionInitializationResult> { |
| 248 | if (!viewer.loggedIn) { |
| 249 | return { sessionContinued: false }; |
| 250 | } |
| 251 | |
| 252 | if (!viewer.hasSessionInfo) { |
| 253 | // If the viewer has no session info but is logged in, that is indicative |
| 254 | // of an expired / invalidated session and we should generate a new one |
| 255 | await setNewSession(viewer, calendarQuery, oldLastUpdate); |
| 256 | return { sessionContinued: false }; |
| 257 | } |
| 258 | |
| 259 | if (oldLastUpdate < viewer.sessionLastUpdated) { |
| 260 | // If the client has an older last_update than the server is tracking for |
| 261 | // that client, then the client either had some issue persisting its store, |
| 262 | // or the user restored the client app from a backup. Either way, we should |
| 263 | // invalidate the existing session, since the server has assumed that the |
| 264 | // checkpoint is further along than it is on the client, and might not still |
| 265 | // have all of the updates necessary to do an incremental update |
| 266 | await setNewSession(viewer, calendarQuery, oldLastUpdate); |
| 267 | return { sessionContinued: false }; |
| 268 | } |
| 269 | |
| 270 | if (oldLastUpdate === 0 && viewer.sessionLastUpdated === 0) { |
| 271 | // If both oldLastUpdate and viewer.sessionLastUpdated are 0, that indicates |
| 272 | // either a fresh registration, or a fresh login following a policy update |
| 273 | // that requires acknowledgment. In the latter case, we don't want to leave |
| 274 | // oldLastUpdate as 0, as it might result in a lot of old updates being |
| 275 | // downloaded. So we make sure to use Date.now() for the new session, and |
| 276 | // return { sessionContinued: false } to make sure the client gets a |
| 277 | // stateSyncPayloadTypes.FULL. |
| 278 | await setNewSession(viewer, calendarQuery, Date.now()); |
| 279 | return { sessionContinued: false }; |
| 280 | } |
| 281 | |
| 282 | let comparisonResult = null; |
| 283 | try { |
| 284 | comparisonResult = compareNewCalendarQuery(viewer, calendarQuery); |
| 285 | } catch (e) { |
| 286 | if (e.message !== 'unknown_error') { |
| 287 | throw e; |
| 288 | } |
| 289 | } |
| 290 | |
| 291 | if (comparisonResult) { |
| 292 | const { difference, oldCalendarQuery } = comparisonResult; |
| 293 | const sessionUpdate = { |
| 294 | ...comparisonResult.sessionUpdate, |
| 295 | lastUpdate: oldLastUpdate, |
| 296 | }; |
| 297 | const deltaEntryInfoResult = await fetchEntriesForSession( |
| 298 | viewer, |
| 299 | difference, |
| 300 | oldCalendarQuery, |
no test coverage detected