Skip to content

Commit 8191bc5

Browse files
committed
Try syncing a single piece of equipment at a time
1 parent 80a0b3a commit 8191bc5

File tree

3 files changed

+50
-13
lines changed

3 files changed

+50
-13
lines changed

src/read-models/shared-state/async-apply-external-event-sources.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
GoogleSpreadsheetDataForSheet,
1616
} from '../../init-dependencies/google/pull_sheet_data';
1717

18-
import {getAllEquipmentMinimal} from './equipment/get';
18+
import {getLeastRecentlySyncedEquipment} from './equipment/get';
1919
import {Dependencies} from '../../dependencies';
2020
import {
2121
extractGoogleSheetMetadata,
@@ -418,14 +418,19 @@ async function asyncApplyGoogleEvents(
418418
logger.info('...done');
419419
}
420420

421-
logger.info('Pulling google training sheet data...');
422-
for (const equipment of getAllEquipmentMinimal(currentState)) {
421+
logger.info(
422+
'Pulling google training sheet data for least recently synced equipment'
423+
);
424+
// Temporarily try syncing just 1 piece of equipment at a time
425+
for (const equipment of getLeastRecentlySyncedEquipment(
426+
currentState,
427+
1
428+
)) {
423429
const equipmentLogger = logger.child({equipment});
424430
if (
425431
O.isNone(equipment.trainingSheetId) ||
426432
(O.isSome(equipment.lastQuizSync) &&
427-
Date.now() - equipment.lastQuizSync.value <
428-
googleRefreshIntervalMs + Math.random() * googleRefreshIntervalMs) // Try a random offset to spread out cpu usage.
433+
Date.now() - equipment.lastQuizSync.value < googleRefreshIntervalMs)
429434
) {
430435
equipmentLogger.info('No google training sheet refresh required');
431436
continue;
@@ -478,7 +483,7 @@ async function asyncApplyGoogleEvents(
478483
}
479484
);
480485
}
481-
logger.info('...done');
486+
logger.info('Finished pulling google training sheet data');
482487
}
483488
);
484489
}

src/read-models/shared-state/equipment/get.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {pipe} from 'fp-ts/lib/function';
22
import {BetterSQLite3Database} from 'drizzle-orm/better-sqlite3';
3-
import {eq} from 'drizzle-orm';
3+
import {eq, asc, isNotNull} from 'drizzle-orm';
44
import * as O from 'fp-ts/Option';
55
import * as RA from 'fp-ts/ReadonlyArray';
66
import {equipmentTable} from '../state';
@@ -51,3 +51,18 @@ export const getAllEquipmentMinimal = (
5151
db: BetterSQLite3Database
5252
): ReadonlyArray<MinimalEquipment> =>
5353
pipe(db.select().from(equipmentTable).all(), RA.map(transformRow));
54+
55+
export const getLeastRecentlySyncedEquipment = (
56+
db: BetterSQLite3Database,
57+
count: number
58+
): ReadonlyArray<MinimalEquipment> =>
59+
pipe(
60+
db
61+
.select()
62+
.from(equipmentTable)
63+
.where(isNotNull(equipmentTable.trainingSheetId))
64+
.orderBy(asc(equipmentTable.lastQuizSync))
65+
.limit(count)
66+
.all(),
67+
RA.map(transformRow)
68+
);

tests/google-sheets/async-apply-external.test.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as O from 'fp-ts/Option';
2+
import * as RA from 'fp-ts/ReadonlyArray';
23
import {NonEmptyString, UUID} from 'io-ts-types';
34
import {faker} from '@faker-js/faker';
45
import * as gsheetData from '../data/google_sheet_data';
@@ -70,22 +71,38 @@ describe('Integration asyncApplyExternalEventSources', () => {
7071
areaId,
7172
O.some(gsheetData.METAL_LATHE.apiResp.spreadsheetId!)
7273
);
73-
const results = await runAsyncApplyExternalEventSources(framework);
74-
checkLastQuizSyncUpdated(results);
74+
const resultsAfterFirstRun =
75+
await runAsyncApplyExternalEventSources(framework);
76+
77+
const resultsAfterSecondRun =
78+
await runAsyncApplyExternalEventSources(framework);
79+
80+
expect(
81+
RA.filter((e: Equipment) => O.isSome(e.lastQuizSync))(
82+
Array.from(resultsAfterFirstRun.equipmentAfter.values())
83+
)
84+
).toHaveLength(1); // Only update a single piece of equipment at a time.
85+
86+
expect(
87+
RA.filter((e: Equipment) => O.isSome(e.lastQuizSync))(
88+
Array.from(resultsAfterSecondRun.equipmentAfter.values())
89+
)
90+
).toHaveLength(2); // Only update a single piece of equipment at a time.
91+
7592
checkLastQuizEventTimestamp(
7693
gsheetData.BAMBU,
77-
results.equipmentAfter.get(bambu.id)!
94+
resultsAfterSecondRun.equipmentAfter.get(bambu.id)!
7895
);
7996
checkLastQuizEventTimestamp(
8097
gsheetData.METAL_LATHE,
81-
results.equipmentAfter.get(lathe.id)!
98+
resultsAfterSecondRun.equipmentAfter.get(lathe.id)!
8299
);
83100

84101
// We already test the produced quiz result events above
85102
// and testing updateState is also tested elsewhere so this integration
86103
// test doesn't need to enumerate every combination it just needs to check
87104
// that generally the equipment is getting updated.
88-
const bambuAfter = results.equipmentAfter.get(bambu.id)!;
105+
const bambuAfter = resultsAfterSecondRun.equipmentAfter.get(bambu.id)!;
89106
expect(bambuAfter.orphanedPassedQuizes).toHaveLength(0);
90107
expect(bambuAfter.membersAwaitingTraining).toHaveLength(1);
91108
expect(bambuAfter.membersAwaitingTraining[0].memberNumber).toStrictEqual(
@@ -96,7 +113,7 @@ describe('Integration asyncApplyExternalEventSources', () => {
96113
);
97114

98115
// Lathe results only have a single failed entry.
99-
const latheAfter = results.equipmentAfter.get(lathe.id)!;
116+
const latheAfter = resultsAfterSecondRun.equipmentAfter.get(lathe.id)!;
100117
expect(latheAfter.orphanedPassedQuizes).toHaveLength(0);
101118
expect(latheAfter.failedQuizAttempts).toHaveLength(1);
102119
expect(latheAfter.failedQuizAttempts[0]).toMatchObject({

0 commit comments

Comments
 (0)