[{"data":1,"prerenderedAt":2689},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Fruntime":314,"\u002Fdocs\u002Fruntime-surround":2684},[4,38,86,149,176,219,257,273],{"title":5,"path":6,"stem":7,"children":8,"icon":37},"Getting Started","\u002Fdocs\u002Fgetting-started","1.docs\u002F1.getting-started\u002F1.index",[9,12,17,22,27,32],{"title":10,"path":6,"stem":7,"icon":11},"Getting started","i-lucide-flag",{"title":13,"path":14,"stem":15,"icon":16},"Modules overview","\u002Fdocs\u002Fgetting-started\u002Fmodules-overview","1.docs\u002F1.getting-started\u002F2.modules-overview","i-lucide-boxes",{"title":18,"path":19,"stem":20,"icon":21},"Installation","\u002Fdocs\u002Fgetting-started\u002Finstallation","1.docs\u002F1.getting-started\u002F3.installation","i-lucide-download",{"title":23,"path":24,"stem":25,"icon":26},"License configuration","\u002Fdocs\u002Fgetting-started\u002Flicense-configuration","1.docs\u002F1.getting-started\u002F4.license-configuration","i-lucide-key-round",{"title":28,"path":29,"stem":30,"icon":31},"Your first app","\u002Fdocs\u002Fgetting-started\u002Ffirst-app","1.docs\u002F1.getting-started\u002F5.first-app","i-lucide-square-play",{"title":33,"path":34,"stem":35,"icon":36},"Project setup","\u002Fdocs\u002Fgetting-started\u002Fproject-setup","1.docs\u002F1.getting-started\u002F6.project-setup","i-lucide-package",false,{"title":39,"path":40,"stem":41,"children":42,"icon":45},"Core Concepts","\u002Fdocs\u002Fconcepts","1.docs\u002F2.concepts\u002F1.index",[43,46,51,56,61,66,71,76,81],{"title":44,"path":40,"stem":41,"icon":45},"Core concepts","i-lucide-book-open",{"title":47,"path":48,"stem":49,"icon":50},"Architecture","\u002Fdocs\u002Fconcepts\u002Farchitecture","1.docs\u002F2.concepts\u002F2.architecture","i-lucide-layers",{"title":52,"path":53,"stem":54,"icon":55},"Exactly-once semantics","\u002Fdocs\u002Fconcepts\u002Fexactly-once","1.docs\u002F2.concepts\u002F3.exactly-once","i-lucide-shield-check",{"title":57,"path":58,"stem":59,"icon":60},"Lanes and parallelism","\u002Fdocs\u002Fconcepts\u002Flanes-and-parallelism","1.docs\u002F2.concepts\u002F4.lanes-and-parallelism","i-lucide-split",{"title":62,"path":63,"stem":64,"icon":65},"State and thread-safety","\u002Fdocs\u002Fconcepts\u002Fstate-and-thread-safety","1.docs\u002F2.concepts\u002F5.state-and-thread-safety","i-lucide-lock",{"title":67,"path":68,"stem":69,"icon":70},"Event time and watermarks","\u002Fdocs\u002Fconcepts\u002Fevent-time-and-watermarks","1.docs\u002F2.concepts\u002F6.event-time-and-watermarks","i-lucide-clock",{"title":72,"path":73,"stem":74,"icon":75},"The configuration model","\u002Fdocs\u002Fconcepts\u002Fconfiguration-model","1.docs\u002F2.concepts\u002F7.configuration-model","i-lucide-sliders-horizontal",{"title":77,"path":78,"stem":79,"icon":80},"The error-handling model","\u002Fdocs\u002Fconcepts\u002Ferror-handling-model","1.docs\u002F2.concepts\u002F8.error-handling-model","i-lucide-triangle-alert",{"title":82,"path":83,"stem":84,"icon":85},"How StoatFlow differs from Kafka Streams","\u002Fdocs\u002Fconcepts\u002Fhow-stoatflow-differs-from-ks","1.docs\u002F2.concepts\u002F9.how-stoatflow-differs-from-ks","i-lucide-arrow-left-right",{"title":87,"path":88,"stem":89,"children":90,"icon":93},"Building Topologies","\u002Fdocs\u002Fbuilding","1.docs\u002F3.building\u002F1.index",[91,94,99,104,109,114,119,124,129,134,139,144],{"title":92,"path":88,"stem":89,"icon":93},"Building topologies","i-lucide-blocks",{"title":95,"path":96,"stem":97,"icon":98},"Error handling and DLQ","\u002Fdocs\u002Fbuilding\u002Ferror-handling-dlq","1.docs\u002F3.building\u002F10.error-handling-dlq","i-lucide-circle-x",{"title":100,"path":101,"stem":102,"icon":103},"State stores","\u002Fdocs\u002Fbuilding\u002Fstate-stores","1.docs\u002F3.building\u002F11.state-stores","i-lucide-database",{"title":105,"path":106,"stem":107,"icon":108},"Testing topologies","\u002Fdocs\u002Fbuilding\u002Ftesting","1.docs\u002F3.building\u002F12.testing","i-lucide-flask-conical",{"title":110,"path":111,"stem":112,"icon":113},"Sources and sinks","\u002Fdocs\u002Fbuilding\u002Fstreams-builder","1.docs\u002F3.building\u002F2.streams-builder","i-lucide-import",{"title":115,"path":116,"stem":117,"icon":118},"KStream and KTable operations","\u002Fdocs\u002Fbuilding\u002Fkstream-ktable","1.docs\u002F3.building\u002F3.kstream-ktable","i-lucide-waypoints",{"title":120,"path":121,"stem":122,"icon":123},"Aggregations","\u002Fdocs\u002Fbuilding\u002Faggregations","1.docs\u002F3.building\u002F4.aggregations","i-lucide-sigma",{"title":125,"path":126,"stem":127,"icon":128},"Windowing","\u002Fdocs\u002Fbuilding\u002Fwindowing","1.docs\u002F3.building\u002F5.windowing","i-lucide-calendar-clock",{"title":130,"path":131,"stem":132,"icon":133},"Joins","\u002Fdocs\u002Fbuilding\u002Fjoins","1.docs\u002F3.building\u002F6.joins","i-lucide-git-merge",{"title":135,"path":136,"stem":137,"icon":138},"The Processor API","\u002Fdocs\u002Fbuilding\u002Fprocessor-api","1.docs\u002F3.building\u002F7.processor-api","i-lucide-cpu",{"title":140,"path":141,"stem":142,"icon":143},"Scheduled sources","\u002Fdocs\u002Fbuilding\u002Fscheduled-sources","1.docs\u002F3.building\u002F8.scheduled-sources","i-lucide-timer",{"title":145,"path":146,"stem":147,"icon":148},"Serdes and Avro","\u002Fdocs\u002Fbuilding\u002Fserdes","1.docs\u002F3.building\u002F9.serdes","i-lucide-binary",{"title":150,"path":151,"stem":152,"children":153,"icon":75},"Configuration","\u002Fdocs\u002Fconfiguration","1.docs\u002F4.configuration\u002F1.index",[154,156,161,166,171],{"title":155,"path":151,"stem":152,"icon":75},"How configuration works",{"title":157,"path":158,"stem":159,"icon":160},"Engine configuration (:core)","\u002Fdocs\u002Fconfiguration\u002Fcore-config","1.docs\u002F4.configuration\u002F2.core-config","i-lucide-settings-2",{"title":162,"path":163,"stem":164,"icon":165},"Runtime configuration (:runtime)","\u002Fdocs\u002Fconfiguration\u002Fruntime-config","1.docs\u002F4.configuration\u002F3.runtime-config","i-lucide-server-cog",{"title":167,"path":168,"stem":169,"icon":170},"Defaults, adaptivity, and presets","\u002Fdocs\u002Fconfiguration\u002Fdefaults-and-presets","1.docs\u002F4.configuration\u002F4.defaults-and-presets","i-lucide-gauge",{"title":172,"path":173,"stem":174,"icon":175},"Kafka client configuration","\u002Fdocs\u002Fconfiguration\u002Fkafka-client-config","1.docs\u002F4.configuration\u002F5.kafka-client-config","i-lucide-plug",{"title":177,"path":178,"stem":179,"children":180,"icon":183},"Running in Production","\u002Fdocs\u002Fruntime","1.docs\u002F5.runtime\u002F1.index",[181,184,189,194,199,204,209,214],{"title":182,"path":178,"stem":179,"icon":183},"The runtime","i-lucide-server",{"title":185,"path":186,"stem":187,"icon":188},"The REST API","\u002Fdocs\u002Fruntime\u002Frest-api","1.docs\u002F5.runtime\u002F2.rest-api","i-lucide-globe",{"title":190,"path":191,"stem":192,"icon":193},"Health checks","\u002Fdocs\u002Fruntime\u002Fhealth-checks","1.docs\u002F5.runtime\u002F3.health-checks","i-lucide-heart-pulse",{"title":195,"path":196,"stem":197,"icon":198},"Metrics","\u002Fdocs\u002Fruntime\u002Fmetrics","1.docs\u002F5.runtime\u002F4.metrics","i-lucide-activity",{"title":200,"path":201,"stem":202,"icon":203},"Pause and resume","\u002Fdocs\u002Fruntime\u002Fpause-unpause","1.docs\u002F5.runtime\u002F5.pause-unpause","i-lucide-pause",{"title":205,"path":206,"stem":207,"icon":208},"Plugins and lifecycle hooks","\u002Fdocs\u002Fruntime\u002Fplugins","1.docs\u002F5.runtime\u002F6.plugins","i-lucide-puzzle",{"title":210,"path":211,"stem":212,"icon":213},"Docker images","\u002Fdocs\u002Fruntime\u002Fdocker","1.docs\u002F5.runtime\u002F7.docker","i-lucide-container",{"title":215,"path":216,"stem":217,"icon":218},"GraalVM native image","\u002Fdocs\u002Fruntime\u002Fnative-image","1.docs\u002F5.runtime\u002F8.native-image","i-lucide-zap",{"title":220,"path":221,"stem":222,"children":223,"icon":226},"Deploying & Operating","\u002Fdocs\u002Foperating","1.docs\u002F6.operating\u002F1.index",[224,227,232,237,242,247,252],{"title":225,"path":221,"stem":222,"icon":226},"Deploying and operating","i-lucide-life-buoy",{"title":228,"path":229,"stem":230,"icon":231},"Running on Kubernetes","\u002Fdocs\u002Foperating\u002Fkubernetes","1.docs\u002F6.operating\u002F2.kubernetes","i-lucide-ship",{"title":233,"path":234,"stem":235,"icon":236},"High availability","\u002Fdocs\u002Foperating\u002Fhigh-availability","1.docs\u002F6.operating\u002F3.high-availability","i-lucide-copy",{"title":238,"path":239,"stem":240,"icon":241},"Liveness and readiness probes","\u002Fdocs\u002Foperating\u002Fprobes","1.docs\u002F6.operating\u002F4.probes","i-lucide-stethoscope",{"title":243,"path":244,"stem":245,"icon":246},"Observability","\u002Fdocs\u002Foperating\u002Fobservability","1.docs\u002F6.operating\u002F5.observability","i-lucide-telescope",{"title":248,"path":249,"stem":250,"icon":251},"Tuning under load","\u002Fdocs\u002Foperating\u002Ftuning","1.docs\u002F6.operating\u002F6.tuning","i-lucide-sliders",{"title":253,"path":254,"stem":255,"icon":256},"Production checklist","\u002Fdocs\u002Foperating\u002Fproduction-checklist","1.docs\u002F6.operating\u002F7.production-checklist","i-lucide-clipboard-check",{"title":258,"path":259,"stem":260,"children":261,"icon":85},"Migrating from Kafka Streams","\u002Fdocs\u002Fmigration","1.docs\u002F7.migration\u002F1.index",[262,263,268],{"title":258,"path":259,"stem":260,"icon":85},{"title":264,"path":265,"stem":266,"icon":267},"Migration without carrying state","\u002Fdocs\u002Fmigration\u002Fwithout-data-migration","1.docs\u002F7.migration\u002F2.without-data-migration","i-lucide-sparkles",{"title":269,"path":270,"stem":271,"icon":272},"Migration carrying state","\u002Fdocs\u002Fmigration\u002Fwith-data-migration","1.docs\u002F7.migration\u002F3.with-data-migration","i-lucide-database-backup",{"title":274,"path":275,"stem":276,"children":277,"icon":279},"Reference","\u002Fdocs\u002Freference","1.docs\u002F8.reference\u002F1.index",[278,280,285,290,295,300,305,309],{"title":274,"path":275,"stem":276,"icon":279},"i-lucide-list",{"title":281,"path":282,"stem":283,"icon":284},"Configuration reference","\u002Fdocs\u002Freference\u002Fconfiguration-reference","1.docs\u002F8.reference\u002F2.configuration-reference","i-lucide-table",{"title":286,"path":287,"stem":288,"icon":289},"REST API reference","\u002Fdocs\u002Freference\u002Frest-api-reference","1.docs\u002F8.reference\u002F3.rest-api-reference","i-lucide-network",{"title":291,"path":292,"stem":293,"icon":294},"Gradle plugin reference","\u002Fdocs\u002Freference\u002Fgradle-plugin-reference","1.docs\u002F8.reference\u002F4.gradle-plugin-reference","i-lucide-box",{"title":296,"path":297,"stem":298,"icon":299},"Maven reference","\u002Fdocs\u002Freference\u002Fmaven-reference","1.docs\u002F8.reference\u002F5.maven-reference","i-simple-icons-apachemaven",{"title":301,"path":302,"stem":303,"icon":304},"Kafka Streams compatibility matrix","\u002Fdocs\u002Freference\u002Fks-compatibility-matrix","1.docs\u002F8.reference\u002F6.ks-compatibility-matrix","i-lucide-table-2",{"title":306,"path":307,"stem":308,"icon":170},"Metrics reference","\u002Fdocs\u002Freference\u002Fmetrics-reference","1.docs\u002F8.reference\u002F7.metrics-reference",{"title":310,"path":311,"stem":312,"icon":313},"Glossary","\u002Fdocs\u002Freference\u002Fglossary","1.docs\u002F8.reference\u002F8.glossary","i-lucide-book-a",{"id":315,"title":182,"body":316,"description":2677,"extension":2678,"meta":2679,"navigation":2680,"pageType":2681,"path":178,"seo":2682,"stem":179,"__hash__":2683},"docs\u002F1.docs\u002F5.runtime\u002F1.index.md",{"type":317,"value":318,"toc":2659},"minimark",[319,335,392,399,428,556,564,568,577,602,1302,1315,1320,1330,1636,1640,1651,2154,2196,2220,2224,2251,2253,2265,2276,2279,2288,2342,2345,2359,2363,2387,2391,2405,2409,2426,2523,2536,2540,2543,2585,2594,2598,2655],[320,321,322,326,327,330,331,334],"p",{},[323,324,325],"code",{},"stoatflow-runtime"," is the batteries-included wrapper around the bare ",[323,328,329],{},"stoatflow-core"," engine. You hand it a topology and a YAML config; it loads the config, wires metrics into the engine, starts an HTTP admin server with health and Prometheus endpoints, bridges your license configuration, runs your plugins, and manages the whole lifecycle — including graceful shutdown on ",[323,332,333],{},"SIGTERM",". This is the module most applications depend on.",[336,337,338],"tldr-panel",{},[339,340,341,361,382],"ul",{},[342,343,344,348,349,352,353,356,357,360],"li",{},[345,346,347],"strong",{},"Entry point:"," ",[323,350,351],{},"StoatFlowRuntime.fromConfig(topologyBuilder, configure)"," — loads ",[323,354,355],{},"application.yaml",", builds your topology, returns a runtime ready to ",[323,358,359],{},"start()",".",[342,362,363,348,366,368,369,372,373,376,377,379,380,360],{},[345,364,365],{},"Lifecycle:",[323,367,359],{}," boots everything and returns; ",[323,370,371],{},"awaitTermination()"," blocks the main thread until shutdown; ",[323,374,375],{},"stop()"," shuts down gracefully. A JVM shutdown hook calls ",[323,378,375],{}," on ",[323,381,333],{},[342,383,384,391],{},[345,385,386,387,390],{},"What it adds over ",[323,388,389],{},":core",":"," YAML config loading, an HTTP admin server (health, metrics, topology, debug), Micrometer\u002FPrometheus metrics, license-config bridge, and a plugin + lifecycle-listener system.",[393,394,396,397],"h2",{"id":395},"what-the-runtime-adds-over-core","What the runtime adds over ",[323,398,389],{},[320,400,401,403,404,407,408,410,411,414,415,410,418,421,422,427],{},[323,402,329],{}," is the DSL and the processing engine — you can embed it directly with ",[323,405,406],{},"StoatFlow.fromBuilder(config, builder)"," and drive ",[323,409,359],{}," \u002F ",[323,412,413],{},"close()"," yourself (the KS-shaped ",[323,416,417],{},"close(Duration)",[323,419,420],{},"close(CloseOptions)"," overloads are available too — see the ",[423,424,426],"a",{"href":425},"\u002Fdocs\u002Freference\u002Fks-compatibility-matrix#lifecycle","KS compatibility matrix","). The runtime wraps that engine and adds the production scaffolding you'd otherwise hand-build:",[429,430,431,444],"table",{},[432,433,434],"thead",{},[435,436,437,441],"tr",{},[438,439,440],"th",{},"Capability",[438,442,443],{},"What it does",[445,446,447,475,488,499,510,526,543],"tbody",{},[435,448,449,455],{},[450,451,452],"td",{},[345,453,454],{},"YAML config loading",[450,456,457,458,410,460,463,464,467,468,471,472,360],{},"Reads ",[323,459,355],{},[323,461,462],{},"application.yml"," from the classpath, applies overlay files and ",[323,465,466],{},"STOATFLOW__","-prefixed environment overrides, and maps it all onto the engine's ",[323,469,470],{},"StreamsConfig",". See ",[423,473,474],{"href":163},"Runtime config",[435,476,477,482],{},[450,478,479],{},[345,480,481],{},"HTTP admin server",[450,483,484,485,360],{},"A JDK-built-in HTTP server on a virtual-thread executor, exposing health, metrics, topology, state, and debug endpoints. See ",[423,486,487],{"href":186},"REST API",[435,489,490,494],{},[450,491,492],{},[345,493,195],{},[450,495,496,497,360],{},"Micrometer instrumentation with a Prometheus scrape endpoint and native Kafka-client metrics bound in. See ",[423,498,195],{"href":196},[435,500,501,505],{},[450,502,503],{},[345,504,190],{},[450,506,507,508,360],{},"Liveness and readiness indicators for the engine, the Kafka broker, Schema Registry (auto-enabled when configured), and the license. See ",[423,509,190],{"href":191},[435,511,512,517],{},[450,513,514],{},[345,515,516],{},"License bridge",[450,518,519,520,523,524,360],{},"Translates ",[323,521,522],{},"stoatflow.license.*"," YAML into the system properties the engine reads, before the engine validates the license. See ",[423,525,23],{"href":24},[435,527,528,533],{},[450,529,530],{},[345,531,532],{},"Plugin system",[450,534,535,536,539,540,360],{},"Register ",[323,537,538],{},"RuntimePlugin","s and lifecycle listeners to extend the runtime — custom endpoints, metrics, health indicators, and startup\u002Fshutdown hooks. See ",[423,541,542],{"href":206},"Plugins",[435,544,545,550],{},[450,546,547],{},[345,548,549],{},"Lifecycle management",[450,551,552,553,555],{},"Coordinated startup ordering, a ",[323,554,333],{}," shutdown hook, and a watcher that shuts the runtime down if the engine terminates on its own.",[320,557,558,559,561,562,360],{},"If you only need the DSL and engine with no scaffolding, depend on ",[323,560,329],{}," directly. Everything below assumes ",[323,563,325],{},[393,565,567],{"id":566},"creating-a-runtime-from-yaml","Creating a runtime from YAML",[320,569,570,573,574,576],{},[323,571,572],{},"StoatFlowRuntime.fromConfig(...)"," is the primary entry point. It loads configuration from ",[323,575,355],{}," on the classpath and applies it before building your topology. You pass two things:",[339,578,579,591],{},[342,580,581,586,587,590],{},[345,582,583],{},[323,584,585],{},"topologyBuilder"," — a function that receives a ",[323,588,589],{},"StreamsBuilder"," and defines your topology.",[342,592,593,598,599,360],{},[345,594,595],{},[323,596,597],{},"configure"," — an optional block for everything that can't live in YAML: serdes, exception handlers, and other non-serializable settings, supplied via ",[323,600,601],{},"streamsConfigOverrides { ... }",[603,604,606,906],"code-tabs",{"group":605},"lang",[607,608,614],"pre",{"className":609,"code":610,"filename":611,"language":612,"meta":613,"style":613},"language-kotlin shiki shiki-themes vitesse-light","import io.stoatflow.core.topology.StreamsBuilder\nimport io.stoatflow.runtime.StoatFlowRuntime\nimport org.apache.kafka.common.serialization.Serdes\n\nfun main() {\n    val runtime = StoatFlowRuntime.fromConfig(\n        topologyBuilder = { builder -> buildTopology(builder) },\n        configure = {\n            streamsConfigOverrides {\n                defaultKeySerde(Serdes.String())\n                defaultValueSerde(Serdes.String())\n            }\n        },\n    )\n\n    runtime.start()             \u002F\u002F boots engine + HTTP + metrics, then returns\n    runtime.awaitTermination()  \u002F\u002F block until shutdown\n}\n\nprivate fun buildTopology(builder: StreamsBuilder) {\n    builder.stream\u003CString, String>(\"input\")\n        .mapValues { it.uppercase() }\n        .to(\"output\")\n}\n","Kotlin","kotlin","",[323,615,616,629,637,645,652,665,687,707,718,726,741,753,759,765,771,776,792,806,812,817,838,867,885,901],{"__ignoreMap":613},[617,618,621,625],"span",{"class":619,"line":620},"line",1,[617,622,624],{"class":623},"sbBg2","import",[617,626,628],{"class":627},"sySUi"," io.stoatflow.core.topology.StreamsBuilder\n",[617,630,632,634],{"class":619,"line":631},2,[617,633,624],{"class":623},[617,635,636],{"class":627}," io.stoatflow.runtime.StoatFlowRuntime\n",[617,638,640,642],{"class":619,"line":639},3,[617,641,624],{"class":623},[617,643,644],{"class":627}," org.apache.kafka.common.serialization.Serdes\n",[617,646,648],{"class":619,"line":647},4,[617,649,651],{"emptyLinePlaceholder":650},true,"\n",[617,653,655,658,661],{"class":619,"line":654},5,[617,656,657],{"class":623},"fun",[617,659,660],{"class":627}," main",[617,662,664],{"class":663},"suHK_","() {\n",[617,666,668,671,674,678,681,684],{"class":619,"line":667},6,[617,669,670],{"class":623},"    val",[617,672,673],{"class":663}," runtime ",[617,675,677],{"class":676},"sYZai","=",[617,679,680],{"class":663}," StoatFlowRuntime.",[617,682,683],{"class":627},"fromConfig",[617,685,686],{"class":663},"(\n",[617,688,690,693,695,698,701,704],{"class":619,"line":689},7,[617,691,692],{"class":663},"        topologyBuilder ",[617,694,677],{"class":676},[617,696,697],{"class":663}," { builder ",[617,699,700],{"class":676},"->",[617,702,703],{"class":627}," buildTopology",[617,705,706],{"class":663},"(builder) },\n",[617,708,710,713,715],{"class":619,"line":709},8,[617,711,712],{"class":663},"        configure ",[617,714,677],{"class":676},[617,716,717],{"class":663}," {\n",[617,719,721,724],{"class":619,"line":720},9,[617,722,723],{"class":627},"            streamsConfigOverrides",[617,725,717],{"class":663},[617,727,729,732,735,738],{"class":619,"line":728},10,[617,730,731],{"class":627},"                defaultKeySerde",[617,733,734],{"class":663},"(Serdes.",[617,736,737],{"class":627},"String",[617,739,740],{"class":663},"())\n",[617,742,744,747,749,751],{"class":619,"line":743},11,[617,745,746],{"class":627},"                defaultValueSerde",[617,748,734],{"class":663},[617,750,737],{"class":627},[617,752,740],{"class":663},[617,754,756],{"class":619,"line":755},12,[617,757,758],{"class":663},"            }\n",[617,760,762],{"class":619,"line":761},13,[617,763,764],{"class":663},"        },\n",[617,766,768],{"class":619,"line":767},14,[617,769,770],{"class":663},"    )\n",[617,772,774],{"class":619,"line":773},15,[617,775,651],{"emptyLinePlaceholder":650},[617,777,779,782,785,788],{"class":619,"line":778},16,[617,780,781],{"class":663},"    runtime.",[617,783,784],{"class":627},"start",[617,786,787],{"class":663},"()             ",[617,789,791],{"class":790},"s8zF2","\u002F\u002F boots engine + HTTP + metrics, then returns\n",[617,793,795,797,800,803],{"class":619,"line":794},17,[617,796,781],{"class":663},[617,798,799],{"class":627},"awaitTermination",[617,801,802],{"class":663},"()  ",[617,804,805],{"class":790},"\u002F\u002F block until shutdown\n",[617,807,809],{"class":619,"line":808},18,[617,810,811],{"class":663},"}\n",[617,813,815],{"class":619,"line":814},19,[617,816,651],{"emptyLinePlaceholder":650},[617,818,820,824,827,829,832,835],{"class":619,"line":819},20,[617,821,823],{"class":822},"si04Y","private",[617,825,826],{"class":623}," fun",[617,828,703],{"class":627},[617,830,831],{"class":663},"(builder: ",[617,833,589],{"class":834},"sUxyF",[617,836,837],{"class":663},") {\n",[617,839,841,844,847,850,852,855,857,860,864],{"class":619,"line":840},21,[617,842,843],{"class":663},"    builder.",[617,845,846],{"class":627},"stream",[617,848,849],{"class":663},"\u003C",[617,851,737],{"class":834},[617,853,854],{"class":663},", ",[617,856,737],{"class":834},[617,858,859],{"class":663},">(",[617,861,863],{"class":862},"spphp","\"input\"",[617,865,866],{"class":663},")\n",[617,868,870,873,876,879,882],{"class":619,"line":869},22,[617,871,872],{"class":663},"        .",[617,874,875],{"class":627},"mapValues",[617,877,878],{"class":663}," { it.",[617,880,881],{"class":627},"uppercase",[617,883,884],{"class":663},"() }\n",[617,886,888,890,893,896,899],{"class":619,"line":887},23,[617,889,872],{"class":663},[617,891,892],{"class":627},"to",[617,894,895],{"class":663},"(",[617,897,898],{"class":862},"\"output\"",[617,900,866],{"class":663},[617,902,904],{"class":619,"line":903},24,[617,905,811],{"class":663},[607,907,912],{"className":908,"code":909,"filename":910,"language":911,"meta":613,"style":613},"language-java shiki shiki-themes vitesse-light","import io.stoatflow.core.topology.StreamsBuilder;\nimport io.stoatflow.runtime.StoatFlowRuntime;\nimport org.apache.kafka.common.serialization.Serdes;\n\npublic class Main {\n    public static void main(String[] args) {\n        var runtime = StoatFlowRuntime.fromConfig(\n            Main::buildTopology,\n            builder -> builder.streamsConfigOverrides(cfg -> {\n                cfg.defaultKeySerde(Serdes.String());\n                cfg.defaultValueSerde(Serdes.String());\n            })\n        );\n\n        runtime.start();             \u002F\u002F boots engine + HTTP + metrics, then returns\n        runtime.awaitTermination();  \u002F\u002F block until shutdown\n    }\n\n    private static void buildTopology(StreamsBuilder builder) {\n        builder.\u003CString, String>stream(\"input\")\n            .mapValues(v -> v.toUpperCase())\n            .to(\"output\");\n    }\n}\n","Java","java",[323,913,914,943,965,999,1003,1016,1045,1065,1079,1103,1124,1143,1148,1153,1157,1172,1185,1190,1194,1217,1252,1276,1294,1298],{"__ignoreMap":613},[617,915,916,918,921,923,926,928,931,933,936,938,940],{"class":619,"line":620},[617,917,624],{"class":623},[617,919,920],{"class":663}," io",[617,922,360],{"class":676},[617,924,925],{"class":663},"stoatflow",[617,927,360],{"class":676},[617,929,930],{"class":663},"core",[617,932,360],{"class":676},[617,934,935],{"class":663},"topology",[617,937,360],{"class":676},[617,939,589],{"class":663},[617,941,942],{"class":676},";\n",[617,944,945,947,949,951,953,955,958,960,963],{"class":619,"line":631},[617,946,624],{"class":623},[617,948,920],{"class":663},[617,950,360],{"class":676},[617,952,925],{"class":663},[617,954,360],{"class":676},[617,956,957],{"class":663},"runtime",[617,959,360],{"class":676},[617,961,962],{"class":663},"StoatFlowRuntime",[617,964,942],{"class":676},[617,966,967,969,972,974,977,979,982,984,987,989,992,994,997],{"class":619,"line":639},[617,968,624],{"class":623},[617,970,971],{"class":663}," org",[617,973,360],{"class":676},[617,975,976],{"class":663},"apache",[617,978,360],{"class":676},[617,980,981],{"class":663},"kafka",[617,983,360],{"class":676},[617,985,986],{"class":663},"common",[617,988,360],{"class":676},[617,990,991],{"class":663},"serialization",[617,993,360],{"class":676},[617,995,996],{"class":663},"Serdes",[617,998,942],{"class":676},[617,1000,1001],{"class":619,"line":647},[617,1002,651],{"emptyLinePlaceholder":650},[617,1004,1005,1008,1011,1014],{"class":619,"line":654},[617,1006,1007],{"class":822},"public",[617,1009,1010],{"class":822}," class",[617,1012,1013],{"class":834}," Main",[617,1015,717],{"class":676},[617,1017,1018,1021,1024,1027,1029,1031,1033,1036,1040,1043],{"class":619,"line":667},[617,1019,1020],{"class":822},"    public",[617,1022,1023],{"class":822}," static",[617,1025,1026],{"class":822}," void",[617,1028,660],{"class":627},[617,1030,895],{"class":676},[617,1032,737],{"class":822},[617,1034,1035],{"class":676},"[]",[617,1037,1039],{"class":1038},"svycV"," args",[617,1041,1042],{"class":676},")",[617,1044,717],{"class":676},[617,1046,1047,1050,1053,1056,1059,1061,1063],{"class":619,"line":689},[617,1048,1049],{"class":822},"        var",[617,1051,1052],{"class":1038}," runtime",[617,1054,1055],{"class":676}," =",[617,1057,1058],{"class":1038}," StoatFlowRuntime",[617,1060,360],{"class":676},[617,1062,683],{"class":627},[617,1064,686],{"class":676},[617,1066,1067,1070,1073,1076],{"class":619,"line":709},[617,1068,1069],{"class":663},"            Main",[617,1071,1072],{"class":623},"::",[617,1074,1075],{"class":663},"buildTopology",[617,1077,1078],{"class":676},",\n",[617,1080,1081,1084,1086,1089,1091,1094,1096,1099,1101],{"class":619,"line":720},[617,1082,1083],{"class":663},"            builder ",[617,1085,700],{"class":676},[617,1087,1088],{"class":1038}," builder",[617,1090,360],{"class":676},[617,1092,1093],{"class":627},"streamsConfigOverrides",[617,1095,895],{"class":676},[617,1097,1098],{"class":663},"cfg ",[617,1100,700],{"class":676},[617,1102,717],{"class":676},[617,1104,1105,1108,1110,1113,1115,1117,1119,1121],{"class":619,"line":728},[617,1106,1107],{"class":1038},"                cfg",[617,1109,360],{"class":676},[617,1111,1112],{"class":627},"defaultKeySerde",[617,1114,895],{"class":676},[617,1116,996],{"class":1038},[617,1118,360],{"class":676},[617,1120,737],{"class":627},[617,1122,1123],{"class":676},"());\n",[617,1125,1126,1128,1130,1133,1135,1137,1139,1141],{"class":619,"line":743},[617,1127,1107],{"class":1038},[617,1129,360],{"class":676},[617,1131,1132],{"class":627},"defaultValueSerde",[617,1134,895],{"class":676},[617,1136,996],{"class":1038},[617,1138,360],{"class":676},[617,1140,737],{"class":627},[617,1142,1123],{"class":676},[617,1144,1145],{"class":619,"line":755},[617,1146,1147],{"class":676},"            })\n",[617,1149,1150],{"class":619,"line":761},[617,1151,1152],{"class":676},"        );\n",[617,1154,1155],{"class":619,"line":767},[617,1156,651],{"emptyLinePlaceholder":650},[617,1158,1159,1162,1164,1166,1169],{"class":619,"line":773},[617,1160,1161],{"class":1038},"        runtime",[617,1163,360],{"class":676},[617,1165,784],{"class":627},[617,1167,1168],{"class":676},"();",[617,1170,1171],{"class":790},"             \u002F\u002F boots engine + HTTP + metrics, then returns\n",[617,1173,1174,1176,1178,1180,1182],{"class":619,"line":778},[617,1175,1161],{"class":1038},[617,1177,360],{"class":676},[617,1179,799],{"class":627},[617,1181,1168],{"class":676},[617,1183,1184],{"class":790},"  \u002F\u002F block until shutdown\n",[617,1186,1187],{"class":619,"line":794},[617,1188,1189],{"class":676},"    }\n",[617,1191,1192],{"class":619,"line":808},[617,1193,651],{"emptyLinePlaceholder":650},[617,1195,1196,1199,1201,1203,1205,1207,1210,1213,1215],{"class":619,"line":814},[617,1197,1198],{"class":822},"    private",[617,1200,1023],{"class":822},[617,1202,1026],{"class":822},[617,1204,703],{"class":627},[617,1206,895],{"class":676},[617,1208,1209],{"class":663},"StreamsBuilder ",[617,1211,1212],{"class":1038},"builder",[617,1214,1042],{"class":676},[617,1216,717],{"class":676},[617,1218,1219,1222,1224,1226,1228,1231,1234,1237,1239,1241,1245,1248,1250],{"class":619,"line":819},[617,1220,1221],{"class":663},"        builder",[617,1223,360],{"class":676},[617,1225,849],{"class":822},[617,1227,737],{"class":663},[617,1229,1230],{"class":676},",",[617,1232,1233],{"class":663}," String",[617,1235,1236],{"class":822},">",[617,1238,846],{"class":627},[617,1240,895],{"class":676},[617,1242,1244],{"class":1243},"sSP4y","\"",[617,1246,1247],{"class":862},"input",[617,1249,1244],{"class":1243},[617,1251,866],{"class":676},[617,1253,1254,1257,1259,1261,1264,1266,1269,1271,1274],{"class":619,"line":840},[617,1255,1256],{"class":676},"            .",[617,1258,875],{"class":627},[617,1260,895],{"class":676},[617,1262,1263],{"class":663},"v ",[617,1265,700],{"class":676},[617,1267,1268],{"class":1038}," v",[617,1270,360],{"class":676},[617,1272,1273],{"class":627},"toUpperCase",[617,1275,740],{"class":676},[617,1277,1278,1280,1282,1284,1286,1289,1291],{"class":619,"line":869},[617,1279,1256],{"class":676},[617,1281,892],{"class":627},[617,1283,895],{"class":676},[617,1285,1244],{"class":1243},[617,1287,1288],{"class":862},"output",[617,1290,1244],{"class":1243},[617,1292,1293],{"class":676},");\n",[617,1295,1296],{"class":619,"line":887},[617,1297,1189],{"class":676},[617,1299,1300],{"class":619,"line":903},[617,1301,811],{"class":676},[320,1303,1304,1305,410,1308,1311,1312,360],{},"The Java overloads accept ",[323,1306,1307],{},"Consumer\u003CStreamsBuilder>",[323,1309,1310],{},"Consumer\u003CStoatFlowRuntime.Builder>"," so void-returning lambdas work without the awkward ",[323,1313,1314],{},"return Unit.INSTANCE",[1316,1317,1319],"h3",{"id":1318},"supplying-a-pre-loaded-config","Supplying a pre-loaded config",[320,1321,1322,1323,1325,1326,1329],{},"There's a second ",[323,1324,683],{}," overload that takes an already-loaded ",[323,1327,1328],{},"ApplicationConfig",". Use it when you need to load configuration from a custom source, or to inspect or modify it before the runtime is created:",[603,1331,1332,1467],{"group":605},[607,1333,1335],{"className":609,"code":1334,"filename":611,"language":612,"meta":613,"style":613},"import io.stoatflow.runtime.config.ConfigLoader\n\nval appConfig = ConfigLoader.loadOrThrow()\n\u002F\u002F inspect or adjust appConfig here\n\nval runtime = StoatFlowRuntime.fromConfig(\n    appConfig = appConfig,\n    topologyBuilder = { builder -> buildTopology(builder) },\n    configure = {\n        streamsConfigOverrides {\n            defaultKeySerde(Serdes.String())\n            defaultValueSerde(Serdes.String())\n        }\n    },\n)\n",[323,1336,1337,1344,1348,1367,1372,1376,1390,1400,1415,1424,1431,1442,1453,1458,1463],{"__ignoreMap":613},[617,1338,1339,1341],{"class":619,"line":620},[617,1340,624],{"class":623},[617,1342,1343],{"class":627}," io.stoatflow.runtime.config.ConfigLoader\n",[617,1345,1346],{"class":619,"line":631},[617,1347,651],{"emptyLinePlaceholder":650},[617,1349,1350,1353,1356,1358,1361,1364],{"class":619,"line":639},[617,1351,1352],{"class":623},"val",[617,1354,1355],{"class":663}," appConfig ",[617,1357,677],{"class":676},[617,1359,1360],{"class":663}," ConfigLoader.",[617,1362,1363],{"class":627},"loadOrThrow",[617,1365,1366],{"class":663},"()\n",[617,1368,1369],{"class":619,"line":647},[617,1370,1371],{"class":790},"\u002F\u002F inspect or adjust appConfig here\n",[617,1373,1374],{"class":619,"line":654},[617,1375,651],{"emptyLinePlaceholder":650},[617,1377,1378,1380,1382,1384,1386,1388],{"class":619,"line":667},[617,1379,1352],{"class":623},[617,1381,673],{"class":663},[617,1383,677],{"class":676},[617,1385,680],{"class":663},[617,1387,683],{"class":627},[617,1389,686],{"class":663},[617,1391,1392,1395,1397],{"class":619,"line":689},[617,1393,1394],{"class":663},"    appConfig ",[617,1396,677],{"class":676},[617,1398,1399],{"class":663}," appConfig,\n",[617,1401,1402,1405,1407,1409,1411,1413],{"class":619,"line":709},[617,1403,1404],{"class":663},"    topologyBuilder ",[617,1406,677],{"class":676},[617,1408,697],{"class":663},[617,1410,700],{"class":676},[617,1412,703],{"class":627},[617,1414,706],{"class":663},[617,1416,1417,1420,1422],{"class":619,"line":720},[617,1418,1419],{"class":663},"    configure ",[617,1421,677],{"class":676},[617,1423,717],{"class":663},[617,1425,1426,1429],{"class":619,"line":728},[617,1427,1428],{"class":627},"        streamsConfigOverrides",[617,1430,717],{"class":663},[617,1432,1433,1436,1438,1440],{"class":619,"line":743},[617,1434,1435],{"class":627},"            defaultKeySerde",[617,1437,734],{"class":663},[617,1439,737],{"class":627},[617,1441,740],{"class":663},[617,1443,1444,1447,1449,1451],{"class":619,"line":755},[617,1445,1446],{"class":627},"            defaultValueSerde",[617,1448,734],{"class":663},[617,1450,737],{"class":627},[617,1452,740],{"class":663},[617,1454,1455],{"class":619,"line":761},[617,1456,1457],{"class":663},"        }\n",[617,1459,1460],{"class":619,"line":767},[617,1461,1462],{"class":663},"    },\n",[617,1464,1465],{"class":619,"line":773},[617,1466,866],{"class":663},[607,1468,1470],{"className":908,"code":1469,"filename":910,"language":911,"meta":613,"style":613},"import io.stoatflow.runtime.config.ConfigLoader;\n\nvar appConfig = ConfigLoader.INSTANCE.loadOrThrow();\n\u002F\u002F inspect or adjust appConfig here\n\nvar runtime = StoatFlowRuntime.fromConfig(\n    appConfig,\n    Main::buildTopology,\n    builder -> builder.streamsConfigOverrides(cfg -> {\n        cfg.defaultKeySerde(Serdes.String());\n        cfg.defaultValueSerde(Serdes.String());\n    })\n);\n",[323,1471,1472,1498,1502,1527,1531,1535,1551,1558,1569,1590,1609,1627,1632],{"__ignoreMap":613},[617,1473,1474,1476,1478,1480,1482,1484,1486,1488,1491,1493,1496],{"class":619,"line":620},[617,1475,624],{"class":623},[617,1477,920],{"class":663},[617,1479,360],{"class":676},[617,1481,925],{"class":663},[617,1483,360],{"class":676},[617,1485,957],{"class":663},[617,1487,360],{"class":676},[617,1489,1490],{"class":663},"config",[617,1492,360],{"class":676},[617,1494,1495],{"class":663},"ConfigLoader",[617,1497,942],{"class":676},[617,1499,1500],{"class":619,"line":631},[617,1501,651],{"emptyLinePlaceholder":650},[617,1503,1504,1507,1510,1512,1515,1517,1520,1522,1524],{"class":619,"line":639},[617,1505,1506],{"class":822},"var",[617,1508,1509],{"class":1038}," appConfig",[617,1511,1055],{"class":676},[617,1513,1514],{"class":1038}," ConfigLoader",[617,1516,360],{"class":676},[617,1518,1519],{"class":1038},"INSTANCE",[617,1521,360],{"class":676},[617,1523,1363],{"class":627},[617,1525,1526],{"class":676},"();\n",[617,1528,1529],{"class":619,"line":647},[617,1530,1371],{"class":790},[617,1532,1533],{"class":619,"line":654},[617,1534,651],{"emptyLinePlaceholder":650},[617,1536,1537,1539,1541,1543,1545,1547,1549],{"class":619,"line":667},[617,1538,1506],{"class":822},[617,1540,1052],{"class":1038},[617,1542,1055],{"class":676},[617,1544,1058],{"class":1038},[617,1546,360],{"class":676},[617,1548,683],{"class":627},[617,1550,686],{"class":676},[617,1552,1553,1556],{"class":619,"line":689},[617,1554,1555],{"class":663},"    appConfig",[617,1557,1078],{"class":676},[617,1559,1560,1563,1565,1567],{"class":619,"line":709},[617,1561,1562],{"class":663},"    Main",[617,1564,1072],{"class":623},[617,1566,1075],{"class":663},[617,1568,1078],{"class":676},[617,1570,1571,1574,1576,1578,1580,1582,1584,1586,1588],{"class":619,"line":720},[617,1572,1573],{"class":663},"    builder ",[617,1575,700],{"class":676},[617,1577,1088],{"class":1038},[617,1579,360],{"class":676},[617,1581,1093],{"class":627},[617,1583,895],{"class":676},[617,1585,1098],{"class":663},[617,1587,700],{"class":676},[617,1589,717],{"class":676},[617,1591,1592,1595,1597,1599,1601,1603,1605,1607],{"class":619,"line":728},[617,1593,1594],{"class":1038},"        cfg",[617,1596,360],{"class":676},[617,1598,1112],{"class":627},[617,1600,895],{"class":676},[617,1602,996],{"class":1038},[617,1604,360],{"class":676},[617,1606,737],{"class":627},[617,1608,1123],{"class":676},[617,1610,1611,1613,1615,1617,1619,1621,1623,1625],{"class":619,"line":743},[617,1612,1594],{"class":1038},[617,1614,360],{"class":676},[617,1616,1132],{"class":627},[617,1618,895],{"class":676},[617,1620,996],{"class":1038},[617,1622,360],{"class":676},[617,1624,737],{"class":627},[617,1626,1123],{"class":676},[617,1628,1629],{"class":619,"line":755},[617,1630,1631],{"class":676},"    })\n",[617,1633,1634],{"class":619,"line":761},[617,1635,1293],{"class":676},[393,1637,1639],{"id":1638},"creating-a-runtime-with-the-builder","Creating a runtime with the builder",[320,1641,1642,1644,1645,1647,1648,1650],{},[323,1643,683],{}," is the recommended path because it pulls everything from YAML. If you'd rather configure the runtime entirely in code — no ",[323,1646,355],{}," — use the builder. You're then responsible for constructing the engine's ",[323,1649,470],{}," yourself, and for any HTTP \u002F metrics config you want to override from defaults.",[603,1652,1653,1860],{"group":605},[607,1654,1656],{"className":609,"code":1655,"filename":611,"language":612,"meta":613,"style":613},"import io.stoatflow.core.config.StreamsConfig\nimport io.stoatflow.runtime.StoatFlowRuntime\nimport io.stoatflow.runtime.http.HttpServerConfig\n\nval runtime = StoatFlowRuntime.builder()\n    .streamsConfig(\n        StreamsConfig(\n            applicationId = \"my-app\",\n            bootstrapServers = \"localhost:9092\",\n        ),\n    )\n    .httpConfig(HttpServerConfig(port = 8080))\n    .topology { builder ->\n        builder.stream\u003CString, String>(\"input\")\n            .mapValues { it.uppercase() }\n            .to(\"output\")\n    }\n    .build()\n\nruntime.start()\nruntime.awaitTermination()\n",[323,1657,1658,1665,1671,1678,1682,1696,1706,1713,1725,1737,1742,1746,1770,1781,1802,1814,1826,1830,1839,1843,1852],{"__ignoreMap":613},[617,1659,1660,1662],{"class":619,"line":620},[617,1661,624],{"class":623},[617,1663,1664],{"class":627}," io.stoatflow.core.config.StreamsConfig\n",[617,1666,1667,1669],{"class":619,"line":631},[617,1668,624],{"class":623},[617,1670,636],{"class":627},[617,1672,1673,1675],{"class":619,"line":639},[617,1674,624],{"class":623},[617,1676,1677],{"class":627}," io.stoatflow.runtime.http.HttpServerConfig\n",[617,1679,1680],{"class":619,"line":647},[617,1681,651],{"emptyLinePlaceholder":650},[617,1683,1684,1686,1688,1690,1692,1694],{"class":619,"line":654},[617,1685,1352],{"class":623},[617,1687,673],{"class":663},[617,1689,677],{"class":676},[617,1691,680],{"class":663},[617,1693,1212],{"class":627},[617,1695,1366],{"class":663},[617,1697,1698,1701,1704],{"class":619,"line":667},[617,1699,1700],{"class":663},"    .",[617,1702,1703],{"class":627},"streamsConfig",[617,1705,686],{"class":663},[617,1707,1708,1711],{"class":619,"line":689},[617,1709,1710],{"class":627},"        StreamsConfig",[617,1712,686],{"class":663},[617,1714,1715,1718,1720,1723],{"class":619,"line":709},[617,1716,1717],{"class":663},"            applicationId ",[617,1719,677],{"class":676},[617,1721,1722],{"class":862}," \"my-app\"",[617,1724,1078],{"class":663},[617,1726,1727,1730,1732,1735],{"class":619,"line":720},[617,1728,1729],{"class":663},"            bootstrapServers ",[617,1731,677],{"class":676},[617,1733,1734],{"class":862}," \"localhost:9092\"",[617,1736,1078],{"class":663},[617,1738,1739],{"class":619,"line":728},[617,1740,1741],{"class":663},"        ),\n",[617,1743,1744],{"class":619,"line":743},[617,1745,770],{"class":663},[617,1747,1748,1750,1753,1755,1758,1761,1763,1767],{"class":619,"line":755},[617,1749,1700],{"class":663},[617,1751,1752],{"class":627},"httpConfig",[617,1754,895],{"class":663},[617,1756,1757],{"class":627},"HttpServerConfig",[617,1759,1760],{"class":663},"(port ",[617,1762,677],{"class":676},[617,1764,1766],{"class":1765},"s-TwI"," 8080",[617,1768,1769],{"class":663},"))\n",[617,1771,1772,1774,1776,1778],{"class":619,"line":761},[617,1773,1700],{"class":663},[617,1775,935],{"class":627},[617,1777,697],{"class":663},[617,1779,1780],{"class":676},"->\n",[617,1782,1783,1786,1788,1790,1792,1794,1796,1798,1800],{"class":619,"line":767},[617,1784,1785],{"class":663},"        builder.",[617,1787,846],{"class":627},[617,1789,849],{"class":663},[617,1791,737],{"class":834},[617,1793,854],{"class":663},[617,1795,737],{"class":834},[617,1797,859],{"class":663},[617,1799,863],{"class":862},[617,1801,866],{"class":663},[617,1803,1804,1806,1808,1810,1812],{"class":619,"line":773},[617,1805,1256],{"class":663},[617,1807,875],{"class":627},[617,1809,878],{"class":663},[617,1811,881],{"class":627},[617,1813,884],{"class":663},[617,1815,1816,1818,1820,1822,1824],{"class":619,"line":778},[617,1817,1256],{"class":663},[617,1819,892],{"class":627},[617,1821,895],{"class":663},[617,1823,898],{"class":862},[617,1825,866],{"class":663},[617,1827,1828],{"class":619,"line":794},[617,1829,1189],{"class":663},[617,1831,1832,1834,1837],{"class":619,"line":808},[617,1833,1700],{"class":663},[617,1835,1836],{"class":627},"build",[617,1838,1366],{"class":663},[617,1840,1841],{"class":619,"line":814},[617,1842,651],{"emptyLinePlaceholder":650},[617,1844,1845,1848,1850],{"class":619,"line":819},[617,1846,1847],{"class":663},"runtime.",[617,1849,784],{"class":627},[617,1851,1366],{"class":663},[617,1853,1854,1856,1858],{"class":619,"line":840},[617,1855,1847],{"class":663},[617,1857,799],{"class":627},[617,1859,1366],{"class":663},[607,1861,1863],{"className":908,"code":1862,"filename":910,"language":911,"meta":613,"style":613},"import io.stoatflow.core.config.StreamsConfig;\nimport io.stoatflow.runtime.StoatFlowRuntime;\nimport io.stoatflow.runtime.http.HttpServerConfig;\n\nvar runtime = StoatFlowRuntime.Companion.builder()\n    .streamsConfig(\n        StreamsConfig.builder(\"my-app\", \"localhost:9092\").build())\n    .httpConfig(new HttpServerConfig(8080, \"0.0.0.0\", 50, true, true))\n    .topology(builder ->\n        builder.\u003CString, String>stream(\"input\")\n            .mapValues(v -> v.toUpperCase())\n            .to(\"output\"))\n    .build();\n\nruntime.start();\nruntime.awaitTermination();\n",[323,1864,1865,1889,1909,1934,1938,1959,1967,2001,2045,2058,2086,2106,2122,2130,2134,2144],{"__ignoreMap":613},[617,1866,1867,1869,1871,1873,1875,1877,1879,1881,1883,1885,1887],{"class":619,"line":620},[617,1868,624],{"class":623},[617,1870,920],{"class":663},[617,1872,360],{"class":676},[617,1874,925],{"class":663},[617,1876,360],{"class":676},[617,1878,930],{"class":663},[617,1880,360],{"class":676},[617,1882,1490],{"class":663},[617,1884,360],{"class":676},[617,1886,470],{"class":663},[617,1888,942],{"class":676},[617,1890,1891,1893,1895,1897,1899,1901,1903,1905,1907],{"class":619,"line":631},[617,1892,624],{"class":623},[617,1894,920],{"class":663},[617,1896,360],{"class":676},[617,1898,925],{"class":663},[617,1900,360],{"class":676},[617,1902,957],{"class":663},[617,1904,360],{"class":676},[617,1906,962],{"class":663},[617,1908,942],{"class":676},[617,1910,1911,1913,1915,1917,1919,1921,1923,1925,1928,1930,1932],{"class":619,"line":639},[617,1912,624],{"class":623},[617,1914,920],{"class":663},[617,1916,360],{"class":676},[617,1918,925],{"class":663},[617,1920,360],{"class":676},[617,1922,957],{"class":663},[617,1924,360],{"class":676},[617,1926,1927],{"class":663},"http",[617,1929,360],{"class":676},[617,1931,1757],{"class":663},[617,1933,942],{"class":676},[617,1935,1936],{"class":619,"line":647},[617,1937,651],{"emptyLinePlaceholder":650},[617,1939,1940,1942,1944,1946,1948,1950,1953,1955,1957],{"class":619,"line":654},[617,1941,1506],{"class":822},[617,1943,1052],{"class":1038},[617,1945,1055],{"class":676},[617,1947,1058],{"class":1038},[617,1949,360],{"class":676},[617,1951,1952],{"class":1038},"Companion",[617,1954,360],{"class":676},[617,1956,1212],{"class":627},[617,1958,1366],{"class":676},[617,1960,1961,1963,1965],{"class":619,"line":667},[617,1962,1700],{"class":676},[617,1964,1703],{"class":627},[617,1966,686],{"class":676},[617,1968,1969,1971,1973,1975,1977,1979,1982,1984,1986,1989,1992,1994,1997,1999],{"class":619,"line":689},[617,1970,1710],{"class":1038},[617,1972,360],{"class":676},[617,1974,1212],{"class":627},[617,1976,895],{"class":676},[617,1978,1244],{"class":1243},[617,1980,1981],{"class":862},"my-app",[617,1983,1244],{"class":1243},[617,1985,1230],{"class":676},[617,1987,1988],{"class":1243}," \"",[617,1990,1991],{"class":862},"localhost:9092",[617,1993,1244],{"class":1243},[617,1995,1996],{"class":676},").",[617,1998,1836],{"class":627},[617,2000,740],{"class":676},[617,2002,2003,2005,2007,2009,2012,2015,2017,2020,2022,2024,2027,2029,2031,2034,2036,2039,2041,2043],{"class":619,"line":709},[617,2004,1700],{"class":676},[617,2006,1752],{"class":627},[617,2008,895],{"class":676},[617,2010,2011],{"class":623},"new",[617,2013,2014],{"class":627}," HttpServerConfig",[617,2016,895],{"class":676},[617,2018,2019],{"class":1765},"8080",[617,2021,1230],{"class":676},[617,2023,1988],{"class":1243},[617,2025,2026],{"class":862},"0.0.0.0",[617,2028,1244],{"class":1243},[617,2030,1230],{"class":676},[617,2032,2033],{"class":1765}," 50",[617,2035,1230],{"class":676},[617,2037,2038],{"class":623}," true",[617,2040,1230],{"class":676},[617,2042,2038],{"class":623},[617,2044,1769],{"class":676},[617,2046,2047,2049,2051,2053,2056],{"class":619,"line":720},[617,2048,1700],{"class":676},[617,2050,935],{"class":627},[617,2052,895],{"class":676},[617,2054,2055],{"class":663},"builder ",[617,2057,1780],{"class":676},[617,2059,2060,2062,2064,2066,2068,2070,2072,2074,2076,2078,2080,2082,2084],{"class":619,"line":728},[617,2061,1221],{"class":663},[617,2063,360],{"class":676},[617,2065,849],{"class":822},[617,2067,737],{"class":663},[617,2069,1230],{"class":676},[617,2071,1233],{"class":663},[617,2073,1236],{"class":822},[617,2075,846],{"class":627},[617,2077,895],{"class":676},[617,2079,1244],{"class":1243},[617,2081,1247],{"class":862},[617,2083,1244],{"class":1243},[617,2085,866],{"class":676},[617,2087,2088,2090,2092,2094,2096,2098,2100,2102,2104],{"class":619,"line":743},[617,2089,1256],{"class":676},[617,2091,875],{"class":627},[617,2093,895],{"class":676},[617,2095,1263],{"class":663},[617,2097,700],{"class":676},[617,2099,1268],{"class":1038},[617,2101,360],{"class":676},[617,2103,1273],{"class":627},[617,2105,740],{"class":676},[617,2107,2108,2110,2112,2114,2116,2118,2120],{"class":619,"line":755},[617,2109,1256],{"class":676},[617,2111,892],{"class":627},[617,2113,895],{"class":676},[617,2115,1244],{"class":1243},[617,2117,1288],{"class":862},[617,2119,1244],{"class":1243},[617,2121,1769],{"class":676},[617,2123,2124,2126,2128],{"class":619,"line":761},[617,2125,1700],{"class":676},[617,2127,1836],{"class":627},[617,2129,1526],{"class":676},[617,2131,2132],{"class":619,"line":767},[617,2133,651],{"emptyLinePlaceholder":650},[617,2135,2136,2138,2140,2142],{"class":619,"line":773},[617,2137,957],{"class":1038},[617,2139,360],{"class":676},[617,2141,784],{"class":627},[617,2143,1526],{"class":676},[617,2145,2146,2148,2150,2152],{"class":619,"line":778},[617,2147,957],{"class":1038},[617,2149,360],{"class":676},[617,2151,799],{"class":627},[617,2153,1526],{"class":676},[320,2155,2156,2157,2160,2161,2163,2164,854,2166,854,2169,854,2172,2175,2176,854,2179,2182,2183,2186,2187,2189,2190,2192,2193,2195],{},"Metrics aren't configured here — when you omit ",[323,2158,2159],{},"metricsConfig(...)",", the builder enables metrics by default and derives the application ID from the ",[323,2162,470],{},". The builder also exposes ",[323,2165,2159],{},[323,2167,2168],{},"addPlugin(...)",[323,2170,2171],{},"addLifecycleListener(...)",[323,2173,2174],{},"addHealthIndicator(name, indicator)",", and config setters for ",[323,2177,2178],{},"infoConfig",[323,2180,2181],{},"configConfig",", and ",[323,2184,2185],{},"healthConfig",". The ",[323,2188,601],{}," block is only used with ",[323,2191,683],{}," — when you pass a ",[323,2194,470],{}," directly, set everything on that object instead.",[2197,2198,2201],"callout",{"color":2199,"icon":2200},"info","i-lucide-lightbulb",[320,2202,2203,2205,2206,2208,2209,2211,2212,2214,2215,2217,2218,360],{},[323,2204,683],{}," and the builder produce the same ",[323,2207,962],{},". The difference is where configuration comes from: ",[323,2210,683],{}," reads YAML and lets ",[323,2213,1093],{}," supply the non-serializable bits; the builder takes a fully-formed ",[323,2216,470],{}," in code. Most applications use ",[323,2219,683],{},[393,2221,2223],{"id":2222},"lifecycle","Lifecycle",[320,2225,2226,2227,2230,2231,2230,2234,2230,2237,2230,2240,2243,2244,2247,2248,360],{},"The runtime moves through a small set of states — ",[323,2228,2229],{},"CREATED"," → ",[323,2232,2233],{},"STARTING",[323,2235,2236],{},"RUNNING",[323,2238,2239],{},"STOPPING",[323,2241,2242],{},"STOPPED"," (or ",[323,2245,2246],{},"ERROR",") — and exposes three lifecycle methods. Query the current state any time with ",[323,2249,2250],{},"state()",[1316,2252,359],{"id":784},[320,2254,2255,2257,2258,2261,2262,2264],{},[323,2256,359],{}," boots the runtime and ",[345,2259,2260],{},"returns"," (it does not block). Internally it initialises metrics, builds and starts the engine in parallel with HTTP-server setup, starts your plugins, registers the JVM shutdown hook, and transitions to ",[323,2263,2236],{},". Health endpoints come up early — while the engine is still restoring state — so orchestrator probes get answers during a slow cold start.",[320,2266,2267,2269,2270,2272,2273,2275],{},[323,2268,359],{}," can only be called from the ",[323,2271,2229],{}," state. If engine startup fails, the runtime cleans up everything it had brought up, transitions to ",[323,2274,2246],{},", and rethrows.",[1316,2277,371],{"id":2278},"awaittermination",[320,2280,2281,2283,2284,2287],{},[323,2282,371],{}," blocks the calling thread until the runtime stops. This is what keeps ",[323,2285,2286],{},"main"," alive while the engine processes records. If the runtime terminated because of an error, this method rethrows that error — so a non-zero exit on failure falls out naturally:",[603,2289,2290,2314],{"group":605},[607,2291,2293],{"className":609,"code":2292,"filename":611,"language":612,"meta":613,"style":613},"runtime.start()\nruntime.awaitTermination()  \u002F\u002F returns on clean stop; throws on error\n",[323,2294,2295,2303],{"__ignoreMap":613},[617,2296,2297,2299,2301],{"class":619,"line":620},[617,2298,1847],{"class":663},[617,2300,784],{"class":627},[617,2302,1366],{"class":663},[617,2304,2305,2307,2309,2311],{"class":619,"line":631},[617,2306,1847],{"class":663},[617,2308,799],{"class":627},[617,2310,802],{"class":663},[617,2312,2313],{"class":790},"\u002F\u002F returns on clean stop; throws on error\n",[607,2315,2317],{"className":908,"code":2316,"filename":910,"language":911,"meta":613,"style":613},"runtime.start();\nruntime.awaitTermination();  \u002F\u002F returns on clean stop; throws on error\n",[323,2318,2319,2329],{"__ignoreMap":613},[617,2320,2321,2323,2325,2327],{"class":619,"line":620},[617,2322,957],{"class":1038},[617,2324,360],{"class":676},[617,2326,784],{"class":627},[617,2328,1526],{"class":676},[617,2330,2331,2333,2335,2337,2339],{"class":619,"line":631},[617,2332,957],{"class":1038},[617,2334,360],{"class":676},[617,2336,799],{"class":627},[617,2338,1168],{"class":676},[617,2340,2341],{"class":790},"  \u002F\u002F returns on clean stop; throws on error\n",[1316,2343,375],{"id":2344},"stop",[320,2346,2347,2349,2350,2352,2353,2355,2356,2358],{},[323,2348,375],{}," shuts the runtime down gracefully: it closes the engine (which drains in-flight records and commits a final barrier), shuts plugins down in reverse registration order, stops the HTTP server, closes the metrics registry, and transitions to ",[323,2351,2242],{},". You rarely call ",[323,2354,375],{}," yourself — the registered JVM shutdown hook calls it on ",[323,2357,333],{}," (the signal Kubernetes sends on pod termination), and a watcher thread calls it if the engine terminates on its own. It's idempotent and safe to call from any state.",[1316,2360,2362],{"id":2361},"lifecycle-events","Lifecycle events",[320,2364,2365,2366,2369,2370,854,2373,854,2376,854,2379,2382,2383,2386],{},"Each transition emits a ",[423,2367,2368],{"href":206},"lifecycle event"," — ",[323,2371,2372],{},"PRE_START",[323,2374,2375],{},"POST_START",[323,2377,2378],{},"PRE_STOP",[323,2380,2381],{},"POST_STOP"," — to any registered ",[323,2384,2385],{},"RuntimeLifecycleListener",". Use these to start or stop dependent services alongside the runtime.",[393,2388,2390],{"id":2389},"pause-and-unpause","Pause and unpause",[320,2392,2393,2394,2397,2398,2401,2402,360],{},"Processing can be paused and resumed at runtime through the HTTP admin endpoints — ",[323,2395,2396],{},"POST \u002Fpause"," and ",[323,2399,2400],{},"POST \u002Funpause",". Pausing stops the runtime consuming new records while keeping the process alive and its endpoints responsive; unpausing resumes from where it left off. This is operated over HTTP rather than as a code method, so you can drive it from an operator, a script, or a runbook without redeploying. See ",[423,2403,2404],{"href":201},"Pause \u002F unpause",[393,2406,2408],{"id":2407},"the-http-admin-surface","The HTTP admin surface",[320,2410,2411,2412,2415,2416,2419,2420,2422,2423,2425],{},"When ",[323,2413,2414],{},"runtime.http.enabled"," is ",[323,2417,2418],{},"true"," (the default), ",[323,2421,359],{}," brings up an HTTP server and registers the operational endpoints. The full catalogue is in the ",[423,2424,286],{"href":287},"; the highlights:",[339,2427,2428,2442,2452,2488,2508],{},[342,2429,2430,2369,2433,2397,2436,2439,2440,360],{},[345,2431,2432],{},"Health",[323,2434,2435],{},"\u002Fhealth\u002Flive",[323,2437,2438],{},"\u002Fhealth\u002Fready"," for orchestrator probes. See ",[423,2441,190],{"href":191},[342,2443,2444,2369,2446,2449,2450,360],{},[345,2445,195],{},[323,2447,2448],{},"\u002Fmetrics"," for Prometheus scraping. See ",[423,2451,195],{"href":196},[342,2453,2454,2369,2457,854,2460,2463,2464,854,2467,854,2470,854,2473,854,2476,854,2479,854,2482,2182,2485,360],{},[345,2455,2456],{},"Introspection",[323,2458,2459],{},"\u002Finfo",[323,2461,2462],{},"\u002Fconfig"," (masked), ",[323,2465,2466],{},"\u002Ftopology",[323,2468,2469],{},"\u002Ftopology\u002Fks",[323,2471,2472],{},"\u002Ftopology\u002Fcompiled",[323,2474,2475],{},"\u002Fstate",[323,2477,2478],{},"\u002Fwatermarks",[323,2480,2481],{},"\u002Foffsets",[323,2483,2484],{},"\u002Fconsumer",[323,2486,2487],{},"\u002Flicense",[342,2489,2490,2369,2493,854,2496,2499,2500,2503,2504,2507],{},[345,2491,2492],{},"Control",[323,2494,2495],{},"\u002Fpause",[323,2497,2498],{},"\u002Funpause","; plus the ",[323,2501,2502],{},"\u002Fha\u002F*"," status and role-switch endpoints when ",[423,2505,2506],{"href":234},"hot standby"," is enabled.",[342,2509,2510,2369,2513,2397,2516,2519,2520,360],{},[345,2511,2512],{},"Debug",[323,2514,2515],{},"\u002Fdebug\u002Fthreads",[323,2517,2518],{},"\u002Fdebug\u002Fbarriers"," for live diagnostics when a topology misbehaves; gated by ",[323,2521,2522],{},"runtime.http.debug.enabled",[320,2524,2525,2527,2528,2531,2532,2535],{},[323,2526,359],{}," returns a handle on the same runtime, so you can chain into it. A couple of accessors are handy from code: ",[323,2529,2530],{},"httpPort()"," returns the bound port (useful when you let the server pick one), and ",[323,2533,2534],{},"meterRegistry()"," returns the Micrometer registry for custom instrumentation.",[393,2537,2539],{"id":2538},"extending-the-runtime","Extending the runtime",[320,2541,2542],{},"The runtime is designed to be extended without modifying it:",[339,2544,2545,2562,2570],{},[342,2546,2547,2549,2550,2552,2553,2555,2556,2558,2559,2561],{},[345,2548,542],{}," — implement ",[323,2551,538],{}," to register custom HTTP handlers, metrics, or health indicators during startup, and clean them up on shutdown. Register with ",[323,2554,2168],{}," on the builder, or have ",[323,2557,683],{},"'s ",[323,2560,597],{}," block add them.",[342,2563,2564,2549,2567,2569],{},[345,2565,2566],{},"Lifecycle listeners",[323,2568,2385],{}," (a functional interface) to hook the four lifecycle events.",[342,2571,2572,2549,2575,2578,2579,2581,2582,360],{},[345,2573,2574],{},"Custom health indicators",[323,2576,2577],{},"HealthIndicator"," and register via ",[323,2580,2174],{}," or ",[323,2583,2584],{},"PluginContext.healthIndicatorRegistry()",[320,2586,2587,2588,2591,2592,360],{},"The plugin contract, the ",[323,2589,2590],{},"PluginContext"," it receives, and worked examples are in ",[423,2593,542],{"href":206},[393,2595,2597],{"id":2596},"where-to-go-next","Where to go next",[339,2599,2600,2614,2621,2628,2635,2642],{},[342,2601,2602,2606,2607,2397,2610,2613],{},[345,2603,2604],{},[423,2605,474],{"href":163}," — every ",[323,2608,2609],{},"stoatflow.*",[323,2611,2612],{},"runtime.*"," YAML key.",[342,2615,2616,2620],{},[345,2617,2618],{},[423,2619,487],{"href":186}," — the full admin-endpoint catalogue.",[342,2622,2623,2627],{},[345,2624,2625],{},[423,2626,190],{"href":191}," — liveness vs readiness, and the built-in indicators.",[342,2629,2630,2634],{},[345,2631,2632],{},[423,2633,195],{"href":196}," — the Prometheus surface and what to scrape.",[342,2636,2637,2641],{},[345,2638,2639],{},[423,2640,542],{"href":206}," — extend the runtime with custom endpoints, metrics, and lifecycle hooks.",[342,2643,2644,2397,2649,2654],{},[345,2645,2646],{},[423,2647,2648],{"href":211},"Docker",[345,2650,2651],{},[423,2652,2653],{"href":216},"Native image"," — package the runtime for deployment.",[2656,2657,2658],"style",{},"html pre.shiki code .sbBg2, html code.shiki .sbBg2{--shiki-default:#1E754F}html pre.shiki code .sySUi, html code.shiki .sySUi{--shiki-default:#59873A}html pre.shiki code .suHK_, html code.shiki .suHK_{--shiki-default:#393A34}html pre.shiki code .sYZai, html code.shiki .sYZai{--shiki-default:#999999}html pre.shiki code .s8zF2, html code.shiki .s8zF2{--shiki-default:#A0ADA0}html pre.shiki code .si04Y, html code.shiki .si04Y{--shiki-default:#AB5959}html pre.shiki code .sUxyF, html code.shiki .sUxyF{--shiki-default:#2E8F82}html pre.shiki code .spphp, html code.shiki .spphp{--shiki-default:#B56959}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .svycV, html code.shiki .svycV{--shiki-default:#B07D48}html pre.shiki code .sSP4y, html code.shiki .sSP4y{--shiki-default:#B5695977}html pre.shiki code .s-TwI, html code.shiki .s-TwI{--shiki-default:#2F798A}",{"title":613,"searchDepth":631,"depth":631,"links":2660},[2661,2663,2666,2667,2673,2674,2675,2676],{"id":395,"depth":631,"text":2662},"What the runtime adds over :core",{"id":566,"depth":631,"text":567,"children":2664},[2665],{"id":1318,"depth":639,"text":1319},{"id":1638,"depth":631,"text":1639},{"id":2222,"depth":631,"text":2223,"children":2668},[2669,2670,2671,2672],{"id":784,"depth":639,"text":359},{"id":2278,"depth":639,"text":371},{"id":2344,"depth":639,"text":375},{"id":2361,"depth":639,"text":2362},{"id":2389,"depth":631,"text":2390},{"id":2407,"depth":631,"text":2408},{"id":2538,"depth":631,"text":2539},{"id":2596,"depth":631,"text":2597},"The batteries-included :runtime module — StoatFlowRuntime.fromConfig, the lifecycle (start \u002F awaitTermination \u002F stop), and what it adds over the bare :core engine.","md",{},{"icon":183},"how-to",{"title":182,"description":2677},"kFK8yY2hney2_C-rzmpQxPM8R86XaSfzm5xW9C8ulZ8",[2685,2687],{"title":172,"path":173,"stem":174,"description":2686,"icon":175,"children":-1},"Pass arbitrary consumer, producer, and restoration-consumer properties through to the Kafka clients, and understand which properties StoatFlow forces for correctness.",{"title":185,"path":186,"stem":187,"description":2688,"icon":188,"children":-1},"A task-oriented tour of the runtime's built-in HTTP endpoints — metadata, topology, state and progress, health, control, license, metrics, and debug.",1783713353512]