mirror of
https://github.com/Crosstalk-Solutions/project-nomad.git
synced 2026-10-17 05:14:19 +02:00
On 1.34.0 every FDA ingest finished with its labels loaded but lost the
installed_resources 'dataset' row, because resource_type was still
enum('zim','map'). The enum migration in #1243 fixes new writes but can't recreate
the lost row. Re-selecting the tier doesn't fix it either, because ZimService
skips a dataset that already has rows. So Medicine never resolved its
Standard tier.
- Add DrugInstallRowProvider. On each boot it backfills the row when an
ingest has finished (rows present, export date set, no download
marker, no drug job running) and no row exists.
- Put the decision in decideDrugRowReconcile() so it has unit tests.
- Add DrugReferenceService.recordInstalledRow() as the one writer used
by the ingest job, the provider, and ZimService.
- ZimService now writes the row when a Medicine tier re-select finds a
finished ingest with no row.
Manual ingests and reset-and-reingest runs, which dispatch without
resourceMeta, also get the row on the next boot.
67 lines
2.7 KiB
TypeScript
67 lines
2.7 KiB
TypeScript
import type { ZimCategoriesSpec } from '../../types/collections.js'
|
|
|
|
/**
|
|
* Observed state of the FDA drug dataset, gathered at admin boot by
|
|
* DrugInstallRowProvider.
|
|
*/
|
|
export interface DrugRowReconcileInput {
|
|
/** Rows in `drug_labels`. */
|
|
rowCount: number
|
|
/** Whether the `installed_resources` 'dataset' row already exists. */
|
|
hasInstallRow: boolean
|
|
/** KV `drugReference.lastUpdatedExportDate`; only the final ingest pass sets it. */
|
|
lastUpdatedExportDate: string | null
|
|
/** Whether KV `drugReference.downloadState` still holds a marker. */
|
|
hasDownloadMarker: boolean
|
|
/** Whether either drug queue has an active/waiting/delayed job. */
|
|
jobInFlight: boolean
|
|
}
|
|
|
|
export type DrugRowReconcileDecision =
|
|
| { action: 'backfill'; version: string }
|
|
| { action: 'skip'; reason: string }
|
|
|
|
/**
|
|
* Decide whether a completed drug ingest is missing its `installed_resources`
|
|
* row and should get one.
|
|
*
|
|
* On 1.34.0 the column was still enum('zim','map'), so every ingest finished
|
|
* `ready` with 261k labels and a failed row write. The tier-status math reads
|
|
* that row, so Medicine never resolved its Standard tier. The same state also
|
|
* follows a manual ingest (no resourceMeta), including a reset-and-reingest.
|
|
*
|
|
* Backfill only when the ingest provably finished: the export-date marker is
|
|
* written by the final pass, and the download marker is cleared right after it
|
|
* (the same "completed" inference getIngestStatus() makes). A running job is
|
|
* left alone, since it writes its own row on `ready`.
|
|
*/
|
|
export function decideDrugRowReconcile(input: DrugRowReconcileInput): DrugRowReconcileDecision {
|
|
if (input.hasInstallRow) return { action: 'skip', reason: 'install row present' }
|
|
if (input.rowCount <= 0) return { action: 'skip', reason: 'no drug labels ingested' }
|
|
if (input.jobInFlight) return { action: 'skip', reason: 'drug download/ingest in flight' }
|
|
if (input.hasDownloadMarker) {
|
|
return { action: 'skip', reason: 'download marker present (ingest not finished)' }
|
|
}
|
|
const version = input.lastUpdatedExportDate?.trim()
|
|
if (!version) return { action: 'skip', reason: 'no export date (ingest never completed)' }
|
|
return { action: 'backfill', version }
|
|
}
|
|
|
|
/**
|
|
* Slug of the curated category whose tiers carry the given dataset resource,
|
|
* for the row's `collection_ref`. Null when the spec is absent or no tier lists it.
|
|
*/
|
|
export function findDatasetCategorySlug(
|
|
spec: ZimCategoriesSpec | null,
|
|
resourceId: string
|
|
): string | null {
|
|
for (const category of spec?.categories ?? []) {
|
|
for (const tier of category.tiers ?? []) {
|
|
if ((tier.resources ?? []).some((r) => r.type === 'dataset' && r.id === resourceId)) {
|
|
return category.slug
|
|
}
|
|
}
|
|
}
|
|
return null
|
|
}
|