feat: add full scan controller
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
import type {
|
||||
MarketApiFailureReason,
|
||||
MarketApiResult,
|
||||
MarketRowSnapshot
|
||||
} from "./types";
|
||||
import type { AfterSearchRates } from "./types";
|
||||
|
||||
interface ResultStoreLike {
|
||||
setAuthorFailed(authorId: string, reason: MarketApiFailureReason): void;
|
||||
setAuthorLoading(authorId: string): void;
|
||||
setAuthorSuccess(
|
||||
authorId: string,
|
||||
rates: Required<AfterSearchRates>
|
||||
): void;
|
||||
upsertMarketRow(row: MarketRowSnapshot): void;
|
||||
}
|
||||
|
||||
interface FullScanControllerOptions {
|
||||
goToNextPage(): Promise<boolean>;
|
||||
hasNextPage(): boolean;
|
||||
loadAuthorMetrics(authorId: string): Promise<MarketApiResult>;
|
||||
readCurrentPageRows(): MarketRowSnapshot[];
|
||||
resultStore: ResultStoreLike;
|
||||
}
|
||||
|
||||
export function createFullScanController(options: FullScanControllerOptions) {
|
||||
let completedScan = false;
|
||||
let scanPromise: Promise<void> | null = null;
|
||||
|
||||
return {
|
||||
ensureScanForExport() {
|
||||
return ensureScan();
|
||||
},
|
||||
ensureScanForFilter() {
|
||||
return ensureScan();
|
||||
},
|
||||
ensureScanForSort() {
|
||||
return ensureScan();
|
||||
}
|
||||
};
|
||||
|
||||
function ensureScan(): Promise<void> {
|
||||
if (completedScan) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
if (scanPromise) {
|
||||
return scanPromise;
|
||||
}
|
||||
|
||||
scanPromise = runScan().finally(() => {
|
||||
scanPromise = null;
|
||||
});
|
||||
return scanPromise;
|
||||
}
|
||||
|
||||
async function runScan(): Promise<void> {
|
||||
do {
|
||||
await scanCurrentPage();
|
||||
if (!options.hasNextPage()) {
|
||||
completedScan = true;
|
||||
return;
|
||||
}
|
||||
} while (await options.goToNextPage());
|
||||
|
||||
completedScan = true;
|
||||
}
|
||||
|
||||
async function scanCurrentPage(): Promise<void> {
|
||||
const rows = options.readCurrentPageRows();
|
||||
|
||||
for (const row of rows) {
|
||||
options.resultStore.upsertMarketRow(row);
|
||||
options.resultStore.setAuthorLoading(row.authorId);
|
||||
|
||||
const metricsResult = await options.loadAuthorMetrics(row.authorId);
|
||||
if (metricsResult.success) {
|
||||
options.resultStore.setAuthorSuccess(row.authorId, metricsResult.rates);
|
||||
continue;
|
||||
}
|
||||
|
||||
options.resultStore.setAuthorFailed(row.authorId, metricsResult.reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user