Skip to content

Commit 04c8fa8

Browse files
committed
Refactor to cleanup control flow for pulling external events
1 parent 0542be0 commit 04c8fa8

File tree

11 files changed

+180
-175
lines changed

11 files changed

+180
-175
lines changed

src/dependencies.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export type Dependencies = {
5555
cacheSheetData: (
5656
cacheTimestamp: Date,
5757
sheetId: TrainingSheetId,
58+
logger: Logger,
5859
data: ReadonlyArray<
5960
| EventOfType<'EquipmentTrainingQuizSync'>
6061
| EventOfType<'EquipmentTrainingQuizResult'>

src/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,12 @@ const dbClient = libsqlClient.createClient({
3030
syncUrl: conf.TURSO_SYNC_URL,
3131
authToken: conf.TURSO_TOKEN,
3232
});
33-
const deps = initDependencies(dbClient, conf);
33+
const cacheClient = libsqlClient.createClient({
34+
url: conf.EVENT_DB_URL,
35+
syncUrl: conf.TURSO_SYNC_URL,
36+
authToken: conf.TURSO_TOKEN,
37+
});
38+
const deps = initDependencies(dbClient, cacheClient, conf);
3439
const routes = initRoutes(deps, conf);
3540

3641
// Passport Setup

src/init-dependencies/google/get-cached-sheet-data.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
internalCodecFailure,
1818
} from '../../types/failure-with-status';
1919
import {StatusCodes} from 'http-status-codes';
20+
import {Logger} from 'pino';
2021

2122
const extractCachedEvents = (
2223
rawCachedData: string
@@ -82,12 +83,14 @@ export const cacheSheetData =
8283
(
8384
cacheTimestamp: Date,
8485
sheetId: string,
86+
logger: Logger,
8587
data: ReadonlyArray<
8688
| EventOfType<'EquipmentTrainingQuizResult'>
8789
| EventOfType<'EquipmentTrainingQuizSync'>
8890
>
89-
) =>
90-
TE.tryCatch(
91+
) => {
92+
logger.info('Caching sheet data (%s entries)', data.length);
93+
return TE.tryCatch(
9194
() =>
9295
dbClient
9396
.execute({
@@ -107,3 +110,4 @@ export const cacheSheetData =
107110
.then(() => {}),
108111
failure('Failed to insert cached sheet data')
109112
);
113+
};

src/init-dependencies/init-dependencies.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424

2525
export const initDependencies = (
2626
dbClient: Client,
27+
cacheClient: Client,
2728
conf: Config
2829
): Dependencies => {
2930
let loggerOptions: LoggerOptions;
@@ -81,7 +82,7 @@ export const initDependencies = (
8182
});
8283
}
8384

84-
const _cacheSheetData = cacheSheetData(dbClient);
85+
const _cacheSheetData = cacheSheetData(cacheClient);
8586

8687
const sharedReadModel = initSharedReadModel(
8788
dbClient,

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

Lines changed: 61 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@ import * as E from 'fp-ts/Either';
33
import * as O from 'fp-ts/Option';
44
import {DomainEvent} from '../../types';
55
import {BetterSQLite3Database} from 'drizzle-orm/better-sqlite3';
6-
import {EpochTimestampMilliseconds, MinimalEquipment} from './return-types';
6+
import {EpochTimestampMilliseconds} from './return-types';
77

88
import {constructEvent, EventOfType} from '../../types/domain-event';
99
import {GoogleHelpers} from '../../init-dependencies/google/pull_sheet_data';
1010

1111
import {getAllEquipmentMinimal} from './equipment/get';
12-
import {expandLastQuizResult} from './equipment/expand';
1312
import {Dependencies} from '../../dependencies';
1413
import {
1514
extractGoogleSheetMetadata,
@@ -22,18 +21,17 @@ import {
2221
shouldPullFromSheet,
2322
} from '../../training-sheets/google';
2423
import {getChunkIndexes} from '../../util';
24+
import {UUID} from 'io-ts-types';
25+
import {expandLastQuizResult} from './equipment/expand';
2526

2627
const ROW_BATCH_SIZE = 200;
2728

28-
export type EquipmentWithLastQuizResult = MinimalEquipment & {
29-
lastQuizResult: O.Option<EpochTimestampMilliseconds>;
30-
};
31-
3229
const pullNewEquipmentQuizResultsForSheet = async (
3330
logger: Logger,
3431
googleHelpers: GoogleHelpers,
35-
equipment: EquipmentWithLastQuizResult,
32+
equipmentId: UUID,
3633
trainingSheetId: string,
34+
eventsFromExclusive: O.Option<EpochTimestampMilliseconds>,
3735
sheet: GoogleSheetMetadata,
3836
timezone: string,
3937
updateState: (event: EventOfType<'EquipmentTrainingQuizResult'>) => void
@@ -71,10 +69,10 @@ const pullNewEquipmentQuizResultsForSheet = async (
7169
const result = extractGoogleSheetData(
7270
logger,
7371
trainingSheetId,
74-
equipment.id,
72+
equipmentId,
7573
sheet,
7674
timezone,
77-
equipment.lastQuizResult
75+
eventsFromExclusive
7876
)(data.right);
7977
logger.info(
8078
'Google sheet data extracted, updating data with the extracted data...'
@@ -89,28 +87,16 @@ const pullNewEquipmentQuizResultsForSheet = async (
8987
export const pullNewEquipmentQuizResults = async (
9088
logger: Logger,
9189
googleHelpers: GoogleHelpers,
92-
equipment: EquipmentWithLastQuizResult,
90+
equipmentId: UUID,
91+
trainingSheetId: string,
92+
eventsSinceExclusive: O.Option<EpochTimestampMilliseconds>,
9393
updateState: (
9494
event:
9595
| EventOfType<'EquipmentTrainingQuizSync'>
9696
| EventOfType<'EquipmentTrainingQuizResult'>
9797
) => void
9898
): Promise<void> => {
99-
// TODO - Refactor this into fp-ts style.
100-
if (O.isNone(equipment.trainingSheetId)) {
101-
logger.warn(
102-
'No training sheet registered for equipment %s, skipping training data ingestion',
103-
equipment.name
104-
);
105-
// eslint-disable-next-line @typescript-eslint/require-await
106-
return;
107-
}
108-
const trainingSheetId = equipment.trainingSheetId.value;
109-
logger = logger.child({trainingSheetId});
110-
logger.info(
111-
'Scanning training sheet. Pulling google sheet data from %s...',
112-
equipment.lastQuizResult
113-
);
99+
logger.info('Scanning training sheet. Pulling google sheet data...');
114100

115101
const initialMeta = await googleHelpers.pullGoogleSheetDataMetadata(
116102
logger,
@@ -167,8 +153,9 @@ export const pullNewEquipmentQuizResults = async (
167153
await pullNewEquipmentQuizResultsForSheet(
168154
logger,
169155
googleHelpers,
170-
equipment,
156+
equipmentId,
171157
trainingSheetId,
158+
eventsSinceExclusive,
172159
sheet,
173160
initialMeta.right.properties.timeZone,
174161
updateState
@@ -181,7 +168,7 @@ export const pullNewEquipmentQuizResults = async (
181168

182169
updateState(
183170
constructEvent('EquipmentTrainingQuizSync')({
184-
equipmentId: equipment.id,
171+
equipmentId,
185172
})
186173
);
187174
};
@@ -191,8 +178,8 @@ export const asyncApplyExternalEventSources = (
191178
currentState: BetterSQLite3Database,
192179
googleHelpers: O.Option<GoogleHelpers>,
193180
updateState: (event: DomainEvent) => void,
194-
googleRateLimitMs: number,
195-
_cacheSheetData: Dependencies['cacheSheetData']
181+
googleRefreshIntervalMs: number,
182+
cacheSheetData: Dependencies['cacheSheetData']
196183
) => {
197184
return () => async () => {
198185
logger.info('Applying external event sources...');
@@ -201,54 +188,56 @@ export const asyncApplyExternalEventSources = (
201188
return;
202189
}
203190
for (const equipment of getAllEquipmentMinimal(currentState)) {
191+
const equipmentLogger = logger.child({equipment});
204192
if (
205-
O.isSome(equipment.trainingSheetId) &&
206-
(O.isNone(equipment.lastQuizSync) ||
207-
(Date.now() as EpochTimestampMilliseconds) -
208-
equipment.lastQuizSync.value >
209-
googleRateLimitMs)
193+
O.isNone(equipment.trainingSheetId) ||
194+
(O.isSome(equipment.lastQuizSync) &&
195+
Date.now() - equipment.lastQuizSync.value < googleRefreshIntervalMs)
210196
) {
211-
logger.info(
212-
'Triggering event update from google training sheets for %s...',
213-
equipment.name
214-
);
215-
const events: (
197+
equipmentLogger.info('No google training sheet refresh required');
198+
continue;
199+
}
200+
201+
equipmentLogger.info(
202+
'Triggering event update from google training sheets...'
203+
);
204+
205+
const events: (
206+
| EventOfType<'EquipmentTrainingQuizSync'>
207+
| EventOfType<'EquipmentTrainingQuizResult'>
208+
)[] = [];
209+
const collectEvents = (
210+
event:
216211
| EventOfType<'EquipmentTrainingQuizSync'>
217212
| EventOfType<'EquipmentTrainingQuizResult'>
218-
)[] = [];
219-
const collectEvents = (
220-
event:
221-
| EventOfType<'EquipmentTrainingQuizSync'>
222-
| EventOfType<'EquipmentTrainingQuizResult'>
223-
) => {
224-
events.push(event);
225-
updateState(event);
226-
};
227-
228-
await pullNewEquipmentQuizResults(
229-
logger,
230-
googleHelpers.value,
231-
expandLastQuizResult(currentState)(equipment),
232-
collectEvents
233-
);
234-
logger.info(
235-
'Finished pulling %s events from google training sheet for %s, caching...',
236-
events.length,
237-
equipment.name
213+
) => {
214+
events.push(event);
215+
updateState(event);
216+
};
217+
218+
await pullNewEquipmentQuizResults(
219+
equipmentLogger,
220+
googleHelpers.value,
221+
equipment.id,
222+
equipment.trainingSheetId.value,
223+
expandLastQuizResult(currentState)(equipment).lastQuizResult,
224+
collectEvents
225+
);
226+
equipmentLogger.info(
227+
'Finished pulling %s events from google training sheet, caching...',
228+
events.length
229+
);
230+
const x = await cacheSheetData(
231+
new Date(),
232+
equipment.trainingSheetId.value,
233+
equipmentLogger,
234+
events
235+
)();
236+
if (E.isLeft(x)) {
237+
equipmentLogger.error(
238+
'Failed to cache training sheet data due to: %s',
239+
x.left.message
238240
);
239-
// const x = await cacheSheetData(
240-
// new Date(),
241-
// equipment.trainingSheetId.value,
242-
// events
243-
// )();
244-
// if (E.isLeft(x)) {
245-
// logger.error(
246-
// 'Failed to cache training sheet data for %s training sheet id %s, due to: %s',
247-
// equipment.name,
248-
// equipment.trainingSheetId,
249-
// x.left.message
250-
// );
251-
// }
252241
}
253242
}
254243
logger.info('Finished applying external event sources');

tests/init-dependencies/happy-path-adapters.helper.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {localGoogleHelpers} from './pull-local-google';
1212
const cacheSheetData = (
1313
_cacheTimestamp: Date,
1414
_sheetId: string,
15+
_logger: Logger,
1516
_data: ReadonlyArray<
1617
| EventOfType<'EquipmentTrainingQuizSync'>
1718
| EventOfType<'EquipmentTrainingQuizResult'>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
Equipment,
1111
} from '../../src/read-models/shared-state/return-types';
1212

13-
describe.skip('Integration asyncApplyExternalEventSources', () => {
13+
describe('Integration asyncApplyExternalEventSources', () => {
1414
const addArea = async (framework: TestFramework) => {
1515
const createArea = {
1616
id: faker.string.uuid() as UUID,

0 commit comments

Comments
 (0)