Skip to content

Commit 74e6658

Browse files
authored
Merge pull request #254 from DestinyItemManager/update-fix
More update fixes
2 parents 71007bb + ee048f7 commit 74e6658

File tree

1 file changed

+40
-125
lines changed

1 file changed

+40
-125
lines changed

api/routes/update.ts

Lines changed: 40 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -206,39 +206,38 @@ function validateUpdates(
206206

207207
metrics.increment(`update.action.${update.action}.count`);
208208

209+
if (update.action !== 'setting' && !platformMembershipId) {
210+
metrics.increment('update.validation.platformMembershipIdMissing.count');
211+
result = {
212+
status: 'InvalidArgument',
213+
message: `${update.action} requires platform membership ID to be set`,
214+
};
215+
}
216+
209217
switch (update.action) {
210218
case 'setting':
211219
case 'tag_cleanup':
220+
case 'delete_loadout':
221+
case 'track_triumph':
222+
case 'delete_search':
212223
// no special validation
213224
break;
214225

215226
case 'loadout':
216-
result = validateUpdateLoadout(platformMembershipId, update.payload, appId);
217-
break;
218-
219-
case 'delete_loadout':
220-
result = validateDeleteLoadout(platformMembershipId);
227+
result = validateUpdateLoadout(update.payload, appId);
221228
break;
222229

223230
case 'tag':
224-
result = validateUpdateItemAnnotation(platformMembershipId, update.payload, appId);
231+
result = validateUpdateItemAnnotation(update.payload);
225232
break;
226233

227234
case 'item_hash_tag':
228-
result = validateUpdateItemHashTag(platformMembershipId, update.payload, appId);
229-
break;
230-
231-
case 'track_triumph':
232-
result = validateTrackTriumph(platformMembershipId);
235+
result = validateUpdateItemHashTag(update.payload);
233236
break;
234237

235238
case 'search':
236239
case 'save_search':
237-
result = validateSearch(platformMembershipId, update.payload);
238-
break;
239-
240-
case 'delete_search':
241-
result = validateDeleteSearch(platformMembershipId);
240+
result = validateSearch(update.payload);
242241
break;
243242

244243
default:
@@ -253,6 +252,14 @@ function validateUpdates(
253252
};
254253
}
255254
if (result.status !== 'Success') {
255+
captureMessage(`update ${update.action} failed validation`, {
256+
extra: {
257+
update,
258+
result,
259+
platformMembershipId,
260+
appId,
261+
},
262+
});
256263
console.log('Stately failed update', update.action, result, appId);
257264
}
258265
results.push(result);
@@ -282,11 +289,16 @@ async function statelyUpdate(
282289
return [u];
283290
});
284291

