ADR-0011: Vacancy geocode stage
Geocode vacancy locations in one fixed flow stage instead of enrichment children.
Status: Proposed. Implementation available for review.
Date: 2026-09-23
Context
ADR-0007 keeps an enrich stage that adds one geocode child per location and one recruiter-match child per contact, waits for them, and combines their results. A failed child does not fail the vacancy: its slot stays empty and enrich records the failure. Recruiter-match only returns a stub. The enrich stage needs an input mapper for several child results and reads error codes back from failed-job messages.
Decision
This ADR replaces the enrich stage and its optional children in ADR-0007 and ADR-0010. The vacancy ingestion sequence is:
harvest -> classify -> geocode -> embed -> finalizeThe geocode job receives the classify result. It geocodes each classified
location in order through GeoClient with the location layers, and adds
geocodedLocations with one slot per location. A location without a match, or
with a match that has no country, keeps its slot as null. A job listing or a
closed job detail is not geocoded. The processor owns these rules; the
@gigflow/geo package owns the Pelias client.
A geocoding provider failure retries the geocode job. When all attempts fail, the vacancy flow fails. The vacancy is not stored without its locations. The next harvest submits the source again.
The classify result field preprocess.markdown becomes markdown.
Consequences
The vacancy-enrich and vacancy-recruiter-match queues, job contracts, and
workers are removed. Flows published with the old graph wait for an enrich job
that no worker runs. Each keeps an admission slot, because the scheduler frees a
slot only when the flow root completes or fails. Drain both queues before
deployment, or cancel those ingestions afterwards with
VacancyClient.cancelIngestion, which removes the flow and frees the slot. Do
not delete their jobs directly: a request whose flow root was deleted keeps its
slot.
A Pelias outage that outlasts the retries now stops vacancies instead of storing them without coordinates. Recruiter matching is not part of the pipeline until a stage needs it.
Verification
From the repository root, with local Redis from dev/cli/dev up engine, run:
bun --env-file=apps/engine/apps/workers/vacancy/geocode/.env \
test --timeout 30000 apps/engine/apps/workers/vacancy/geocode/e2eThe test runs the real worker against a local Pelias fixture. The report is
written to .context/verification/vacancy-geocode/geocode-stage/report.json.