@startuml skinparam style strictuml skinparam defaultFontName "DM Sans" skinparam defaultFontSize 14 skinparam titleFontName "Volkhov" skinparam titleFontSize 20 skinparam backgroundColor #FAFCF9 skinparam defaultFontColor #28342A skinparam titleFontColor #28342A skinparam ArrowColor #628A5B skinparam NoteBackgroundColor #EAF0E8 skinparam NoteBorderColor #547461 skinparam ActivityBackgroundColor #FAFCF9 skinparam ActivityBorderColor #547461 skinparam ActivityDiamondBackgroundColor #FAFCF9 skinparam ActivityDiamondBorderColor #628A5B skinparam ActivityBarColor #628A5B skinparam SwimlaneBorderColor #547461 skinparam SwimlaneBorderThickness 0.3 title The Biergarten Data Pipeline (Streaming Architecture) |#F2F6F0|main.cc| start :ParseArguments(argc, argv); if (Are arguments valid?) then (no) :spdlog::error usage info; stop else (yes) endif :Init CurlGlobalState & LlamaBackendState; :di::make_injector(...); :injector.create>(); :BiergartenDataGenerator::Run(); |#EAF0E8|BiergartenDataGenerator| :Initialize SQLite export; |#E0EAE0|SqliteExportService| :GetUtcTimestamp() from SystemDateTimeProvider; :Initialize(); note right Builds a fresh biergarten_seed_.sqlite filename Appends a numeric suffix if the timestamp already exists Opens DB Connection Executes Schema DDL Begins Transaction end note |#EAF0E8|BiergartenDataGenerator| :QueryCitiesWithCountries(); |#E2EBDC|JsonLoader| :JsonLoader::LoadLocations("locations.json"); :std::ranges::sample(all_locations, 50); |#EAF0E8|BiergartenDataGenerator| while (For each sampled Location?) is (Remaining cities) |#DCE8D8|WikipediaService| :GetLocationContext(loc); :FetchExtracts(City, Country, Beer); |#EAF0E8|BiergartenDataGenerator| :Store EnrichedCity{Location, region_context}; endwhile (Done) |#EAF0E8|BiergartenDataGenerator| :GenerateBreweries(enriched_cities); |#E5EDE1|DataGenerator| while (For each EnrichedCity?) is (Remaining cities) if (Generator Mode) then (MockGenerator) :DeterministicHash & Format; else (LlamaGenerator) :PrepareRegionContext; :LoadBrewerySystemPrompt("prompts/system.md"); repeat :Infer(system_prompt, user_prompt, max_tokens, kBreweryJsonGrammar); :ValidateBreweryJson(raw, brewery); if (Is JSON Valid?) then (yes) break else (no) :Attempt++; endif repeat while (Attempt < 3?) is (yes) endif |#EAF0E8|BiergartenDataGenerator| if (Generation successful?) then (yes) |#E0EAE0|SqliteExportService| :ProcessRecord(GeneratedBrewery); if (Location in cache?) then (yes) :Reuse location_id; else (no) :Insert Location & Cache ID; endif :Insert Brewery (FK: location_id); if (Exception caught during insert?) then (yes) |#EAF0E8|BiergartenDataGenerator| :spdlog::warn "Failed to stream record to SQLite export"; note right Data loss is prevented per-record. The pipeline continues running. end note else (no) endif else (no) :spdlog::warn "Generation failed, skipping..."; endif |#E5EDE1|DataGenerator| endwhile (Done) |#E0EAE0|SqliteExportService| :Finalize(); note right Commits Transaction Closes Database Connection end note |#F2F6F0|main.cc| :Return 0; stop @enduml