292+
const tagIds = new Set<string>();
293+
for (const update of sortedUpdates) {
294+
if (update.action === 'tag') {
295+
tagIds.add(update.payload.id);
296+
}
297+
}
298+
285299
for (const updateChunk of chunk(sortedUpdates, 25)) {
286300
await client.transaction(async (txn) => {
287301
for (const [action, group] of Object.entries(groupBy(updateChunk, actionKey))) {
288-
metrics.increment(`update.action.${action}.count`);
289-
290302
switch (action) {
291303
case 'setting': {
292304
// The DIM reducer already combines settings updates, but just in case...
@@ -328,7 +340,11 @@ async function statelyUpdate(
328340
case 'tag_cleanup': {
329341
const instanceIds = (group as TagCleanupUpdate[])
330342
.flatMap((u) => u.payload)
331-
.filter(isValidItemId);
343+
.filter(
344+
(id) =>
345+
// We've seen a problem where DIM sends a tag_cleanup and a tag for the same item in the same update
346+
!tagIds.has(id) && isValidItemId(id),
347+
);
332348
if (instanceIds.length) {
333349
await deleteItemAnnotationListStately(
334350
txn,
@@ -388,8 +404,6 @@ async function pgUpdate(
388404
) {
389405
return transaction(async (client) => {
390406
for (const update of updates) {
391-
metrics.increment(`update.action.${update.action}.count`);
392-
393407
switch (update.action) {
394408
case 'setting':
395409
await updateSetting(client, appId, bungieMembershipId, update.payload);
@@ -488,25 +502,8 @@ async function updateLoadout(
488502
metrics.timing('update.loadout', start);
489503
}
490504

491-
function validateUpdateLoadout(
492-
platformMembershipId: string | undefined,
493-
loadout: Loadout,
494-
appId: string,
495-
): ProfileUpdateResult {
496-
if (!platformMembershipId) {
497-
metrics.increment('update.validation.platformMembershipIdMissing.count');
498-
return {
499-
status: 'InvalidArgument',
500-
message: 'Loadouts require platform membership ID to be set',
501-
};
502-
}
503-
504-
const validationResult = validateLoadout('update', loadout, appId);
505-
if (validationResult) {
506-
return validationResult;
507-
}
508-
509-
return { status: 'Success' };
505+
function validateUpdateLoadout(loadout: Loadout, appId: string): ProfileUpdateResult {
506+
return validateLoadout('update', loadout, appId) ?? { status: 'Success' };
510507
}
511508

512509
export function validateLoadout(metricPrefix: string, loadout: Loadout, appId: string) {
@@ -610,17 +607,6 @@ async function deleteLoadout(
610607
metrics.timing('update.deleteLoadout', start);
611608
}
612609

613-
function validateDeleteLoadout(platformMembershipId: string | undefined): ProfileUpdateResult {
614-
if (!platformMembershipId) {
615-
metrics.increment('update.validation.platformMembershipIdMissing.count');
616-
return {
617-
status: 'InvalidArgument',
618-
message: 'Loadouts require platform membership ID to be set',
619-
};
620-
}
621-
return { status: 'Success' };
622-
}
623-
624610
async function updateItemAnnotation(
625611
client: ClientBase,
626612
appId: string,
@@ -641,27 +627,8 @@ async function updateItemAnnotation(
641627
metrics.timing('update.tag', start);
642628
}
643629

644-
function validateUpdateItemAnnotation(
645-
platformMembershipId: string | undefined,
646-
itemAnnotation: ItemAnnotation,
647-
appId: string,
648-
): ProfileUpdateResult {
649-
if (!platformMembershipId) {
650-
metrics.increment('update.validation.platformMembershipIdMissing.count');
651-
return {
652-
status: 'InvalidArgument',
653-
message: 'Tags require platform membership ID to be set',
654-
};
655-
}
656-
630+
function validateUpdateItemAnnotation(itemAnnotation: ItemAnnotation): ProfileUpdateResult {
657631
if (!isValidItemId(itemAnnotation.id)) {
658-
captureMessage('item ID is not in the right format', {
659-
extra: {
660-
itemAnnotation,
661-
platformMembershipId,
662-
appId,
663-
},
664-
});
665632
metrics.increment('update.validation.badItemId.count');
666633
return {
667634
status: 'InvalidArgument',
@@ -690,27 +657,8 @@ function validateUpdateItemAnnotation(
690657
return { status: 'Success' };
691658
}
692659

693-
function validateUpdateItemHashTag(
694-
platformMembershipId: string | undefined,
695-
itemAnnotation: ItemHashTag,
696-
appId: string,
697-
): ProfileUpdateResult {
698-
if (!platformMembershipId) {
699-
metrics.increment('update.validation.platformMembershipIdMissing.count');
700-
return {
701-
status: 'InvalidArgument',
702-
message: 'Tags require platform membership ID to be set',
703-
};
704-
}
705-
660+
function validateUpdateItemHashTag(itemAnnotation: ItemHashTag): ProfileUpdateResult {
706661
if (!Number.isInteger(itemAnnotation.hash)) {
707-
captureMessage('item hash is not in the right format', {
708-
extra: {
709-
itemAnnotation,
710-
platformMembershipId,
711-
appId,
712-
},
713-
});
714662
metrics.increment('update.validation.badItemHash.count');
715663
return {
716664
status: 'InvalidArgument',
@@ -775,17 +723,6 @@ async function trackTriumph(
775723
metrics.timing('update.trackTriumph', start);
776724
}
777725

778-
function validateTrackTriumph(platformMembershipId: string | undefined): ProfileUpdateResult {
779-
if (!platformMembershipId) {
780-
metrics.increment('update.validation.platformMembershipIdMissing.count');
781-
return {
782-
status: 'InvalidArgument',
783-
message: 'Tracked triumphs require platform membership ID to be set',
784-
};
785-
}
786-
return { status: 'Success' };
787-
}
788-
789726
async function recordSearch(
790727
client: ClientBase,
791728
appId: string,
@@ -825,18 +762,7 @@ async function saveSearch(
825762
metrics.timing('update.saveSearch', start);
826763
}
827764

828-
function validateSearch(
829-
platformMembershipId: string | undefined,
830-
payload: UsedSearchUpdate['payload'],
831-
): ProfileUpdateResult {
832-
if (!platformMembershipId) {
833-
metrics.increment('update.validation.platformMembershipIdMissing.count');
834-
return {
835-
status: 'InvalidArgument',
836-
message: 'Searches require platform membership ID to be set',
837-
};
838-
}
839-
765+
function validateSearch(payload: UsedSearchUpdate['payload']): ProfileUpdateResult {
840766
if (payload.query.length > 2048) {
841767
metrics.increment('update.validation.searchTooLong.count');
842768
return {
@@ -870,17 +796,6 @@ async function deleteSearch(
870796
metrics.timing('update.deleteSearch', start);
871797
}
872798

873-
function validateDeleteSearch(platformMembershipId: string | undefined): ProfileUpdateResult {
874-
if (!platformMembershipId) {
875-
metrics.increment('update.validation.platformMembershipIdMissing.count');
876-
return {
877-
status: 'InvalidArgument',
878-
message: 'Searches require platform membership ID to be set',
879-
};
880-
}
881-
return { status: 'Success' };
882-
}
883-
884799
async function updateItemHashTag(
885800
client: ClientBase,
886801
appId: string,

0 commit comments

Comments
 (0)