Fetch a Teamtailor description only for a posting we do not have - #1994
Conversation
The crawl fetched every posting's detail page every hour. Measured on prod: ~40k live postings on the board file, about ONE an hour genuinely new — so a run spent ~36.7k detail requests to discover ~100 postings, and fired them in ten minutes. That volume is what Teamtailor's edge turned away, 1208 of 1987 boards 403'd, and what pacing (#1992) could only spread out rather than remove. HydratingSource is the seam for exactly this and thirteen adapters already implement it, workday among them — a per-tenant ATS like this one. FetchNew enumerates the board as before but hydrates only ids the catalogue lacks; a seen posting is emitted as a liveness refresh carrying identity alone, which the pipeline routes to a touch instead of a write. That distinction is load-bearing: a content-less re-upsert would re-derive the facets from an empty description and wipe them. Fetch keeps hydrating everything. It is the fallback the pipeline uses when it cannot supply a seen set, and the case the pacer's interval is still sized for. A steady-state run should now cost ~4k requests instead of ~41k — nearly all of them the listing pages that enumerate the board.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
Included review availability: Your plan includes up to 2 reviews per rolling hour; 1 remains after this review. 📝 WalkthroughWalkthroughTeamtailor now enumerates listing URLs separately from detail hydration. ChangesTeamtailor hydration flow
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to The change limits detail-page fetching to postings the catalogue does not already contain while preserving liveness refreshes for known postings; no actionable merge-blocking risk remains after normal checks and review. Sequence Diagram(s)sequenceDiagram
participant FetchNew
participant jobURLs
participant SeenSet
participant DetailEndpoint
FetchNew->>jobURLs: enumerate all posting URLs
jobURLs-->>FetchNew: return URL list
FetchNew->>SeenSet: check native posting ID
alt Posting is seen
FetchNew-->>FetchNew: emit SeenRefresh identity
else Posting is unseen
FetchNew->>DetailEndpoint: fetch posting details
end
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…elov1#1994) The crawl fetched every posting's detail page every hour. Measured on prod: ~40k live postings on the board file, about ONE an hour genuinely new — so a run spent ~36.7k detail requests to discover ~100 postings, and fired them in ten minutes. That volume is what Teamtailor's edge turned away, 1208 of 1987 boards 403'd, and what pacing (strelov1#1992) could only spread out rather than remove. HydratingSource is the seam for exactly this and thirteen adapters already implement it, workday among them — a per-tenant ATS like this one. FetchNew enumerates the board as before but hydrates only ids the catalogue lacks; a seen posting is emitted as a liveness refresh carrying identity alone, which the pipeline routes to a touch instead of a write. That distinction is load-bearing: a content-less re-upsert would re-derive the facets from an empty description and wipe them. Fetch keeps hydrating everything. It is the fallback the pipeline uses when it cannot supply a seen set, and the case the pacer's interval is still sized for. A steady-state run should now cost ~4k requests instead of ~41k — nearly all of them the listing pages that enumerate the board.
The waste
The Teamtailor crawl fetched every posting's detail page every hour, because that is where
the description lives. Measured on prod 2026-08-16:
So a run spent ~36.7k requests to discover ~100 postings, and fired them in ten minutes — about
62 req/s at one career-site vendor. That volume is what Teamtailor's edge turned away (1208 of
1987 boards 403'd), and what #1989 and #1992 could only recover or spread out rather than remove.
The fix already had a seam
HydratingSourceexists for exactly this and thirteen adapters already implement it —workdayamong them, a per-tenant ATS like this one. The pipeline supplies aseen(externalID)predicate; the adapter hydrates only what the catalogue lacks.
FetchNewenumerates the board exactly as before and then:That second branch is load-bearing rather than an optimisation detail: the pipeline routes a
SeenRefreshto a liveness touch instead of a write, because a content-less re-upsert wouldre-derive the facets from an empty description and wipe them.
Fetchis untouched and still hydrates everything — it is the fallback used when the pipelinecannot supply a seen set, and the worst case the pacer's interval is still sized for.
Expected effect
A steady-state run should cost ~4k requests instead of ~41k, nearly all of them the listing
pages that enumerate the board. That also unwinds the trend this exposed: run duration had crept
31 → 42 minutes against the unit's 50-minute
TimeoutStartSec, and it was creeping because theearlier fixes worked — more boards answering means more postings found means more detail
fetches.
Tests
The request count is the deliverable, so it is asserted directly: three postings listed with two
already seen makes exactly three requests (two listing pages, one detail). Plus: a seen posting
is marked
SeenRefreshand carries no content, an unseen one is hydrated, an all-seen boardtouches no detail page at all, a failed listing still fails the board (an empty result would let
the unseen sweep close everything the board still has), and
Fetchstill hydrates everything.Summary by CodeRabbit
Performance
Reliability
Tests