The Biergarten Data Pipeline — Activity DiagramThe Biergarten Data Pipeline — Activity DiagramParseArguments(argc, argv)spdlog::erroryesInvalid args?noInit CurlGlobalState & LlamaBackendStateBuild DI injectorJsonLoader::LoadLocations("locations.json")JsonLoader::LoadBeerStyles("beer-styles.json")NEW: Beer styles do not need location context.Wikipedia summaries for the entire palette arefetched and cached globally at startup.EnrichmentService::PreWarmBeerStyleCache(beer_styles)Opens SQLite connection.Begins a single transactioncovering all five fixture types.Initialize SqliteExportServiceBiergartenPipelineOrchestrator::Run()COMMIT covers all five fixture types.Finalize SqliteExportServicespdlog::info "Pipeline complete in X ms"RunUserPhase(sampled_locations)Create BoundedChannels(user_llm_ch, user_exp_ch)Loop: Send Locations → user_llm_chClose user_llm_chJoin LLM Worker, SQLite WorkerRunBreweryAndBeerPhase(sampled_locations)Create BoundedChannels(loc_ch, llm_ch, exp_ch)Loop: Send Locations → loc_chClose loc_chJoin Enrichment WorkersClose llm_chBoth brewery_pool_ and beer_pool_are now completely populated.Join LLM Worker, SQLite WorkerRunCheckinPhase()ICheckinDistributionStrategy::AssignActivityWeights(user_pool_)CheckinsForUser(user, brewery_pool_.size())TimestampFor(user, index)Select brewery from brewery_pool_GenerateCheckin(user, brewery, timestamp)via DataGeneratorProcessCheckin(checkin) → sqlite3_int64Append → checkin_pool_remainingFor each checkin index?doneremainingFor each GeneratedUser in user_pool_?doneRunRatingPhase()Match brewery_id → select beerfrom beer_pool_ (same brewery_id)Beer exists for brewery?yesnoGenerateRating(user, beer, checkin_id)via DataGeneratorProcessRating(rating)Skip — brewery has no beersremainingFor each GeneratedCheckin in checkin_pool_?doneReceive LocationGenerateUser(location)via DataGeneratorSend GeneratedUser → user_exp_chyesuser_llm_ch has items?noClose user_exp_chReceive EnrichedCityGenerateBrewery(location, context)via DataGeneratorIBeerSelectionStrategy::SelectStyles(brewery, beer_style_palette_)Guaranteed cache hit from startup.GetStyleContextFromCache(style)GenerateBeer(brewery, style_context)via DataGeneratorAttach GeneratedBeer to Brewery bundleremainingFor each selected BeerStyle?doneThe next generation of a brewery isentirely dependent on the currentbrewery and its beers completing.Send BreweryWithBeers Bundle → exp_chyesllm_ch has items?noClose exp_chReceive GeneratedUserProcessUser(user) → sqlite3_int64Append → user_pool_yesuser_exp_ch has items?noReceive BreweryWithBeers BundleProcessBrewery(brewery) → brewery_idAppend → brewery_pool_Set beer.brewery_id = brewery_idProcessBeer(beer) → sqlite3_int64Append → beer_pool_remainingFor each beer in bundle?doneyesexp_ch has items?noReceive LocationGetLocationContext(location,BreweryContextStrategy)Send EnrichedCity → llm_chyesloc_ch has items?noMainOrchestratorLLM WorkerSQLite WorkerEnrichment Workers (xN)