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