11import * as Sentry from '@sentry/node' ;
2- import { ListToken } from '@stately-cloud/client' ;
32import express from 'express' ;
43import asyncHandler from 'express-async-handler' ;
54import { readTransaction } from '../db/index.js' ;
@@ -12,9 +11,8 @@ import {
1211 syncItemHashTagsForProfile ,
1312} from '../db/item-hash-tags-queries.js' ;
1413import { getLoadoutsForProfile , syncLoadoutsForProfile } from '../db/loadouts-queries.js' ;
15- import { getMigrationState , MigrationState } from '../db/migration-state-queries.js' ;
1614import { getSearchesForProfile , syncSearchesForProfile } from '../db/searches-queries.js' ;
17- import { getSettings } from '../db/settings-queries.js' ;
15+ import { getSettings , syncSettings } from '../db/settings-queries.js' ;
1816import {
1917 getTrackedTriumphsForProfile ,
2018 syncTrackedTriumphsForProfile ,
@@ -26,8 +24,6 @@ import { ProfileResponse } from '../shapes/profile.js';
2624import { Search , SearchType } from '../shapes/search.js' ;
2725import { defaultSettings } from '../shapes/settings.js' ;
2826import { UserInfo } from '../shapes/user.js' ;
29- import { getProfile , syncProfile } from '../stately/bulk-queries.js' ;
30- import { querySettings , syncSettings } from '../stately/settings-queries.js' ;
3127import { badRequest , checkPlatformMembershipId , isValidPlatformMembershipId } from '../utils.js' ;
3228
3329type ProfileComponent = 'settings' | 'loadouts' | 'tags' | 'hashtags' | 'triumphs' | 'searches' ;
@@ -224,21 +220,15 @@ async function loadProfile(
224220 destinyVersion : DestinyVersion ,
225221 incomingSyncTokens ?: { [ component : string ] : Buffer | number } ,
226222) {
227- let response : ProfileResponse = {
223+ const response : ProfileResponse = {
228224 sync : Boolean ( incomingSyncTokens ) ,
229225 } ;
230226 const timerPrefix = response . sync ? 'profileSync' : 'profileStately' ;
231227 const counterPrefix = response . sync ? 'sync' : 'stately' ;
232- const syncTokens : { [ component : string ] : string | number } = { } ;
233- const addSyncToken = (
234- name : string ,
235- token : ListToken | { canSync : boolean ; tokenData : number } ,
236- ) => {
228+ const syncTokens : { [ component : string ] : number } = { } ;
229+ const addSyncToken = ( name : string , token : { canSync : boolean ; tokenData : number } ) => {
237230 if ( token . canSync ) {
238- syncTokens [ name ] =
239- token . tokenData instanceof Uint8Array
240- ? Buffer . from ( token . tokenData ) . toString ( 'base64' )
241- : token . tokenData ;
231+ syncTokens [ name ] = token . tokenData ;
242232 }
243233 } ;
244234 const getSyncToken = < T extends number | Buffer > ( name : string ) => {
@@ -256,55 +246,38 @@ async function loadProfile(
256246 // TODO: should settings be stored under profile too?? maybe primary profile ID?
257247 promises . push (
258248 ( async ( ) => {
259- // Load settings from Postgres. If they're there, you're done. Otherwise load from Stately.
260249 const start = new Date ( ) ;
261-
262250 const now = Date . now ( ) ;
251+ const tokenData = getSyncToken < number > ( 's' ) ;
263252 // TODO: Should add the token to the query to avoid fetching if unchanged
264253 const pgSettings = await readTransaction ( async ( pgClient ) =>
265- getSettings ( pgClient , bungieMembershipId ) ,
254+ tokenData
255+ ? syncSettings ( pgClient , bungieMembershipId , tokenData )
256+ : getSettings ( pgClient , bungieMembershipId ) ,
266257 ) ;
267- if ( pgSettings ) {
268- const tokenData = getSyncToken < number > ( 's' ) ;
269- if ( tokenData === undefined || pgSettings . lastModifiedAt > tokenData ) {
270- response . settings = { ...defaultSettings , ...pgSettings . settings } ;
271- }
272- addSyncToken ( 's' , { canSync : true , tokenData : now } ) ;
273- } else {
274- const tokenData = getSyncToken < Buffer > ( 'settings' ) ;
275- const { settings : storedSettings , token : settingsToken } = tokenData
276- ? await syncSettings ( tokenData )
277- : await querySettings ( bungieMembershipId ) ;
278- response . settings = storedSettings ;
279- addSyncToken ( 'settings' , settingsToken ) ;
258+ if (
259+ tokenData === undefined ||
260+ ( pgSettings !== undefined && pgSettings . lastModifiedAt > tokenData )
261+ ) {
262+ response . settings = { ...defaultSettings , ...pgSettings ?. settings } ;
280263 }
264+ addSyncToken ( 's' , { canSync : true , tokenData : now } ) ;
281265
282266 metrics . timing ( `${ timerPrefix } .settings` , start ) ;
283267 } ) ( ) ,
284268 ) ;
285269 }
286270
287- let loadFromPostgres = false ;
288271 if (
289- platformMembershipId &&
290272 ( [ 'loadouts' , 'tags' , 'hashtags' , 'triumphs' , 'searches' ] as const ) . some ( ( c ) =>
291273 components . includes ( c ) ,
292274 )
293275 ) {
294- const { state : migrationState } = await readTransaction ( async ( client ) =>
295- getMigrationState ( client , platformMembershipId ) ,
296- ) ;
297-
298- if ( migrationState === MigrationState . Postgres ) {
299- loadFromPostgres = true ;
300- }
301- }
302-
303- if ( loadFromPostgres ) {
304276 if ( ! platformMembershipId ) {
305277 badRequest ( res , `Need a platformMembershipId to return ${ components . join ( ', ' ) } ` ) ;
306278 return ;
307279 }
280+
308281 promises . push (
309282 ( async ( ) => {
310283 const now = Date . now ( ) ;
@@ -446,71 +419,6 @@ async function loadProfile(
446419 } ) ;
447420 } ) ( ) ,
448421 ) ;
449- } else {
450- // Special case: DIM wants everything, so we can get it in a single query
451- if (
452- platformMembershipId &&
453- ( [ 'loadouts' , 'tags' , 'hashtags' , 'triumphs' , 'searches' ] as const ) . every ( ( c ) =>
454- components . includes ( c ) ,
455- )
456- ) {
457- // Replace the individual components with a bulk fetch
458- components = components . includes ( 'settings' ) ? [ 'settings' , 'p' ] : [ 'p' ] ;
459- }
460-
461- const loadComponent = (
462- name : Exclude < ProfileComponent , 'settings' > | 'p' ,
463- suffix : string ,
464- handleEmpty : ( ) => void ,
465- ) => {
466- if ( components . includes ( name ) ) {
467- if ( ! platformMembershipId ) {
468- badRequest ( res , `Need a platformMembershipId to return ${ name } ` ) ;
469- return ;
470- }
471- promises . push (
472- ( async ( ) => {
473- const start = new Date ( ) ;
474- const tokenData = getSyncToken < Buffer > ( name ) ;
475- const { profile, token } = tokenData
476- ? await syncProfile ( tokenData )
477- : await getProfile ( platformMembershipId , destinyVersion , suffix ) ;
478- response = { ...response , ...profile } ;
479- if ( ! tokenData ) {
480- handleEmpty ( ) ;
481- }
482- addSyncToken ( name , token ) ;
483- metrics . timing ( `${ timerPrefix } .${ name } ` , start ) ;
484- } ) ( ) ,
485- ) ;
486- }
487- } ;
488-
489- loadComponent ( 'p' , '' , ( ) => {
490- response . loadouts ??= [ ] ;
491- response . searches ??= [ ] ;
492- response . tags ??= [ ] ;
493- response . itemHashTags ??= [ ] ;
494- response . triumphs ??= [ ] ;
495- response . searches ??= [ ] ;
496- } ) ;
497- loadComponent ( 'loadouts' , '/loadout' , ( ) => {
498- response . loadouts ??= [ ] ;
499- } ) ;
500- loadComponent ( 'tags' , '/ia' , ( ) => {
501- response . tags ??= [ ] ;
502- } ) ;
503- if ( destinyVersion === 2 ) {
504- loadComponent ( 'hashtags' , '/iht' , ( ) => {
505- response . itemHashTags ??= [ ] ;
506- } ) ;
507- }
508- loadComponent ( 'triumphs' , '/triumph' , ( ) => {
509- response . triumphs ??= [ ] ;
510- } ) ;
511- loadComponent ( 'searches' , '/search' , ( ) => {
512- response . searches ??= [ ] ;
513- } ) ;
514422 }
515423
516424 await Promise . all ( promises ) ;
0 commit comments