TheYard data flow

Pinch or Ctrl+scroll to zoom; the text is selectable. Source · TheYard

TheYard data flow: a vehicle from a JSON file on disk to a card in the browser, and a bid back TheYard data flow: a vehicle from a JSON file to a card in the browser, and a bid back Every box is a file; the path under each title is where that step lives. Domain, Application, Infrastructure and Api are the projects under api/; render/ is the rendering service beside them. The read path, top to bottom The first four boxes run once at startup; the rest run for every request, and a page's first read runs on the rendering service. The write path: a bid A signed-in buyer, bids kept in the store; the domain decides. The seed file data/vehicles.json The 200 records from the challenge, never modified. The Vehicle record they load into lives with the other plain data shapes in api/TheYard.Data. once, at startup JsonFileVehicleSource api/TheYard.Infrastructure/JsonFileSources.cs Reads the seed once, at startup. SyntheticVehicleSource api/TheYard.Infrastructure/SyntheticVehicleSource.cs Expands 200 to 100,000 deterministic variants. Each new id is hashed (FNV-1a, api/TheYard.Domain/Fnv1a.cs) to vary the VIN, year, odometer, prices and bid state while keeping the seed's make, model and trim mix. InventoryService api/TheYard.Application/InventoryService.cs Applies each vehicle's photo gallery (api/TheYard.Domain/PhotoGallery.cs picks from the pools in api/TheYard.Api/photo-manifest.json) and materializes the list plus an id index once. The host awaits that load in api/TheYard.Api/Composition/Startup.cs before it serves. then, for every request GET /api/vehicles api/TheYard.Api/Endpoints/VehicleEndpoints.cs api/TheYard.Api/VehicleQueryParams.cs binds and validates every parameter into a filter and a sort. The clock is the server's (api/TheYard.Api/Clocks.cs): now, and the UTC midnight that began the day, the same for every visitor. Search, through Auction.Search api/TheYard.Application/Auction.cs 1. Everybody's bids, then the room's, are laid over each vehicle (Auction.Overlay, raising a price through api/TheYard.Domain/StandingRules.cs), so price bounds see the figures the page shows. 2. Where: api/TheYard.Domain/VehicleFilter.cs 3. OrderBy: api/TheYard.Domain/VehicleOrdering.cs 4. Skip and Take for the page. Auction windows come from api/TheYard.Domain/AuctionSchedule.cs, all in memory. VehicleWire api/TheYard.Api/VehicleWire.cs Stamps the server-derived facts on each vehicle: auction_starts_at, auction_ends_at, auction_status, min_next_bid. The endpoint answers { total, vehicles } in snake_case. { total, vehicles } as JSON The rendering service, for a page render/loaders.ts, render/render.ts A page request (the bare path with its query) comes here from the edge, not to the API. One loader per view reads what the address needs from the API above (for the inventory, the listing with its facets), all at once under a 2.5 s deadline, then src/app/entry-server.tsx draws the site with React's server renderer and the HTML leaves with the first load, the JSON the reads answered, written beside #root. A read that misses the deadline is left to the browser. the page, drawn, with its first load The fetch seam src/lib/data.ts In the browser, src/app/mount.tsx starts every hook from the first load the page carries, so the first draw matches the server's and React takes the page over instead of drawing it again. After that: debounces filter changes (500 ms), caches responses per query string for five minutes (a hit skips the debounce) and aborts superseded requests. The query string comes from src/lib/inventory.ts, the same serializer that feeds the address bar. App state and the address bar src/app/hooks/useAddressBar.ts Holds the page. Filters, sort, ?vehicle and ?view are mirrored into the URL, and Back and Forward re-read it. Cards, detail, bid panel src/components/* Format currency (src/lib/format.ts) and tick the countdowns from the server's window (src/lib/auction.ts). No business math runs in the browser. BidPanel src/components/vehicle/BidPanel/BidPanel.tsx Posts { amount } to POST /api/vehicles/{id}/bids through src/lib/data.ts; buy now posts to /buy-now. Only a signed-in buyer can. POST HandleBid api/TheYard.Api/Endpoints/BidEndpoints.cs Three questions in order: is this session on this store (401 if not), does the vehicle exist (404 if not), does the domain accept the action (400 with the reason if not). the Application ring Auction.PlaceBidAsync api/TheYard.Application/Auction.cs Measures the bid against the room's standing price as well as everybody's bids, so nobody retakes a lead below the going rate. the domain decides BidRules api/TheYard.Domain/BidRules.cs The sole authority: the live window, the tiered minimum increment, and the buy-now override (a bid at or above buy_now_price wins outright at that price). accepted, won, or rejected BidService api/TheYard.Application/BidService.cs Under one gate: an accepted or won bid is written to the store (Azure SQL Database or Cosmos DB, through the IBidStore port) and then to memory, under the buyer's account. The response carries the updated vehicle with a fresh min_next_bid. the updated vehicle useBids src/hooks/useBids.ts Clears the query cache and refetches, so every list, filter and total reflects the bid through the same read path. refetch, through the same read path One rule shapes everything: derive, do not store. Windows, statuses, galleries and the 100,000 inventory are computed from stable ids, never persisted. Source: docs/images/dataflow.svg in the repository, drawn by docs/images/dataflow.mjs and redrawn when a box moves.