[{"data":1,"prerenderedAt":7219},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Fbuilding\u002Fprocessor-api":314,"\u002Fdocs\u002Fbuilding\u002Fprocessor-api-surround":7214},[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":135,"body":316,"description":7207,"extension":7208,"meta":7209,"navigation":7210,"pageType":7211,"path":136,"seo":7212,"stem":137,"__hash__":7213},"docs\u002F1.docs\u002F3.building\u002F7.processor-api.md",{"type":317,"value":318,"toc":7180},"minimark",[319,335,417,422,425,484,495,516,521,530,963,967,975,1302,1306,1319,1342,1352,1581,1595,1598,1611,1615,1623,1683,1705,1709,1712,1821,1836,1852,1855,1862,1866,1883,2543,2547,2567,2865,2869,2886,3552,3555,3574,3588,3592,3601,3657,3682,3686,3691,3725,3749,3753,4519,4536,4539,4554,4558,4572,4576,4593,4667,4674,4700,6121,6134,6138,6147,7131,7135,7176],[320,321,322,323,327,328,331,332,334],"p",{},"When the declarative DSL operators don't cover what you need, drop down to the ",[324,325,326],"strong",{},"Processor API",": a record-by-record interface where you control forwarding, state access, periodic work, and timers directly. It mirrors the Kafka Streams Processor API, so code written for KS ports with only an import change. For the engine model behind state access and timer execution, see ",[329,330,47],"a",{"href":48}," and ",[329,333,57],{"href":58},".",[336,337,338],"tldr-panel",{},[339,340,341,365,385,395,407],"ul",{},[342,343,344,350,351,354,355,360,361,364],"li",{},[324,345,346],{},[347,348,349],"code",{},"Processor\u003CKIn, VIn, KOut, VOut>"," can change keys (",[347,352,353],{},"KStream.process","); ",[324,356,357],{},[347,358,359],{},"FixedKeyProcessor\u003CKIn, VIn, VOut>"," preserves the key (",[347,362,363],{},"KStream.processValues",").",[342,366,367,370,371,374,375,378,379,370,382,334],{},[324,368,369],{},"Forward"," via ",[347,372,373],{},"ProcessorContext"," \u002F ",[347,376,377],{},"FixedKeyProcessorContext","; ",[324,380,381],{},"read\u002Fwrite state",[347,383,384],{},"getStateStore(name)",[342,386,387,390,391,394],{},[324,388,389],{},"Punctuators"," (",[347,392,393],{},"context.schedule(...)",") run periodically on stream time or wall-clock time.",[342,396,397,390,400,403,404,334],{},[324,398,399],{},"Timers",[347,401,402],{},"context.timerService()",") fire per key at an event-time or processing-time instant, calling ",[347,405,406],{},"onTimer(...)",[342,408,409,410,413,414,334],{},"Attach stores by declaring them in the supplier's ",[347,411,412],{},"stores()"," set, or register with ",[347,415,416],{},"builder.addStateStore(...)",[418,419,421],"h2",{"id":420},"processor-vs-fixedkeyprocessor","Processor vs FixedKeyProcessor",[320,423,424],{},"Two interfaces, chosen by whether your logic changes the record key:",[426,427,428,446],"table",{},[429,430,431],"thead",{},[432,433,434,438,441,444],"tr",{},[435,436,437],"th",{},"Interface",[435,439,440],{},"Attach with",[435,442,443],{},"Can change key?",[435,445,369],{},[447,448,449,467],"tbody",{},[432,450,451,456,461,464],{},[452,453,454],"td",{},[347,455,349],{},[452,457,458],{},[347,459,460],{},"KStream.process(...)",[452,462,463],{},"Yes",[452,465,466],{},"new key + value",[432,468,469,473,478,481],{},[452,470,471],{},[347,472,359],{},[452,474,475],{},[347,476,477],{},"KStream.processValues(...)",[452,479,480],{},"No (key fixed)",[452,482,483],{},"value only",[320,485,486,487,490,491,494],{},"Use ",[347,488,489],{},"FixedKeyProcessor"," whenever you only transform values — keeping the key fixed avoids a re-keying boundary in the topology. Reach for ",[347,492,493],{},"Processor"," when you need to emit records under a different key.",[320,496,497,498,501,502,331,505,508,509,512,513,334],{},"Both interfaces are in ",[347,499,500],{},"io.stoatflow.core.processor",". The convenience base classes ",[347,503,504],{},"ContextualProcessor",[347,506,507],{},"ContextualFixedKeyProcessor"," store the context for you so you don't have to keep a field; ",[347,510,511],{},"context()"," returns it after ",[347,514,515],{},"init",[517,518,520],"h3",{"id":519},"a-value-only-processor","A value-only processor",[320,522,523,525,526,529],{},[347,524,489],{}," transforms the value and forwards it under the original key. ",[347,527,528],{},"process(record)"," runs once per input record; forward zero records to filter the record out, or more than one to fan out.",[531,532,534,724],"code-tabs",{"group":533},"lang",[535,536,542],"pre",{"className":537,"code":538,"filename":539,"language":540,"meta":541,"style":541},"language-kotlin shiki shiki-themes vitesse-light","import io.stoatflow.core.processor.ContextualFixedKeyProcessor\nimport io.stoatflow.core.processor.FixedKeyRecord\n\nclass UppercaseProcessor : ContextualFixedKeyProcessor\u003CString, String, String>() {\n    override fun process(record: FixedKeyRecord\u003CString, String>) {\n        val value = record.value\n        if (value.isNotBlank()) {\n            \u002F\u002F key and timestamp are preserved automatically\n            context().forward(value.uppercase())\n        }\n    }\n}\n","Kotlin","kotlin","",[347,543,544,557,565,572,606,636,655,674,681,706,712,718],{"__ignoreMap":541},[545,546,549,553],"span",{"class":547,"line":548},"line",1,[545,550,552],{"class":551},"sbBg2","import",[545,554,556],{"class":555},"sySUi"," io.stoatflow.core.processor.ContextualFixedKeyProcessor\n",[545,558,560,562],{"class":547,"line":559},2,[545,561,552],{"class":551},[545,563,564],{"class":555}," io.stoatflow.core.processor.FixedKeyRecord\n",[545,566,568],{"class":547,"line":567},3,[545,569,571],{"emptyLinePlaceholder":570},true,"\n",[545,573,575,578,582,586,588,591,594,597,599,601,603],{"class":547,"line":574},4,[545,576,577],{"class":551},"class",[545,579,581],{"class":580},"sUxyF"," UppercaseProcessor",[545,583,585],{"class":584},"suHK_"," : ",[545,587,507],{"class":580},[545,589,590],{"class":584},"\u003C",[545,592,593],{"class":580},"String",[545,595,596],{"class":584},", ",[545,598,593],{"class":580},[545,600,596],{"class":584},[545,602,593],{"class":580},[545,604,605],{"class":584},">() {\n",[545,607,609,613,616,619,622,625,627,629,631,633],{"class":547,"line":608},5,[545,610,612],{"class":611},"si04Y","    override",[545,614,615],{"class":551}," fun",[545,617,618],{"class":555}," process",[545,620,621],{"class":584},"(record: ",[545,623,624],{"class":580},"FixedKeyRecord",[545,626,590],{"class":584},[545,628,593],{"class":580},[545,630,596],{"class":584},[545,632,593],{"class":580},[545,634,635],{"class":584},">) {\n",[545,637,639,642,645,649,652],{"class":547,"line":638},6,[545,640,641],{"class":551},"        val",[545,643,644],{"class":611}," value",[545,646,648],{"class":647},"sYZai"," =",[545,650,651],{"class":584}," record.",[545,653,654],{"class":611},"value\n",[545,656,658,661,663,666,668,671],{"class":547,"line":657},7,[545,659,660],{"class":551},"        if",[545,662,390],{"class":584},[545,664,665],{"class":611},"value",[545,667,334],{"class":584},[545,669,670],{"class":555},"isNotBlank",[545,672,673],{"class":584},"()) {\n",[545,675,677],{"class":547,"line":676},8,[545,678,680],{"class":679},"s8zF2","            \u002F\u002F key and timestamp are preserved automatically\n",[545,682,684,687,690,693,696,698,700,703],{"class":547,"line":683},9,[545,685,686],{"class":555},"            context",[545,688,689],{"class":584},"().",[545,691,692],{"class":555},"forward",[545,694,695],{"class":584},"(",[545,697,665],{"class":611},[545,699,334],{"class":584},[545,701,702],{"class":555},"uppercase",[545,704,705],{"class":584},"())\n",[545,707,709],{"class":547,"line":708},10,[545,710,711],{"class":584},"        }\n",[545,713,715],{"class":547,"line":714},11,[545,716,717],{"class":584},"    }\n",[545,719,721],{"class":547,"line":720},12,[545,722,723],{"class":584},"}\n",[535,725,730],{"className":726,"code":727,"filename":728,"language":729,"meta":541,"style":541},"language-java shiki shiki-themes vitesse-light","import io.stoatflow.core.processor.ContextualFixedKeyProcessor;\nimport io.stoatflow.core.processor.FixedKeyRecord;\n\npublic class UppercaseProcessor\n        extends ContextualFixedKeyProcessor\u003CString, String, String> {\n\n    @Override\n    public void process(FixedKeyRecord\u003CString, String> record) {\n        String value = record.value();\n        if (value != null && !value.isBlank()) {\n            \u002F\u002F key and timestamp are preserved automatically\n            context().forward(value.toUpperCase());\n        }\n    }\n}\n","Java","java",[347,731,732,761,785,789,800,828,832,840,873,891,924,928,948,953,958],{"__ignoreMap":541},[545,733,734,736,739,741,744,746,749,751,754,756,758],{"class":547,"line":548},[545,735,552],{"class":551},[545,737,738],{"class":584}," io",[545,740,334],{"class":647},[545,742,743],{"class":584},"stoatflow",[545,745,334],{"class":647},[545,747,748],{"class":584},"core",[545,750,334],{"class":647},[545,752,753],{"class":584},"processor",[545,755,334],{"class":647},[545,757,507],{"class":584},[545,759,760],{"class":647},";\n",[545,762,763,765,767,769,771,773,775,777,779,781,783],{"class":547,"line":559},[545,764,552],{"class":551},[545,766,738],{"class":584},[545,768,334],{"class":647},[545,770,743],{"class":584},[545,772,334],{"class":647},[545,774,748],{"class":584},[545,776,334],{"class":647},[545,778,753],{"class":584},[545,780,334],{"class":647},[545,782,624],{"class":584},[545,784,760],{"class":647},[545,786,787],{"class":547,"line":567},[545,788,571],{"emptyLinePlaceholder":570},[545,790,791,794,797],{"class":547,"line":574},[545,792,793],{"class":611},"public",[545,795,796],{"class":611}," class",[545,798,799],{"class":580}," UppercaseProcessor\n",[545,801,802,805,808,810,812,815,818,820,822,825],{"class":547,"line":608},[545,803,804],{"class":611},"        extends",[545,806,807],{"class":555}," ContextualFixedKeyProcessor",[545,809,590],{"class":647},[545,811,593],{"class":611},[545,813,814],{"class":647},",",[545,816,817],{"class":611}," String",[545,819,814],{"class":647},[545,821,817],{"class":611},[545,823,824],{"class":647},">",[545,826,827],{"class":647}," {\n",[545,829,830],{"class":547,"line":638},[545,831,571],{"emptyLinePlaceholder":570},[545,833,834,837],{"class":547,"line":657},[545,835,836],{"class":647},"    @",[545,838,839],{"class":611},"Override\n",[545,841,842,845,848,850,852,854,856,858,860,862,864,868,871],{"class":547,"line":676},[545,843,844],{"class":611},"    public",[545,846,847],{"class":611}," void",[545,849,618],{"class":555},[545,851,695],{"class":647},[545,853,624],{"class":584},[545,855,590],{"class":647},[545,857,593],{"class":611},[545,859,814],{"class":647},[545,861,817],{"class":611},[545,863,824],{"class":647},[545,865,867],{"class":866},"svycV"," record",[545,869,870],{"class":647},")",[545,872,827],{"class":647},[545,874,875,878,880,882,884,886,888],{"class":547,"line":683},[545,876,877],{"class":584},"        String",[545,879,644],{"class":866},[545,881,648],{"class":647},[545,883,867],{"class":866},[545,885,334],{"class":647},[545,887,665],{"class":555},[545,889,890],{"class":647},"();\n",[545,892,893,895,897,900,903,906,909,912,914,916,919,922],{"class":547,"line":708},[545,894,660],{"class":551},[545,896,390],{"class":647},[545,898,899],{"class":584},"value ",[545,901,902],{"class":611},"!=",[545,904,905],{"class":551}," null",[545,907,908],{"class":611}," &&",[545,910,911],{"class":611}," !",[545,913,665],{"class":866},[545,915,334],{"class":647},[545,917,918],{"class":555},"isBlank",[545,920,921],{"class":647},"())",[545,923,827],{"class":647},[545,925,926],{"class":547,"line":714},[545,927,680],{"class":679},[545,929,930,932,934,936,938,940,942,945],{"class":547,"line":720},[545,931,686],{"class":555},[545,933,689],{"class":647},[545,935,692],{"class":555},[545,937,695],{"class":647},[545,939,665],{"class":866},[545,941,334],{"class":647},[545,943,944],{"class":555},"toUpperCase",[545,946,947],{"class":647},"());\n",[545,949,951],{"class":547,"line":950},13,[545,952,711],{"class":647},[545,954,956],{"class":547,"line":955},14,[545,957,717],{"class":647},[545,959,961],{"class":547,"line":960},15,[545,962,723],{"class":647},[517,964,966],{"id":965},"a-key-changing-processor","A key-changing processor",[320,968,969,971,972,974],{},[347,970,493],{}," can emit records under a different key. ",[347,973,460],{}," is a key-changing operation, so downstream stateful operators see the new key.",[531,976,977,1096],{"group":533},[535,978,980],{"className":537,"code":979,"filename":539,"language":540,"meta":541,"style":541},"import io.stoatflow.core.processor.ContextualProcessor\nimport io.stoatflow.core.processor.Record\n\nclass RouteByTypeProcessor : ContextualProcessor\u003CString, Event, String, Event>() {\n    override fun process(record: Record\u003CString, Event>) {\n        val event = record.value\n        \u002F\u002F re-key on the event type, keeping the original timestamp\n        context().forward(Record(event.type, event, record.timestamp))\n    }\n}\n",[347,981,982,989,996,1000,1030,1053,1067,1072,1088,1092],{"__ignoreMap":541},[545,983,984,986],{"class":547,"line":548},[545,985,552],{"class":551},[545,987,988],{"class":555}," io.stoatflow.core.processor.ContextualProcessor\n",[545,990,991,993],{"class":547,"line":559},[545,992,552],{"class":551},[545,994,995],{"class":555}," io.stoatflow.core.processor.Record\n",[545,997,998],{"class":547,"line":567},[545,999,571],{"emptyLinePlaceholder":570},[545,1001,1002,1004,1007,1009,1011,1013,1015,1017,1020,1022,1024,1026,1028],{"class":547,"line":574},[545,1003,577],{"class":551},[545,1005,1006],{"class":580}," RouteByTypeProcessor",[545,1008,585],{"class":584},[545,1010,504],{"class":580},[545,1012,590],{"class":584},[545,1014,593],{"class":580},[545,1016,596],{"class":584},[545,1018,1019],{"class":580},"Event",[545,1021,596],{"class":584},[545,1023,593],{"class":580},[545,1025,596],{"class":584},[545,1027,1019],{"class":580},[545,1029,605],{"class":584},[545,1031,1032,1034,1036,1038,1040,1043,1045,1047,1049,1051],{"class":547,"line":608},[545,1033,612],{"class":611},[545,1035,615],{"class":551},[545,1037,618],{"class":555},[545,1039,621],{"class":584},[545,1041,1042],{"class":580},"Record",[545,1044,590],{"class":584},[545,1046,593],{"class":580},[545,1048,596],{"class":584},[545,1050,1019],{"class":580},[545,1052,635],{"class":584},[545,1054,1055,1057,1060,1063,1065],{"class":547,"line":638},[545,1056,641],{"class":551},[545,1058,1059],{"class":584}," event ",[545,1061,1062],{"class":647},"=",[545,1064,651],{"class":584},[545,1066,654],{"class":611},[545,1068,1069],{"class":547,"line":657},[545,1070,1071],{"class":679},"        \u002F\u002F re-key on the event type, keeping the original timestamp\n",[545,1073,1074,1077,1079,1081,1083,1085],{"class":547,"line":676},[545,1075,1076],{"class":555},"        context",[545,1078,689],{"class":584},[545,1080,692],{"class":555},[545,1082,695],{"class":584},[545,1084,1042],{"class":555},[545,1086,1087],{"class":584},"(event.type, event, record.timestamp))\n",[545,1089,1090],{"class":547,"line":683},[545,1091,717],{"class":584},[545,1093,1094],{"class":547,"line":708},[545,1095,723],{"class":584},[535,1097,1099],{"className":726,"code":1098,"filename":728,"language":729,"meta":541,"style":541},"import io.stoatflow.core.processor.ContextualProcessor;\nimport io.stoatflow.core.processor.Record;\n\npublic class RouteByTypeProcessor\n        extends ContextualProcessor\u003CString, Event, String, Event> {\n\n    @Override\n    public void process(Record\u003CString, Event> record) {\n        Event event = record.value();\n        \u002F\u002F re-key on the event type, keeping the original timestamp\n        context().forward(new Record\u003C>(event.type(), event, record.timestamp()));\n    }\n}\n",[347,1100,1101,1125,1149,1153,1162,1190,1194,1200,1228,1246,1250,1294,1298],{"__ignoreMap":541},[545,1102,1103,1105,1107,1109,1111,1113,1115,1117,1119,1121,1123],{"class":547,"line":548},[545,1104,552],{"class":551},[545,1106,738],{"class":584},[545,1108,334],{"class":647},[545,1110,743],{"class":584},[545,1112,334],{"class":647},[545,1114,748],{"class":584},[545,1116,334],{"class":647},[545,1118,753],{"class":584},[545,1120,334],{"class":647},[545,1122,504],{"class":584},[545,1124,760],{"class":647},[545,1126,1127,1129,1131,1133,1135,1137,1139,1141,1143,1145,1147],{"class":547,"line":559},[545,1128,552],{"class":551},[545,1130,738],{"class":584},[545,1132,334],{"class":647},[545,1134,743],{"class":584},[545,1136,334],{"class":647},[545,1138,748],{"class":584},[545,1140,334],{"class":647},[545,1142,753],{"class":584},[545,1144,334],{"class":647},[545,1146,1042],{"class":584},[545,1148,760],{"class":647},[545,1150,1151],{"class":547,"line":567},[545,1152,571],{"emptyLinePlaceholder":570},[545,1154,1155,1157,1159],{"class":547,"line":574},[545,1156,793],{"class":611},[545,1158,796],{"class":611},[545,1160,1161],{"class":580}," RouteByTypeProcessor\n",[545,1163,1164,1166,1169,1171,1173,1175,1178,1180,1182,1184,1186,1188],{"class":547,"line":608},[545,1165,804],{"class":611},[545,1167,1168],{"class":555}," ContextualProcessor",[545,1170,590],{"class":647},[545,1172,593],{"class":611},[545,1174,814],{"class":647},[545,1176,1177],{"class":611}," Event",[545,1179,814],{"class":647},[545,1181,817],{"class":611},[545,1183,814],{"class":647},[545,1185,1177],{"class":611},[545,1187,824],{"class":647},[545,1189,827],{"class":647},[545,1191,1192],{"class":547,"line":638},[545,1193,571],{"emptyLinePlaceholder":570},[545,1195,1196,1198],{"class":547,"line":657},[545,1197,836],{"class":647},[545,1199,839],{"class":611},[545,1201,1202,1204,1206,1208,1210,1212,1214,1216,1218,1220,1222,1224,1226],{"class":547,"line":676},[545,1203,844],{"class":611},[545,1205,847],{"class":611},[545,1207,618],{"class":555},[545,1209,695],{"class":647},[545,1211,1042],{"class":584},[545,1213,590],{"class":647},[545,1215,593],{"class":611},[545,1217,814],{"class":647},[545,1219,1177],{"class":611},[545,1221,824],{"class":647},[545,1223,867],{"class":866},[545,1225,870],{"class":647},[545,1227,827],{"class":647},[545,1229,1230,1233,1236,1238,1240,1242,1244],{"class":547,"line":683},[545,1231,1232],{"class":584},"        Event",[545,1234,1235],{"class":866}," event",[545,1237,648],{"class":647},[545,1239,867],{"class":866},[545,1241,334],{"class":647},[545,1243,665],{"class":555},[545,1245,890],{"class":647},[545,1247,1248],{"class":547,"line":708},[545,1249,1071],{"class":679},[545,1251,1252,1254,1256,1258,1260,1263,1266,1269,1272,1274,1277,1280,1282,1284,1286,1288,1291],{"class":547,"line":714},[545,1253,1076],{"class":555},[545,1255,689],{"class":647},[545,1257,692],{"class":555},[545,1259,695],{"class":647},[545,1261,1262],{"class":551},"new",[545,1264,1265],{"class":584}," Record",[545,1267,1268],{"class":647},"\u003C>(",[545,1270,1271],{"class":866},"event",[545,1273,334],{"class":647},[545,1275,1276],{"class":555},"type",[545,1278,1279],{"class":647},"(),",[545,1281,1235],{"class":584},[545,1283,814],{"class":647},[545,1285,867],{"class":866},[545,1287,334],{"class":647},[545,1289,1290],{"class":555},"timestamp",[545,1292,1293],{"class":647},"()));\n",[545,1295,1296],{"class":547,"line":720},[545,1297,717],{"class":647},[545,1299,1300],{"class":547,"line":950},[545,1301,723],{"class":647},[418,1303,1305],{"id":1304},"suppliers","Suppliers",[320,1307,1308,331,1311,1314,1315,1318],{},[347,1309,1310],{},"process",[347,1312,1313],{},"processValues"," take a ",[324,1316,1317],{},"supplier",", not a processor instance — the engine creates fresh instances as needed:",[339,1320,1321,1333],{},[342,1322,1323,1326,1327,1330,1331,334],{},[347,1324,1325],{},"ProcessorSupplier\u003CKIn, VIn, KOut, VOut>"," — ",[347,1328,1329],{},"get()"," returns a ",[347,1332,493],{},[342,1334,1335,1326,1338,1330,1340,334],{},[347,1336,1337],{},"FixedKeyProcessorSupplier\u003CKIn, VIn, VOut>",[347,1339,1329],{},[347,1341,489],{},[320,1343,1344,1345,1347,1348,334],{},"Both are functional interfaces, so a lambda or method reference works. They also expose a ",[347,1346,412],{}," method (default: empty) for declaring state stores inline with the processor — see ",[329,1349,1351],{"href":1350},"#attaching-state-stores","Attaching state stores",[531,1353,1354,1460],{"group":533},[535,1355,1357],{"className":537,"code":1356,"filename":539,"language":540,"meta":541,"style":541},"val routed: KStream\u003CString, Event> =\n    events.process({ RouteByTypeProcessor() }, Named.`as`(\"route-by-type\"))\n\nval shouted: KStream\u003CString, String> =\n    lines.processValues({ UppercaseProcessor() }, Named.`as`(\"uppercase\"))\n",[347,1358,1359,1384,1412,1416,1437],{"__ignoreMap":541},[545,1360,1361,1364,1367,1370,1372,1374,1376,1378,1381],{"class":547,"line":548},[545,1362,1363],{"class":551},"val",[545,1365,1366],{"class":584}," routed: ",[545,1368,1369],{"class":580},"KStream",[545,1371,590],{"class":584},[545,1373,593],{"class":580},[545,1375,596],{"class":584},[545,1377,1019],{"class":580},[545,1379,1380],{"class":584},"> ",[545,1382,1383],{"class":647},"=\n",[545,1385,1386,1389,1391,1394,1397,1400,1403,1405,1409],{"class":547,"line":559},[545,1387,1388],{"class":584},"    events.",[545,1390,1310],{"class":555},[545,1392,1393],{"class":584},"({ ",[545,1395,1396],{"class":555},"RouteByTypeProcessor",[545,1398,1399],{"class":584},"() }, Named.",[545,1401,1402],{"class":555},"`as`",[545,1404,695],{"class":584},[545,1406,1408],{"class":1407},"spphp","\"route-by-type\"",[545,1410,1411],{"class":584},"))\n",[545,1413,1414],{"class":547,"line":567},[545,1415,571],{"emptyLinePlaceholder":570},[545,1417,1418,1420,1423,1425,1427,1429,1431,1433,1435],{"class":547,"line":574},[545,1419,1363],{"class":551},[545,1421,1422],{"class":584}," shouted: ",[545,1424,1369],{"class":580},[545,1426,590],{"class":584},[545,1428,593],{"class":580},[545,1430,596],{"class":584},[545,1432,593],{"class":580},[545,1434,1380],{"class":584},[545,1436,1383],{"class":647},[545,1438,1439,1442,1444,1446,1449,1451,1453,1455,1458],{"class":547,"line":608},[545,1440,1441],{"class":584},"    lines.",[545,1443,1313],{"class":555},[545,1445,1393],{"class":584},[545,1447,1448],{"class":555},"UppercaseProcessor",[545,1450,1399],{"class":584},[545,1452,1402],{"class":555},[545,1454,695],{"class":584},[545,1456,1457],{"class":1407},"\"uppercase\"",[545,1459,1411],{"class":584},[535,1461,1463],{"className":726,"code":1462,"filename":728,"language":729,"meta":541,"style":541},"KStream\u003CString, Event> routed =\n    events.process(RouteByTypeProcessor::new, Named.as(\"route-by-type\"));\n\nKStream\u003CString, String> shouted =\n    lines.processValues(UppercaseProcessor::new, Named.as(\"uppercase\"));\n",[347,1464,1465,1485,1525,1529,1548],{"__ignoreMap":541},[545,1466,1467,1469,1471,1473,1475,1477,1479,1482],{"class":547,"line":548},[545,1468,1369],{"class":584},[545,1470,590],{"class":647},[545,1472,593],{"class":611},[545,1474,814],{"class":647},[545,1476,1177],{"class":611},[545,1478,824],{"class":647},[545,1480,1481],{"class":866}," routed",[545,1483,1484],{"class":647}," =\n",[545,1486,1487,1490,1492,1494,1496,1498,1501,1503,1506,1508,1511,1513,1517,1520,1522],{"class":547,"line":559},[545,1488,1489],{"class":866},"    events",[545,1491,334],{"class":647},[545,1493,1310],{"class":555},[545,1495,695],{"class":647},[545,1497,1396],{"class":584},[545,1499,1500],{"class":551},"::new",[545,1502,814],{"class":647},[545,1504,1505],{"class":866}," Named",[545,1507,334],{"class":647},[545,1509,1510],{"class":555},"as",[545,1512,695],{"class":647},[545,1514,1516],{"class":1515},"sSP4y","\"",[545,1518,1519],{"class":1407},"route-by-type",[545,1521,1516],{"class":1515},[545,1523,1524],{"class":647},"));\n",[545,1526,1527],{"class":547,"line":567},[545,1528,571],{"emptyLinePlaceholder":570},[545,1530,1531,1533,1535,1537,1539,1541,1543,1546],{"class":547,"line":574},[545,1532,1369],{"class":584},[545,1534,590],{"class":647},[545,1536,593],{"class":611},[545,1538,814],{"class":647},[545,1540,817],{"class":611},[545,1542,824],{"class":647},[545,1544,1545],{"class":866}," shouted",[545,1547,1484],{"class":647},[545,1549,1550,1553,1555,1557,1559,1561,1563,1565,1567,1569,1571,1573,1575,1577,1579],{"class":547,"line":608},[545,1551,1552],{"class":866},"    lines",[545,1554,334],{"class":647},[545,1556,1313],{"class":555},[545,1558,695],{"class":647},[545,1560,1448],{"class":584},[545,1562,1500],{"class":551},[545,1564,814],{"class":647},[545,1566,1505],{"class":866},[545,1568,334],{"class":647},[545,1570,1510],{"class":555},[545,1572,695],{"class":647},[545,1574,1516],{"class":1515},[545,1576,702],{"class":1407},[545,1578,1516],{"class":1515},[545,1580,1524],{"class":647},[1582,1583,1586],"callout",{"color":1584,"icon":1585},"info","i-lucide-info",[320,1587,1588,1589,1592,1593,334],{},"The ",[347,1590,1591],{},"Named"," argument is optional but recommended — StoatFlow uses these stable names for the topology graph, metrics, and state-store identity. The same convention as the DSL operators in ",[329,1594,28],{"href":29},[418,1596,373],{"id":1597},"processorcontext",[320,1599,1600,1603,1604,1607,1608,1610],{},[347,1601,1602],{},"init(context)"," is called once before any records. Store the context (or extend a ",[347,1605,1606],{},"Contextual*"," base class and use ",[347,1609,511],{},"). The context gives you forwarding, record metadata, time access, state stores, punctuator scheduling, and the timer service.",[517,1612,1614],{"id":1613},"forwarding","Forwarding",[320,1616,1617,1619,1620,1622],{},[347,1618,373],{}," (key-changing) forwards a full ",[347,1621,1042],{}," or a key\u002Fvalue pair:",[426,1624,1625,1635],{},[429,1626,1627],{},[432,1628,1629,1632],{},[435,1630,1631],{},"Method",[435,1633,1634],{},"Behaviour",[447,1636,1637,1650,1660,1670],{},[432,1638,1639,1644],{},[452,1640,1641],{},[347,1642,1643],{},"forward(record)",[452,1645,1646,1647],{},"Forward a ",[347,1648,1649],{},"Record\u003CKOut, VOut>",[432,1651,1652,1657],{},[452,1653,1654],{},[347,1655,1656],{},"forward(key, value)",[452,1658,1659],{},"Forward using the current record's timestamp",[432,1661,1662,1667],{},[452,1663,1664],{},[347,1665,1666],{},"forward(key, value, timestamp)",[452,1668,1669],{},"Forward with an explicit timestamp",[432,1671,1672,1680],{},[452,1673,1674,374,1677],{},[347,1675,1676],{},"forward(record, childName)",[347,1678,1679],{},"forward(key, value, childName)",[452,1681,1682],{},"Forward to a specific named child node",[320,1684,1685,1687,1688,596,1691,1694,1695,374,1697,1700,1701,1704],{},[347,1686,377],{}," forwards values only — the key is fixed: ",[347,1689,1690],{},"forward(value)",[347,1692,1693],{},"forward(value, timestamp)",", and the ",[347,1696,624],{},[347,1698,1699],{},"childName"," variants. Call ",[347,1702,1703],{},"key()"," on the context to read the (immutable) key.",[517,1706,1708],{"id":1707},"record-metadata-and-time","Record metadata and time",[320,1710,1711],{},"Both contexts expose the metadata of the record currently being processed and the engine's time notions:",[426,1713,1714,1723],{},[429,1715,1716],{},[432,1717,1718,1720],{},[435,1719,1631],{},[435,1721,1722],{},"Returns",[447,1724,1725,1735,1747,1763,1773,1787,1799,1812],{},[432,1726,1727,1732],{},[452,1728,1729],{},[347,1730,1731],{},"timestamp()",[452,1733,1734],{},"Timestamp of the current record",[432,1736,1737,1742],{},[452,1738,1739],{},[347,1740,1741],{},"headers()",[452,1743,1744],{},[347,1745,1746],{},"org.apache.kafka.common.header.Headers",[432,1748,1749,1760],{},[452,1750,1751,374,1754,374,1757],{},[347,1752,1753],{},"topic()",[347,1755,1756],{},"partition()",[347,1758,1759],{},"offset()",[452,1761,1762],{},"Source coordinates of the current record",[432,1764,1765,1770],{},[452,1766,1767],{},[347,1768,1769],{},"applicationId()",[452,1771,1772],{},"The configured application ID",[432,1774,1775,1780],{},[452,1776,1777],{},[347,1778,1779],{},"currentWatermarkMs()",[452,1781,1782,1783,1786],{},"Global event-time progress (min watermark across non-idle partitions); may be ",[347,1784,1785],{},"Long.MIN_VALUE"," before any events",[432,1788,1789,1794],{},[452,1790,1791],{},[347,1792,1793],{},"currentStreamTimeMs()",[452,1795,1796,1797],{},"KS-compatible alias for ",[347,1798,1779],{},[432,1800,1801,1806],{},[452,1802,1803],{},[347,1804,1805],{},"currentSystemTimeMs()",[452,1807,1808,1809,870],{},"Wall-clock time (",[347,1810,1811],{},"System.currentTimeMillis()",[432,1813,1814,1818],{},[452,1815,1816],{},[347,1817,384],{},[452,1819,1820],{},"A state store by name",[320,1822,1823,1825,1826,1829,1830,1833,1834,334],{},[347,1824,373],{}," additionally has ",[347,1827,1828],{},"isLate()"," — true when the current record's timestamp is below the watermark. It's only meaningful during ",[347,1831,1832],{},"process(...)","; in timer and punctuator callbacks it returns false. See ",[329,1835,67],{"href":68},[1582,1837,1838],{"color":1584,"icon":103},[320,1839,1840,1841,596,1843,1845,1846,1848,1849,334],{},"State stores are epoch-scoped and accessed only from within ",[347,1842,1832],{},[347,1844,406],{},", and punctuators — not from ",[347,1847,515],{}," background threads of your own making. Reads see your own uncommitted writes; the engine flushes and makes them durable at commit barriers. See ",[329,1850,1851],{"href":63},"State and thread safety",[418,1853,1351],{"id":1854},"attaching-state-stores",[320,1856,1857,1858,1861],{},"A processor reads and writes a store by name via ",[347,1859,1860],{},"context.getStateStore(name)",". The store must exist in the topology and be connected to the processor. Two ways to do that:",[517,1863,1865],{"id":1864},"option-a-declare-stores-in-the-supplier","Option A — declare stores in the supplier",[320,1867,1868,1869,1871,1872,1875,1876,1879,1880,334],{},"Override ",[347,1870,412],{}," on the supplier to return the ",[347,1873,1874],{},"StateStoreBuilder","s the processor needs. The engine creates and connects them automatically. Build store builders with the ",[347,1877,1878],{},"Stores"," factory in ",[347,1881,1882],{},"io.stoatflow.core.state",[531,1884,1885,2111],{"group":533},[535,1886,1888],{"className":537,"code":1887,"filename":539,"language":540,"meta":541,"style":541},"import io.stoatflow.core.processor.ProcessorSupplier\nimport io.stoatflow.core.state.StateStoreBuilder\nimport io.stoatflow.core.state.Stores\nimport org.apache.kafka.common.serialization.Serdes\n\nval supplier =\n    object : ProcessorSupplier\u003CString, Event, String, Event> {\n        override fun get() = SessionProcessor(\"sessions\")\n\n        override fun stores(): Set\u003CStateStoreBuilder\u003C*>> =\n            setOf(\n                Stores.keyValueStoreBuilder(\n                    Stores.persistentKeyValueStore(\"sessions\"),\n                    Serdes.String(),\n                    sessionSerde,\n                ),\n            )\n    }\n\nval out = events.process(supplier, Named.`as`(\"sessionize\"))\n",[347,1889,1890,1897,1904,1911,1918,1922,1931,1960,1986,1990,2014,2022,2032,2047,2057,2062,2068,2074,2079,2084],{"__ignoreMap":541},[545,1891,1892,1894],{"class":547,"line":548},[545,1893,552],{"class":551},[545,1895,1896],{"class":555}," io.stoatflow.core.processor.ProcessorSupplier\n",[545,1898,1899,1901],{"class":547,"line":559},[545,1900,552],{"class":551},[545,1902,1903],{"class":555}," io.stoatflow.core.state.StateStoreBuilder\n",[545,1905,1906,1908],{"class":547,"line":567},[545,1907,552],{"class":551},[545,1909,1910],{"class":555}," io.stoatflow.core.state.Stores\n",[545,1912,1913,1915],{"class":547,"line":574},[545,1914,552],{"class":551},[545,1916,1917],{"class":555}," org.apache.kafka.common.serialization.Serdes\n",[545,1919,1920],{"class":547,"line":608},[545,1921,571],{"emptyLinePlaceholder":570},[545,1923,1924,1926,1929],{"class":547,"line":638},[545,1925,1363],{"class":551},[545,1927,1928],{"class":584}," supplier ",[545,1930,1383],{"class":647},[545,1932,1933,1936,1938,1941,1943,1945,1947,1949,1951,1953,1955,1957],{"class":547,"line":657},[545,1934,1935],{"class":551},"    object",[545,1937,585],{"class":584},[545,1939,1940],{"class":580},"ProcessorSupplier",[545,1942,590],{"class":584},[545,1944,593],{"class":580},[545,1946,596],{"class":584},[545,1948,1019],{"class":580},[545,1950,596],{"class":584},[545,1952,593],{"class":580},[545,1954,596],{"class":584},[545,1956,1019],{"class":580},[545,1958,1959],{"class":584},"> {\n",[545,1961,1962,1965,1967,1970,1973,1975,1978,1980,1983],{"class":547,"line":676},[545,1963,1964],{"class":611},"        override",[545,1966,615],{"class":551},[545,1968,1969],{"class":555}," get",[545,1971,1972],{"class":584},"() ",[545,1974,1062],{"class":647},[545,1976,1977],{"class":555}," SessionProcessor",[545,1979,695],{"class":584},[545,1981,1982],{"class":1407},"\"sessions\"",[545,1984,1985],{"class":584},")\n",[545,1987,1988],{"class":547,"line":683},[545,1989,571],{"emptyLinePlaceholder":570},[545,1991,1992,1994,1996,1999,2002,2005,2007,2009,2012],{"class":547,"line":708},[545,1993,1964],{"class":611},[545,1995,615],{"class":551},[545,1997,1998],{"class":555}," stores",[545,2000,2001],{"class":584},"(): ",[545,2003,2004],{"class":580},"Set",[545,2006,590],{"class":584},[545,2008,1874],{"class":580},[545,2010,2011],{"class":584},"\u003C*>> ",[545,2013,1383],{"class":647},[545,2015,2016,2019],{"class":547,"line":714},[545,2017,2018],{"class":555},"            setOf",[545,2020,2021],{"class":584},"(\n",[545,2023,2024,2027,2030],{"class":547,"line":720},[545,2025,2026],{"class":584},"                Stores.",[545,2028,2029],{"class":555},"keyValueStoreBuilder",[545,2031,2021],{"class":584},[545,2033,2034,2037,2040,2042,2044],{"class":547,"line":950},[545,2035,2036],{"class":584},"                    Stores.",[545,2038,2039],{"class":555},"persistentKeyValueStore",[545,2041,695],{"class":584},[545,2043,1982],{"class":1407},[545,2045,2046],{"class":584},"),\n",[545,2048,2049,2052,2054],{"class":547,"line":955},[545,2050,2051],{"class":584},"                    Serdes.",[545,2053,593],{"class":555},[545,2055,2056],{"class":584},"(),\n",[545,2058,2059],{"class":547,"line":960},[545,2060,2061],{"class":584},"                    sessionSerde,\n",[545,2063,2065],{"class":547,"line":2064},16,[545,2066,2067],{"class":584},"                ),\n",[545,2069,2071],{"class":547,"line":2070},17,[545,2072,2073],{"class":584},"            )\n",[545,2075,2077],{"class":547,"line":2076},18,[545,2078,717],{"class":584},[545,2080,2082],{"class":547,"line":2081},19,[545,2083,571],{"emptyLinePlaceholder":570},[545,2085,2087,2089,2092,2094,2097,2099,2102,2104,2106,2109],{"class":547,"line":2086},20,[545,2088,1363],{"class":551},[545,2090,2091],{"class":584}," out ",[545,2093,1062],{"class":647},[545,2095,2096],{"class":584}," events.",[545,2098,1310],{"class":555},[545,2100,2101],{"class":584},"(supplier, Named.",[545,2103,1402],{"class":555},[545,2105,695],{"class":584},[545,2107,2108],{"class":1407},"\"sessionize\"",[545,2110,1411],{"class":584},[535,2112,2114],{"className":726,"code":2113,"filename":728,"language":729,"meta":541,"style":541},"import io.stoatflow.core.processor.Processor;\nimport io.stoatflow.core.processor.ProcessorSupplier;\nimport io.stoatflow.core.state.StateStoreBuilder;\nimport io.stoatflow.core.state.Stores;\nimport org.apache.kafka.common.serialization.Serdes;\n\nimport java.util.Set;\n\nProcessorSupplier\u003CString, Event, String, Event> supplier =\n    new ProcessorSupplier\u003C>() {\n        @Override\n        public Processor\u003CString, Event, String, Event> get() {\n            return new SessionProcessor(\"sessions\");\n        }\n\n        @Override\n        public Set\u003CStateStoreBuilder\u003C?>> stores() {\n            return Set.of(\n                Stores.keyValueStoreBuilder(\n                    Stores.persistentKeyValueStore(\"sessions\"),\n                    Serdes.String(),\n                    sessionSerde));\n        }\n    };\n\nKStream\u003CString, Event> out = events.process(supplier, Named.as(\"sessionize\"));\n",[347,2115,2116,2140,2164,2189,2213,2247,2251,2269,2273,2300,2313,2320,2353,2375,2379,2383,2389,2414,2427,2438,2457,2469,2477,2482,2488,2493],{"__ignoreMap":541},[545,2117,2118,2120,2122,2124,2126,2128,2130,2132,2134,2136,2138],{"class":547,"line":548},[545,2119,552],{"class":551},[545,2121,738],{"class":584},[545,2123,334],{"class":647},[545,2125,743],{"class":584},[545,2127,334],{"class":647},[545,2129,748],{"class":584},[545,2131,334],{"class":647},[545,2133,753],{"class":584},[545,2135,334],{"class":647},[545,2137,493],{"class":584},[545,2139,760],{"class":647},[545,2141,2142,2144,2146,2148,2150,2152,2154,2156,2158,2160,2162],{"class":547,"line":559},[545,2143,552],{"class":551},[545,2145,738],{"class":584},[545,2147,334],{"class":647},[545,2149,743],{"class":584},[545,2151,334],{"class":647},[545,2153,748],{"class":584},[545,2155,334],{"class":647},[545,2157,753],{"class":584},[545,2159,334],{"class":647},[545,2161,1940],{"class":584},[545,2163,760],{"class":647},[545,2165,2166,2168,2170,2172,2174,2176,2178,2180,2183,2185,2187],{"class":547,"line":567},[545,2167,552],{"class":551},[545,2169,738],{"class":584},[545,2171,334],{"class":647},[545,2173,743],{"class":584},[545,2175,334],{"class":647},[545,2177,748],{"class":584},[545,2179,334],{"class":647},[545,2181,2182],{"class":584},"state",[545,2184,334],{"class":647},[545,2186,1874],{"class":584},[545,2188,760],{"class":647},[545,2190,2191,2193,2195,2197,2199,2201,2203,2205,2207,2209,2211],{"class":547,"line":574},[545,2192,552],{"class":551},[545,2194,738],{"class":584},[545,2196,334],{"class":647},[545,2198,743],{"class":584},[545,2200,334],{"class":647},[545,2202,748],{"class":584},[545,2204,334],{"class":647},[545,2206,2182],{"class":584},[545,2208,334],{"class":647},[545,2210,1878],{"class":584},[545,2212,760],{"class":647},[545,2214,2215,2217,2220,2222,2225,2227,2230,2232,2235,2237,2240,2242,2245],{"class":547,"line":608},[545,2216,552],{"class":551},[545,2218,2219],{"class":584}," org",[545,2221,334],{"class":647},[545,2223,2224],{"class":584},"apache",[545,2226,334],{"class":647},[545,2228,2229],{"class":584},"kafka",[545,2231,334],{"class":647},[545,2233,2234],{"class":584},"common",[545,2236,334],{"class":647},[545,2238,2239],{"class":584},"serialization",[545,2241,334],{"class":647},[545,2243,2244],{"class":584},"Serdes",[545,2246,760],{"class":647},[545,2248,2249],{"class":547,"line":638},[545,2250,571],{"emptyLinePlaceholder":570},[545,2252,2253,2255,2258,2260,2263,2265,2267],{"class":547,"line":657},[545,2254,552],{"class":551},[545,2256,2257],{"class":584}," java",[545,2259,334],{"class":647},[545,2261,2262],{"class":584},"util",[545,2264,334],{"class":647},[545,2266,2004],{"class":584},[545,2268,760],{"class":647},[545,2270,2271],{"class":547,"line":676},[545,2272,571],{"emptyLinePlaceholder":570},[545,2274,2275,2277,2279,2281,2283,2285,2287,2289,2291,2293,2295,2298],{"class":547,"line":683},[545,2276,1940],{"class":584},[545,2278,590],{"class":647},[545,2280,593],{"class":611},[545,2282,814],{"class":647},[545,2284,1177],{"class":611},[545,2286,814],{"class":647},[545,2288,817],{"class":611},[545,2290,814],{"class":647},[545,2292,1177],{"class":611},[545,2294,824],{"class":647},[545,2296,2297],{"class":866}," supplier",[545,2299,1484],{"class":647},[545,2301,2302,2305,2308,2311],{"class":547,"line":708},[545,2303,2304],{"class":551},"    new",[545,2306,2307],{"class":584}," ProcessorSupplier",[545,2309,2310],{"class":647},"\u003C>()",[545,2312,827],{"class":647},[545,2314,2315,2318],{"class":547,"line":714},[545,2316,2317],{"class":647},"        @",[545,2319,839],{"class":611},[545,2321,2322,2325,2328,2330,2332,2334,2336,2338,2340,2342,2344,2346,2348,2351],{"class":547,"line":720},[545,2323,2324],{"class":611},"        public",[545,2326,2327],{"class":584}," Processor",[545,2329,590],{"class":647},[545,2331,593],{"class":611},[545,2333,814],{"class":647},[545,2335,1177],{"class":611},[545,2337,814],{"class":647},[545,2339,817],{"class":611},[545,2341,814],{"class":647},[545,2343,1177],{"class":611},[545,2345,824],{"class":647},[545,2347,1969],{"class":555},[545,2349,2350],{"class":647},"()",[545,2352,827],{"class":647},[545,2354,2355,2358,2361,2363,2365,2367,2370,2372],{"class":547,"line":950},[545,2356,2357],{"class":551},"            return",[545,2359,2360],{"class":551}," new",[545,2362,1977],{"class":555},[545,2364,695],{"class":647},[545,2366,1516],{"class":1515},[545,2368,2369],{"class":1407},"sessions",[545,2371,1516],{"class":1515},[545,2373,2374],{"class":647},");\n",[545,2376,2377],{"class":547,"line":955},[545,2378,711],{"class":647},[545,2380,2381],{"class":547,"line":960},[545,2382,571],{"emptyLinePlaceholder":570},[545,2384,2385,2387],{"class":547,"line":2064},[545,2386,2317],{"class":647},[545,2388,839],{"class":611},[545,2390,2391,2393,2396,2398,2400,2402,2405,2408,2410,2412],{"class":547,"line":2070},[545,2392,2324],{"class":611},[545,2394,2395],{"class":584}," Set",[545,2397,590],{"class":647},[545,2399,1874],{"class":584},[545,2401,590],{"class":647},[545,2403,2404],{"class":611},"?",[545,2406,2407],{"class":647},">>",[545,2409,1998],{"class":555},[545,2411,2350],{"class":647},[545,2413,827],{"class":647},[545,2415,2416,2418,2420,2422,2425],{"class":547,"line":2076},[545,2417,2357],{"class":551},[545,2419,2395],{"class":866},[545,2421,334],{"class":647},[545,2423,2424],{"class":555},"of",[545,2426,2021],{"class":647},[545,2428,2429,2432,2434,2436],{"class":547,"line":2081},[545,2430,2431],{"class":866},"                Stores",[545,2433,334],{"class":647},[545,2435,2029],{"class":555},[545,2437,2021],{"class":647},[545,2439,2440,2443,2445,2447,2449,2451,2453,2455],{"class":547,"line":2086},[545,2441,2442],{"class":866},"                    Stores",[545,2444,334],{"class":647},[545,2446,2039],{"class":555},[545,2448,695],{"class":647},[545,2450,1516],{"class":1515},[545,2452,2369],{"class":1407},[545,2454,1516],{"class":1515},[545,2456,2046],{"class":647},[545,2458,2460,2463,2465,2467],{"class":547,"line":2459},21,[545,2461,2462],{"class":866},"                    Serdes",[545,2464,334],{"class":647},[545,2466,593],{"class":555},[545,2468,2056],{"class":647},[545,2470,2472,2475],{"class":547,"line":2471},22,[545,2473,2474],{"class":584},"                    sessionSerde",[545,2476,1524],{"class":647},[545,2478,2480],{"class":547,"line":2479},23,[545,2481,711],{"class":647},[545,2483,2485],{"class":547,"line":2484},24,[545,2486,2487],{"class":647},"    };\n",[545,2489,2491],{"class":547,"line":2490},25,[545,2492,571],{"emptyLinePlaceholder":570},[545,2494,2496,2498,2500,2502,2504,2506,2508,2511,2513,2516,2518,2520,2522,2524,2526,2528,2530,2532,2534,2536,2539,2541],{"class":547,"line":2495},26,[545,2497,1369],{"class":584},[545,2499,590],{"class":647},[545,2501,593],{"class":611},[545,2503,814],{"class":647},[545,2505,1177],{"class":611},[545,2507,824],{"class":647},[545,2509,2510],{"class":866}," out",[545,2512,648],{"class":647},[545,2514,2515],{"class":866}," events",[545,2517,334],{"class":647},[545,2519,1310],{"class":555},[545,2521,695],{"class":647},[545,2523,1317],{"class":584},[545,2525,814],{"class":647},[545,2527,1505],{"class":866},[545,2529,334],{"class":647},[545,2531,1510],{"class":555},[545,2533,695],{"class":647},[545,2535,1516],{"class":1515},[545,2537,2538],{"class":1407},"sessionize",[545,2540,1516],{"class":1515},[545,2542,1524],{"class":647},[517,2544,2546],{"id":2545},"option-b-register-on-the-builder","Option B — register on the builder",[320,2548,2549,2550,2553,2554,2557,2558,2560,2561,2564,2565,334],{},"Register the store on the ",[347,2551,2552],{},"StreamsBuilder"," with ",[347,2555,2556],{},"addStateStore(...)",", then refer to it by name from the processor. ",[347,2559,2039],{}," is the recommended store type for production (RocksDB, changelog-backed); ",[347,2562,2563],{},"inMemoryKeyValueStore"," is available for non-durable state. See ",[329,2566,100],{"href":101},[531,2568,2569,2681],{"group":533},[535,2570,2572],{"className":537,"code":2571,"filename":539,"language":540,"meta":541,"style":541},"import io.stoatflow.core.state.Stores\nimport org.apache.kafka.common.serialization.Serdes\n\nbuilder.addStateStore(\n    Stores.keyValueStoreBuilder(\n        Stores.persistentKeyValueStore(\"sessions\"),\n        Serdes.String(),\n        sessionSerde,\n    ),\n)\n\nval out = events.process({ SessionProcessor(\"sessions\") }, Named.`as`(\"sessionize\"))\n",[347,2573,2574,2580,2586,2590,2600,2609,2622,2631,2636,2641,2645,2649],{"__ignoreMap":541},[545,2575,2576,2578],{"class":547,"line":548},[545,2577,552],{"class":551},[545,2579,1910],{"class":555},[545,2581,2582,2584],{"class":547,"line":559},[545,2583,552],{"class":551},[545,2585,1917],{"class":555},[545,2587,2588],{"class":547,"line":567},[545,2589,571],{"emptyLinePlaceholder":570},[545,2591,2592,2595,2598],{"class":547,"line":574},[545,2593,2594],{"class":584},"builder.",[545,2596,2597],{"class":555},"addStateStore",[545,2599,2021],{"class":584},[545,2601,2602,2605,2607],{"class":547,"line":608},[545,2603,2604],{"class":584},"    Stores.",[545,2606,2029],{"class":555},[545,2608,2021],{"class":584},[545,2610,2611,2614,2616,2618,2620],{"class":547,"line":638},[545,2612,2613],{"class":584},"        Stores.",[545,2615,2039],{"class":555},[545,2617,695],{"class":584},[545,2619,1982],{"class":1407},[545,2621,2046],{"class":584},[545,2623,2624,2627,2629],{"class":547,"line":657},[545,2625,2626],{"class":584},"        Serdes.",[545,2628,593],{"class":555},[545,2630,2056],{"class":584},[545,2632,2633],{"class":547,"line":676},[545,2634,2635],{"class":584},"        sessionSerde,\n",[545,2637,2638],{"class":547,"line":683},[545,2639,2640],{"class":584},"    ),\n",[545,2642,2643],{"class":547,"line":708},[545,2644,1985],{"class":584},[545,2646,2647],{"class":547,"line":714},[545,2648,571],{"emptyLinePlaceholder":570},[545,2650,2651,2653,2655,2657,2659,2661,2663,2666,2668,2670,2673,2675,2677,2679],{"class":547,"line":720},[545,2652,1363],{"class":551},[545,2654,2091],{"class":584},[545,2656,1062],{"class":647},[545,2658,2096],{"class":584},[545,2660,1310],{"class":555},[545,2662,1393],{"class":584},[545,2664,2665],{"class":555},"SessionProcessor",[545,2667,695],{"class":584},[545,2669,1982],{"class":1407},[545,2671,2672],{"class":584},") }, Named.",[545,2674,1402],{"class":555},[545,2676,695],{"class":584},[545,2678,2108],{"class":1407},[545,2680,1411],{"class":584},[535,2682,2684],{"className":726,"code":2683,"filename":728,"language":729,"meta":541,"style":541},"import io.stoatflow.core.state.Stores;\nimport org.apache.kafka.common.serialization.Serdes;\n\nbuilder.addStateStore(Stores.keyValueStoreBuilder(\n    Stores.persistentKeyValueStore(\"sessions\"),\n    Serdes.String(),\n    sessionSerde));\n\nKStream\u003CString, Event> out =\n    events.process(() -> new SessionProcessor(\"sessions\"), Named.as(\"sessionize\"));\n",[347,2685,2686,2710,2738,2742,2761,2780,2791,2798,2802,2820],{"__ignoreMap":541},[545,2687,2688,2690,2692,2694,2696,2698,2700,2702,2704,2706,2708],{"class":547,"line":548},[545,2689,552],{"class":551},[545,2691,738],{"class":584},[545,2693,334],{"class":647},[545,2695,743],{"class":584},[545,2697,334],{"class":647},[545,2699,748],{"class":584},[545,2701,334],{"class":647},[545,2703,2182],{"class":584},[545,2705,334],{"class":647},[545,2707,1878],{"class":584},[545,2709,760],{"class":647},[545,2711,2712,2714,2716,2718,2720,2722,2724,2726,2728,2730,2732,2734,2736],{"class":547,"line":559},[545,2713,552],{"class":551},[545,2715,2219],{"class":584},[545,2717,334],{"class":647},[545,2719,2224],{"class":584},[545,2721,334],{"class":647},[545,2723,2229],{"class":584},[545,2725,334],{"class":647},[545,2727,2234],{"class":584},[545,2729,334],{"class":647},[545,2731,2239],{"class":584},[545,2733,334],{"class":647},[545,2735,2244],{"class":584},[545,2737,760],{"class":647},[545,2739,2740],{"class":547,"line":567},[545,2741,571],{"emptyLinePlaceholder":570},[545,2743,2744,2747,2749,2751,2753,2755,2757,2759],{"class":547,"line":574},[545,2745,2746],{"class":866},"builder",[545,2748,334],{"class":647},[545,2750,2597],{"class":555},[545,2752,695],{"class":647},[545,2754,1878],{"class":866},[545,2756,334],{"class":647},[545,2758,2029],{"class":555},[545,2760,2021],{"class":647},[545,2762,2763,2766,2768,2770,2772,2774,2776,2778],{"class":547,"line":608},[545,2764,2765],{"class":866},"    Stores",[545,2767,334],{"class":647},[545,2769,2039],{"class":555},[545,2771,695],{"class":647},[545,2773,1516],{"class":1515},[545,2775,2369],{"class":1407},[545,2777,1516],{"class":1515},[545,2779,2046],{"class":647},[545,2781,2782,2785,2787,2789],{"class":547,"line":638},[545,2783,2784],{"class":866},"    Serdes",[545,2786,334],{"class":647},[545,2788,593],{"class":555},[545,2790,2056],{"class":647},[545,2792,2793,2796],{"class":547,"line":657},[545,2794,2795],{"class":584},"    sessionSerde",[545,2797,1524],{"class":647},[545,2799,2800],{"class":547,"line":676},[545,2801,571],{"emptyLinePlaceholder":570},[545,2803,2804,2806,2808,2810,2812,2814,2816,2818],{"class":547,"line":683},[545,2805,1369],{"class":584},[545,2807,590],{"class":647},[545,2809,593],{"class":611},[545,2811,814],{"class":647},[545,2813,1177],{"class":611},[545,2815,824],{"class":647},[545,2817,2510],{"class":866},[545,2819,1484],{"class":647},[545,2821,2822,2824,2826,2828,2831,2834,2836,2838,2840,2842,2844,2846,2849,2851,2853,2855,2857,2859,2861,2863],{"class":547,"line":708},[545,2823,1489],{"class":866},[545,2825,334],{"class":647},[545,2827,1310],{"class":555},[545,2829,2830],{"class":647},"(()",[545,2832,2833],{"class":647}," ->",[545,2835,2360],{"class":551},[545,2837,1977],{"class":555},[545,2839,695],{"class":647},[545,2841,1516],{"class":1515},[545,2843,2369],{"class":1407},[545,2845,1516],{"class":1515},[545,2847,2848],{"class":647},"),",[545,2850,1505],{"class":866},[545,2852,334],{"class":647},[545,2854,1510],{"class":555},[545,2856,695],{"class":647},[545,2858,1516],{"class":1515},[545,2860,2538],{"class":1407},[545,2862,1516],{"class":1515},[545,2864,1524],{"class":647},[517,2866,2868],{"id":2867},"reading-and-writing-the-store","Reading and writing the store",[320,2870,2871,2872,2874,2875,2877,2878,2881,2882,2885],{},"Look up the store in ",[347,2873,515],{},", then use it in ",[347,2876,1310],{}," (and ",[347,2879,2880],{},"onTimer","). ",[347,2883,2884],{},"getStateStore"," is generic over the store type; in Kotlin pass the type argument, in Java assign to a typed variable.",[531,2887,2888,3131],{"group":533},[535,2889,2891],{"className":537,"code":2890,"filename":539,"language":540,"meta":541,"style":541},"import io.stoatflow.core.processor.ContextualProcessor\nimport io.stoatflow.core.processor.ProcessorContext\nimport io.stoatflow.core.processor.Record\nimport io.stoatflow.core.state.KeyValueStore\n\nclass CountingProcessor : ContextualProcessor\u003CString, String, String, Long>() {\n    private lateinit var counts: KeyValueStore\u003CString, Long>\n\n    override fun init(context: ProcessorContext\u003CString, Long>) {\n        super.init(context)\n        counts = context.getStateStore(\"counts\")\n    }\n\n    override fun process(record: Record\u003CString, String>) {\n        val next = (counts.get(record.key) ?: 0L) + 1\n        counts.put(record.key, next)\n        context().forward(record.key, next)\n    }\n}\n",[347,2892,2893,2899,2906,2912,2919,2923,2953,2981,2985,3009,3022,3041,3045,3049,3071,3102,3113,3123,3127],{"__ignoreMap":541},[545,2894,2895,2897],{"class":547,"line":548},[545,2896,552],{"class":551},[545,2898,988],{"class":555},[545,2900,2901,2903],{"class":547,"line":559},[545,2902,552],{"class":551},[545,2904,2905],{"class":555}," io.stoatflow.core.processor.ProcessorContext\n",[545,2907,2908,2910],{"class":547,"line":567},[545,2909,552],{"class":551},[545,2911,995],{"class":555},[545,2913,2914,2916],{"class":547,"line":574},[545,2915,552],{"class":551},[545,2917,2918],{"class":555}," io.stoatflow.core.state.KeyValueStore\n",[545,2920,2921],{"class":547,"line":608},[545,2922,571],{"emptyLinePlaceholder":570},[545,2924,2925,2927,2930,2932,2934,2936,2938,2940,2942,2944,2946,2948,2951],{"class":547,"line":638},[545,2926,577],{"class":551},[545,2928,2929],{"class":580}," CountingProcessor",[545,2931,585],{"class":584},[545,2933,504],{"class":580},[545,2935,590],{"class":584},[545,2937,593],{"class":580},[545,2939,596],{"class":584},[545,2941,593],{"class":580},[545,2943,596],{"class":584},[545,2945,593],{"class":580},[545,2947,596],{"class":584},[545,2949,2950],{"class":580},"Long",[545,2952,605],{"class":584},[545,2954,2955,2958,2961,2964,2967,2970,2972,2974,2976,2978],{"class":547,"line":657},[545,2956,2957],{"class":611},"    private",[545,2959,2960],{"class":611}," lateinit",[545,2962,2963],{"class":551}," var",[545,2965,2966],{"class":584}," counts: ",[545,2968,2969],{"class":580},"KeyValueStore",[545,2971,590],{"class":584},[545,2973,593],{"class":580},[545,2975,596],{"class":584},[545,2977,2950],{"class":580},[545,2979,2980],{"class":584},">\n",[545,2982,2983],{"class":547,"line":676},[545,2984,571],{"emptyLinePlaceholder":570},[545,2986,2987,2989,2991,2994,2997,2999,3001,3003,3005,3007],{"class":547,"line":683},[545,2988,612],{"class":611},[545,2990,615],{"class":551},[545,2992,2993],{"class":555}," init",[545,2995,2996],{"class":584},"(context: ",[545,2998,373],{"class":580},[545,3000,590],{"class":584},[545,3002,593],{"class":580},[545,3004,596],{"class":584},[545,3006,2950],{"class":580},[545,3008,635],{"class":584},[545,3010,3011,3015,3017,3019],{"class":547,"line":708},[545,3012,3014],{"class":3013},"sEi1f","        super",[545,3016,334],{"class":584},[545,3018,515],{"class":555},[545,3020,3021],{"class":584},"(context)\n",[545,3023,3024,3027,3029,3032,3034,3036,3039],{"class":547,"line":714},[545,3025,3026],{"class":584},"        counts ",[545,3028,1062],{"class":647},[545,3030,3031],{"class":584}," context.",[545,3033,2884],{"class":555},[545,3035,695],{"class":584},[545,3037,3038],{"class":1407},"\"counts\"",[545,3040,1985],{"class":584},[545,3042,3043],{"class":547,"line":720},[545,3044,717],{"class":584},[545,3046,3047],{"class":547,"line":950},[545,3048,571],{"emptyLinePlaceholder":570},[545,3050,3051,3053,3055,3057,3059,3061,3063,3065,3067,3069],{"class":547,"line":955},[545,3052,612],{"class":611},[545,3054,615],{"class":551},[545,3056,618],{"class":555},[545,3058,621],{"class":584},[545,3060,1042],{"class":580},[545,3062,590],{"class":584},[545,3064,593],{"class":580},[545,3066,596],{"class":584},[545,3068,593],{"class":580},[545,3070,635],{"class":584},[545,3072,3073,3075,3078,3080,3083,3086,3089,3093,3096,3099],{"class":547,"line":960},[545,3074,641],{"class":551},[545,3076,3077],{"class":584}," next ",[545,3079,1062],{"class":647},[545,3081,3082],{"class":584}," (counts.",[545,3084,3085],{"class":555},"get",[545,3087,3088],{"class":584},"(record.key) ?: ",[545,3090,3092],{"class":3091},"s-TwI","0L",[545,3094,3095],{"class":584},") ",[545,3097,3098],{"class":611},"+",[545,3100,3101],{"class":3091}," 1\n",[545,3103,3104,3107,3110],{"class":547,"line":2064},[545,3105,3106],{"class":584},"        counts.",[545,3108,3109],{"class":555},"put",[545,3111,3112],{"class":584},"(record.key, next)\n",[545,3114,3115,3117,3119,3121],{"class":547,"line":2070},[545,3116,1076],{"class":555},[545,3118,689],{"class":584},[545,3120,692],{"class":555},[545,3122,3112],{"class":584},[545,3124,3125],{"class":547,"line":2076},[545,3126,717],{"class":584},[545,3128,3129],{"class":547,"line":2081},[545,3130,723],{"class":584},[535,3132,3134],{"className":726,"code":3133,"filename":728,"language":729,"meta":541,"style":541},"import io.stoatflow.core.processor.ContextualProcessor;\nimport io.stoatflow.core.processor.ProcessorContext;\nimport io.stoatflow.core.processor.Record;\nimport io.stoatflow.core.state.KeyValueStore;\n\npublic class CountingProcessor\n        extends ContextualProcessor\u003CString, String, String, Long> {\n\n    private KeyValueStore\u003CString, Long> counts;\n\n    @Override\n    public void init(ProcessorContext\u003CString, Long> context) {\n        super.init(context);\n        this.counts = context.getStateStore(\"counts\");\n    }\n\n    @Override\n    public void process(Record\u003CString, String> record) {\n        long current = counts.get(record.key()) == null ? 0L : counts.get(record.key());\n        long next = current + 1;\n        counts.put(record.key(), next);\n        context().forward(record.key(), next);\n    }\n}\n",[347,3135,3136,3160,3184,3208,3232,3236,3245,3272,3276,3298,3302,3308,3337,3352,3380,3384,3388,3394,3422,3480,3499,3522,3544,3548],{"__ignoreMap":541},[545,3137,3138,3140,3142,3144,3146,3148,3150,3152,3154,3156,3158],{"class":547,"line":548},[545,3139,552],{"class":551},[545,3141,738],{"class":584},[545,3143,334],{"class":647},[545,3145,743],{"class":584},[545,3147,334],{"class":647},[545,3149,748],{"class":584},[545,3151,334],{"class":647},[545,3153,753],{"class":584},[545,3155,334],{"class":647},[545,3157,504],{"class":584},[545,3159,760],{"class":647},[545,3161,3162,3164,3166,3168,3170,3172,3174,3176,3178,3180,3182],{"class":547,"line":559},[545,3163,552],{"class":551},[545,3165,738],{"class":584},[545,3167,334],{"class":647},[545,3169,743],{"class":584},[545,3171,334],{"class":647},[545,3173,748],{"class":584},[545,3175,334],{"class":647},[545,3177,753],{"class":584},[545,3179,334],{"class":647},[545,3181,373],{"class":584},[545,3183,760],{"class":647},[545,3185,3186,3188,3190,3192,3194,3196,3198,3200,3202,3204,3206],{"class":547,"line":567},[545,3187,552],{"class":551},[545,3189,738],{"class":584},[545,3191,334],{"class":647},[545,3193,743],{"class":584},[545,3195,334],{"class":647},[545,3197,748],{"class":584},[545,3199,334],{"class":647},[545,3201,753],{"class":584},[545,3203,334],{"class":647},[545,3205,1042],{"class":584},[545,3207,760],{"class":647},[545,3209,3210,3212,3214,3216,3218,3220,3222,3224,3226,3228,3230],{"class":547,"line":574},[545,3211,552],{"class":551},[545,3213,738],{"class":584},[545,3215,334],{"class":647},[545,3217,743],{"class":584},[545,3219,334],{"class":647},[545,3221,748],{"class":584},[545,3223,334],{"class":647},[545,3225,2182],{"class":584},[545,3227,334],{"class":647},[545,3229,2969],{"class":584},[545,3231,760],{"class":647},[545,3233,3234],{"class":547,"line":608},[545,3235,571],{"emptyLinePlaceholder":570},[545,3237,3238,3240,3242],{"class":547,"line":638},[545,3239,793],{"class":611},[545,3241,796],{"class":611},[545,3243,3244],{"class":580}," CountingProcessor\n",[545,3246,3247,3249,3251,3253,3255,3257,3259,3261,3263,3265,3268,3270],{"class":547,"line":657},[545,3248,804],{"class":611},[545,3250,1168],{"class":555},[545,3252,590],{"class":647},[545,3254,593],{"class":611},[545,3256,814],{"class":647},[545,3258,817],{"class":611},[545,3260,814],{"class":647},[545,3262,817],{"class":611},[545,3264,814],{"class":647},[545,3266,3267],{"class":611}," Long",[545,3269,824],{"class":647},[545,3271,827],{"class":647},[545,3273,3274],{"class":547,"line":676},[545,3275,571],{"emptyLinePlaceholder":570},[545,3277,3278,3280,3283,3285,3287,3289,3291,3293,3296],{"class":547,"line":683},[545,3279,2957],{"class":611},[545,3281,3282],{"class":584}," KeyValueStore",[545,3284,590],{"class":647},[545,3286,593],{"class":611},[545,3288,814],{"class":647},[545,3290,3267],{"class":611},[545,3292,824],{"class":647},[545,3294,3295],{"class":866}," counts",[545,3297,760],{"class":647},[545,3299,3300],{"class":547,"line":708},[545,3301,571],{"emptyLinePlaceholder":570},[545,3303,3304,3306],{"class":547,"line":714},[545,3305,836],{"class":647},[545,3307,839],{"class":611},[545,3309,3310,3312,3314,3316,3318,3320,3322,3324,3326,3328,3330,3333,3335],{"class":547,"line":720},[545,3311,844],{"class":611},[545,3313,847],{"class":611},[545,3315,2993],{"class":555},[545,3317,695],{"class":647},[545,3319,373],{"class":584},[545,3321,590],{"class":647},[545,3323,593],{"class":611},[545,3325,814],{"class":647},[545,3327,3267],{"class":611},[545,3329,824],{"class":647},[545,3331,3332],{"class":866}," context",[545,3334,870],{"class":647},[545,3336,827],{"class":647},[545,3338,3339,3341,3343,3345,3347,3350],{"class":547,"line":950},[545,3340,3014],{"class":3013},[545,3342,334],{"class":647},[545,3344,515],{"class":555},[545,3346,695],{"class":647},[545,3348,3349],{"class":584},"context",[545,3351,2374],{"class":647},[545,3353,3354,3357,3359,3362,3364,3366,3368,3370,3372,3374,3376,3378],{"class":547,"line":955},[545,3355,3356],{"class":3013},"        this",[545,3358,334],{"class":647},[545,3360,3361],{"class":866},"counts",[545,3363,648],{"class":647},[545,3365,3332],{"class":866},[545,3367,334],{"class":647},[545,3369,2884],{"class":555},[545,3371,695],{"class":647},[545,3373,1516],{"class":1515},[545,3375,3361],{"class":1407},[545,3377,1516],{"class":1515},[545,3379,2374],{"class":647},[545,3381,3382],{"class":547,"line":960},[545,3383,717],{"class":647},[545,3385,3386],{"class":547,"line":2064},[545,3387,571],{"emptyLinePlaceholder":570},[545,3389,3390,3392],{"class":547,"line":2070},[545,3391,836],{"class":647},[545,3393,839],{"class":611},[545,3395,3396,3398,3400,3402,3404,3406,3408,3410,3412,3414,3416,3418,3420],{"class":547,"line":2076},[545,3397,844],{"class":611},[545,3399,847],{"class":611},[545,3401,618],{"class":555},[545,3403,695],{"class":647},[545,3405,1042],{"class":584},[545,3407,590],{"class":647},[545,3409,593],{"class":611},[545,3411,814],{"class":647},[545,3413,817],{"class":611},[545,3415,824],{"class":647},[545,3417,867],{"class":866},[545,3419,870],{"class":647},[545,3421,827],{"class":647},[545,3423,3424,3427,3430,3432,3434,3436,3438,3440,3443,3445,3448,3450,3453,3455,3458,3461,3464,3466,3468,3470,3472,3474,3476,3478],{"class":547,"line":2081},[545,3425,3426],{"class":611},"        long",[545,3428,3429],{"class":866}," current",[545,3431,648],{"class":647},[545,3433,3295],{"class":866},[545,3435,334],{"class":647},[545,3437,3085],{"class":555},[545,3439,695],{"class":647},[545,3441,3442],{"class":866},"record",[545,3444,334],{"class":647},[545,3446,3447],{"class":555},"key",[545,3449,921],{"class":647},[545,3451,3452],{"class":611}," ==",[545,3454,905],{"class":551},[545,3456,3457],{"class":551}," ?",[545,3459,3460],{"class":3091}," 0L",[545,3462,3463],{"class":551}," :",[545,3465,3295],{"class":866},[545,3467,334],{"class":647},[545,3469,3085],{"class":555},[545,3471,695],{"class":647},[545,3473,3442],{"class":866},[545,3475,334],{"class":647},[545,3477,3447],{"class":555},[545,3479,947],{"class":647},[545,3481,3482,3484,3487,3489,3492,3494,3497],{"class":547,"line":2086},[545,3483,3426],{"class":611},[545,3485,3486],{"class":866}," next",[545,3488,648],{"class":647},[545,3490,3491],{"class":584}," current ",[545,3493,3098],{"class":611},[545,3495,3496],{"class":3091}," 1",[545,3498,760],{"class":647},[545,3500,3501,3504,3506,3508,3510,3512,3514,3516,3518,3520],{"class":547,"line":2459},[545,3502,3503],{"class":866},"        counts",[545,3505,334],{"class":647},[545,3507,3109],{"class":555},[545,3509,695],{"class":647},[545,3511,3442],{"class":866},[545,3513,334],{"class":647},[545,3515,3447],{"class":555},[545,3517,1279],{"class":647},[545,3519,3486],{"class":584},[545,3521,2374],{"class":647},[545,3523,3524,3526,3528,3530,3532,3534,3536,3538,3540,3542],{"class":547,"line":2471},[545,3525,1076],{"class":555},[545,3527,689],{"class":647},[545,3529,692],{"class":555},[545,3531,695],{"class":647},[545,3533,3442],{"class":866},[545,3535,334],{"class":647},[545,3537,3447],{"class":555},[545,3539,1279],{"class":647},[545,3541,3486],{"class":584},[545,3543,2374],{"class":647},[545,3545,3546],{"class":547,"line":2479},[545,3547,717],{"class":647},[545,3549,3550],{"class":547,"line":2484},[545,3551,723],{"class":647},[418,3553,389],{"id":3554},"punctuators",[320,3556,3557,3558,3561,3562,370,3564,3566,3567,3570,3571,364],{},"A ",[324,3559,3560],{},"punctuator"," is a callback that runs periodically — useful for heartbeats, metrics, or flushing buffered state. Schedule one in ",[347,3563,515],{},[347,3565,393],{},". It returns a ",[347,3568,3569],{},"Cancellable"," you can use to stop it (for example in ",[347,3572,3573],{},"close()",[320,3575,3576,3579,3580,3583,3584,3587],{},[347,3577,3578],{},"schedule"," takes an interval, a ",[347,3581,3582],{},"TimeNotion",", an optional ",[347,3585,3586],{},"PunctuatorMode",", and the callback. The callback receives the trigger timestamp.",[517,3589,3591],{"id":3590},"time-notion","Time notion",[320,3593,3594,3596,3597,3600],{},[347,3595,3582],{}," is the same type used for timers and ",[347,3598,3599],{},"StreamsBuilder.scheduled(...)",". It carries both StoatFlow\u002FKafka-Streams and Flink naming for the same two concepts:",[426,3602,3603,3619],{},[429,3604,3605],{},[432,3606,3607,3610,3613,3616],{},[435,3608,3609],{},"Constant",[435,3611,3612],{},"Alias",[435,3614,3615],{},"Fires when",[435,3617,3618],{},"Timestamp passed",[447,3620,3621,3639],{},[432,3622,3623,3628,3633,3636],{},[452,3624,3625],{},[347,3626,3627],{},"TimeNotion.STREAM_TIME",[452,3629,3630],{},[347,3631,3632],{},"EVENT_TIME",[452,3634,3635],{},"the watermark advances past the next interval",[452,3637,3638],{},"the current watermark",[432,3640,3641,3646,3651,3654],{},[452,3642,3643],{},[347,3644,3645],{},"TimeNotion.WALL_CLOCK_TIME",[452,3647,3648],{},[347,3649,3650],{},"PROCESSING_TIME",[452,3652,3653],{},"system time reaches the next interval",[452,3655,3656],{},"the current system time",[320,3658,3659,3660,3663,3664,374,3667,331,3670,3673,3674,374,3676,3678,3679,3681],{},"From Java, the ",[347,3661,3662],{},"PunctuationType"," object exposes ",[347,3665,3666],{},"STREAM_TIME",[347,3668,3669],{},"WALL_CLOCK_TIME",[347,3671,3672],{},"TimeDomain"," exposes ",[347,3675,3632],{},[347,3677,3650],{}," — both resolve to the same ",[347,3680,3582],{}," constants.",[517,3683,3685],{"id":3684},"punctuator-mode","Punctuator mode",[320,3687,3688,3690],{},[347,3689,3586],{}," controls how a punctuator interacts with commit barriers:",[426,3692,3693,3702],{},[429,3694,3695],{},[432,3696,3697,3700],{},[435,3698,3699],{},"Mode",[435,3701,1634],{},[447,3703,3704,3715],{},[432,3705,3706,3712],{},[452,3707,3708,3711],{},[347,3709,3710],{},"BLOCKING"," (default)",[452,3713,3714],{},"The next commit waits for the punctuator to finish; records it forwards commit atomically with that barrier. Strong consistency, higher latency.",[432,3716,3717,3722],{},[452,3718,3719],{},[347,3720,3721],{},"NON_BLOCKING",[452,3723,3724],{},"The punctuator runs asynchronously; records it forwards join whichever barrier is active when they're enqueued. Lower latency, no atomicity guarantee across the run. Best for fire-and-forget work (monitoring, metrics).",[1582,3726,3728],{"color":3727,"icon":80},"warning",[320,3729,3730,3731,3734,3735,3738,3739,3742,3743,3745,3746,3748],{},"Punctuators execute on a dedicated ",[324,3732,3733],{},"punctuation lane"," per sub-topology (not on the per-key record lanes), with full state-store access in an epoch-aligned context. Because they run concurrently with the record lanes, a punctuator's read-modify-write on a key is ",[324,3736,3737],{},"not"," serialized against that key's record processing. For per-key mutations on a time trigger, prefer a ",[324,3740,3741],{},"timer"," (next section), whose ",[347,3744,2880],{}," callback runs in the same per-key serialized context as ",[347,3747,1832],{},". Each punctuator also has locked-run semantics: if a run is still in progress when the next interval fires, that trigger is skipped.",[517,3750,3752],{"id":3751},"example","Example",[531,3754,3755,4042],{"group":533},[535,3756,3758],{"className":537,"code":3757,"filename":539,"language":540,"meta":541,"style":541},"import io.stoatflow.core.processor.Cancellable\nimport io.stoatflow.core.processor.ContextualProcessor\nimport io.stoatflow.core.processor.ProcessorContext\nimport io.stoatflow.core.processor.PunctuatorMode\nimport io.stoatflow.core.processor.Record\nimport io.stoatflow.core.processor.TimeNotion\nimport java.time.Duration\n\nclass HeartbeatProcessor : ContextualProcessor\u003CString, Int, String, Int>() {\n    private var schedule: Cancellable? = null\n\n    override fun init(context: ProcessorContext\u003CString, Int>) {\n        super.init(context)\n        \u002F\u002F wall-clock heartbeat every 10 seconds\n        schedule =\n            context.schedule(Duration.ofSeconds(10), TimeNotion.WALL_CLOCK_TIME) { ts ->\n                context.forward(\"heartbeat\", ts.toInt())\n            }\n    }\n\n    override fun process(record: Record\u003CString, Int>) {\n        context().forward(record.key, record.value)\n    }\n\n    override fun close() {\n        schedule?.cancel()\n    }\n}\n",[347,3759,3760,3767,3773,3779,3786,3792,3799,3806,3810,3840,3859,3863,3885,3895,3900,3907,3931,3951,3956,3960,3964,3986,4001,4005,4009,4021,4032,4037],{"__ignoreMap":541},[545,3761,3762,3764],{"class":547,"line":548},[545,3763,552],{"class":551},[545,3765,3766],{"class":555}," io.stoatflow.core.processor.Cancellable\n",[545,3768,3769,3771],{"class":547,"line":559},[545,3770,552],{"class":551},[545,3772,988],{"class":555},[545,3774,3775,3777],{"class":547,"line":567},[545,3776,552],{"class":551},[545,3778,2905],{"class":555},[545,3780,3781,3783],{"class":547,"line":574},[545,3782,552],{"class":551},[545,3784,3785],{"class":555}," io.stoatflow.core.processor.PunctuatorMode\n",[545,3787,3788,3790],{"class":547,"line":608},[545,3789,552],{"class":551},[545,3791,995],{"class":555},[545,3793,3794,3796],{"class":547,"line":638},[545,3795,552],{"class":551},[545,3797,3798],{"class":555}," io.stoatflow.core.processor.TimeNotion\n",[545,3800,3801,3803],{"class":547,"line":657},[545,3802,552],{"class":551},[545,3804,3805],{"class":555}," java.time.Duration\n",[545,3807,3808],{"class":547,"line":676},[545,3809,571],{"emptyLinePlaceholder":570},[545,3811,3812,3814,3817,3819,3821,3823,3825,3827,3830,3832,3834,3836,3838],{"class":547,"line":683},[545,3813,577],{"class":551},[545,3815,3816],{"class":580}," HeartbeatProcessor",[545,3818,585],{"class":584},[545,3820,504],{"class":580},[545,3822,590],{"class":584},[545,3824,593],{"class":580},[545,3826,596],{"class":584},[545,3828,3829],{"class":580},"Int",[545,3831,596],{"class":584},[545,3833,593],{"class":580},[545,3835,596],{"class":584},[545,3837,3829],{"class":580},[545,3839,605],{"class":584},[545,3841,3842,3844,3846,3849,3851,3854,3856],{"class":547,"line":708},[545,3843,2957],{"class":611},[545,3845,2963],{"class":551},[545,3847,3848],{"class":584}," schedule: ",[545,3850,3569],{"class":580},[545,3852,3853],{"class":584},"? ",[545,3855,1062],{"class":647},[545,3857,3858],{"class":611}," null\n",[545,3860,3861],{"class":547,"line":714},[545,3862,571],{"emptyLinePlaceholder":570},[545,3864,3865,3867,3869,3871,3873,3875,3877,3879,3881,3883],{"class":547,"line":720},[545,3866,612],{"class":611},[545,3868,615],{"class":551},[545,3870,2993],{"class":555},[545,3872,2996],{"class":584},[545,3874,373],{"class":580},[545,3876,590],{"class":584},[545,3878,593],{"class":580},[545,3880,596],{"class":584},[545,3882,3829],{"class":580},[545,3884,635],{"class":584},[545,3886,3887,3889,3891,3893],{"class":547,"line":950},[545,3888,3014],{"class":3013},[545,3890,334],{"class":584},[545,3892,515],{"class":555},[545,3894,3021],{"class":584},[545,3896,3897],{"class":547,"line":955},[545,3898,3899],{"class":679},"        \u002F\u002F wall-clock heartbeat every 10 seconds\n",[545,3901,3902,3905],{"class":547,"line":960},[545,3903,3904],{"class":584},"        schedule ",[545,3906,1383],{"class":647},[545,3908,3909,3912,3914,3917,3920,3922,3925,3928],{"class":547,"line":2064},[545,3910,3911],{"class":584},"            context.",[545,3913,3578],{"class":555},[545,3915,3916],{"class":584},"(Duration.",[545,3918,3919],{"class":555},"ofSeconds",[545,3921,695],{"class":584},[545,3923,3924],{"class":3091},"10",[545,3926,3927],{"class":584},"), TimeNotion.WALL_CLOCK_TIME) { ts ",[545,3929,3930],{"class":647},"->\n",[545,3932,3933,3936,3938,3940,3943,3946,3949],{"class":547,"line":2070},[545,3934,3935],{"class":584},"                context.",[545,3937,692],{"class":555},[545,3939,695],{"class":584},[545,3941,3942],{"class":1407},"\"heartbeat\"",[545,3944,3945],{"class":584},", ts.",[545,3947,3948],{"class":555},"toInt",[545,3950,705],{"class":584},[545,3952,3953],{"class":547,"line":2076},[545,3954,3955],{"class":584},"            }\n",[545,3957,3958],{"class":547,"line":2081},[545,3959,717],{"class":584},[545,3961,3962],{"class":547,"line":2086},[545,3963,571],{"emptyLinePlaceholder":570},[545,3965,3966,3968,3970,3972,3974,3976,3978,3980,3982,3984],{"class":547,"line":2459},[545,3967,612],{"class":611},[545,3969,615],{"class":551},[545,3971,618],{"class":555},[545,3973,621],{"class":584},[545,3975,1042],{"class":580},[545,3977,590],{"class":584},[545,3979,593],{"class":580},[545,3981,596],{"class":584},[545,3983,3829],{"class":580},[545,3985,635],{"class":584},[545,3987,3988,3990,3992,3994,3997,3999],{"class":547,"line":2471},[545,3989,1076],{"class":555},[545,3991,689],{"class":584},[545,3993,692],{"class":555},[545,3995,3996],{"class":584},"(record.key, record.",[545,3998,665],{"class":611},[545,4000,1985],{"class":584},[545,4002,4003],{"class":547,"line":2479},[545,4004,717],{"class":584},[545,4006,4007],{"class":547,"line":2484},[545,4008,571],{"emptyLinePlaceholder":570},[545,4010,4011,4013,4015,4018],{"class":547,"line":2490},[545,4012,612],{"class":611},[545,4014,615],{"class":551},[545,4016,4017],{"class":555}," close",[545,4019,4020],{"class":584},"() {\n",[545,4022,4023,4026,4029],{"class":547,"line":2495},[545,4024,4025],{"class":584},"        schedule?.",[545,4027,4028],{"class":555},"cancel",[545,4030,4031],{"class":584},"()\n",[545,4033,4035],{"class":547,"line":4034},27,[545,4036,717],{"class":584},[545,4038,4040],{"class":547,"line":4039},28,[545,4041,723],{"class":584},[535,4043,4045],{"className":726,"code":4044,"filename":728,"language":729,"meta":541,"style":541},"import io.stoatflow.core.processor.Cancellable;\nimport io.stoatflow.core.processor.ContextualProcessor;\nimport io.stoatflow.core.processor.ProcessorContext;\nimport io.stoatflow.core.processor.PunctuationType;\nimport io.stoatflow.core.processor.Record;\nimport java.time.Duration;\n\npublic class HeartbeatProcessor\n        extends ContextualProcessor\u003CString, Integer, String, Integer> {\n\n    private Cancellable schedule;\n\n    @Override\n    public void init(ProcessorContext\u003CString, Integer> context) {\n        super.init(context);\n        \u002F\u002F wall-clock heartbeat every 10 seconds\n        this.schedule = context.schedule(\n            Duration.ofSeconds(10),\n            PunctuationType.WALL_CLOCK_TIME,\n            ts -> context.forward(\"heartbeat\", (int) ts));\n    }\n\n    @Override\n    public void process(Record\u003CString, Integer> record) {\n        context().forward(record.key(), record.value());\n    }\n\n    @Override\n    public void close() {\n        if (schedule != null) {\n            schedule.cancel();\n        }\n    }\n}\n",[347,4046,4047,4071,4095,4119,4143,4167,4185,4189,4198,4225,4229,4241,4245,4251,4279,4293,4297,4315,4330,4342,4379,4383,4387,4393,4421,4447,4451,4455,4461,4474,4492,4504,4509,4514],{"__ignoreMap":541},[545,4048,4049,4051,4053,4055,4057,4059,4061,4063,4065,4067,4069],{"class":547,"line":548},[545,4050,552],{"class":551},[545,4052,738],{"class":584},[545,4054,334],{"class":647},[545,4056,743],{"class":584},[545,4058,334],{"class":647},[545,4060,748],{"class":584},[545,4062,334],{"class":647},[545,4064,753],{"class":584},[545,4066,334],{"class":647},[545,4068,3569],{"class":584},[545,4070,760],{"class":647},[545,4072,4073,4075,4077,4079,4081,4083,4085,4087,4089,4091,4093],{"class":547,"line":559},[545,4074,552],{"class":551},[545,4076,738],{"class":584},[545,4078,334],{"class":647},[545,4080,743],{"class":584},[545,4082,334],{"class":647},[545,4084,748],{"class":584},[545,4086,334],{"class":647},[545,4088,753],{"class":584},[545,4090,334],{"class":647},[545,4092,504],{"class":584},[545,4094,760],{"class":647},[545,4096,4097,4099,4101,4103,4105,4107,4109,4111,4113,4115,4117],{"class":547,"line":567},[545,4098,552],{"class":551},[545,4100,738],{"class":584},[545,4102,334],{"class":647},[545,4104,743],{"class":584},[545,4106,334],{"class":647},[545,4108,748],{"class":584},[545,4110,334],{"class":647},[545,4112,753],{"class":584},[545,4114,334],{"class":647},[545,4116,373],{"class":584},[545,4118,760],{"class":647},[545,4120,4121,4123,4125,4127,4129,4131,4133,4135,4137,4139,4141],{"class":547,"line":574},[545,4122,552],{"class":551},[545,4124,738],{"class":584},[545,4126,334],{"class":647},[545,4128,743],{"class":584},[545,4130,334],{"class":647},[545,4132,748],{"class":584},[545,4134,334],{"class":647},[545,4136,753],{"class":584},[545,4138,334],{"class":647},[545,4140,3662],{"class":584},[545,4142,760],{"class":647},[545,4144,4145,4147,4149,4151,4153,4155,4157,4159,4161,4163,4165],{"class":547,"line":608},[545,4146,552],{"class":551},[545,4148,738],{"class":584},[545,4150,334],{"class":647},[545,4152,743],{"class":584},[545,4154,334],{"class":647},[545,4156,748],{"class":584},[545,4158,334],{"class":647},[545,4160,753],{"class":584},[545,4162,334],{"class":647},[545,4164,1042],{"class":584},[545,4166,760],{"class":647},[545,4168,4169,4171,4173,4175,4178,4180,4183],{"class":547,"line":638},[545,4170,552],{"class":551},[545,4172,2257],{"class":584},[545,4174,334],{"class":647},[545,4176,4177],{"class":584},"time",[545,4179,334],{"class":647},[545,4181,4182],{"class":584},"Duration",[545,4184,760],{"class":647},[545,4186,4187],{"class":547,"line":657},[545,4188,571],{"emptyLinePlaceholder":570},[545,4190,4191,4193,4195],{"class":547,"line":676},[545,4192,793],{"class":611},[545,4194,796],{"class":611},[545,4196,4197],{"class":580}," HeartbeatProcessor\n",[545,4199,4200,4202,4204,4206,4208,4210,4213,4215,4217,4219,4221,4223],{"class":547,"line":683},[545,4201,804],{"class":611},[545,4203,1168],{"class":555},[545,4205,590],{"class":647},[545,4207,593],{"class":611},[545,4209,814],{"class":647},[545,4211,4212],{"class":611}," Integer",[545,4214,814],{"class":647},[545,4216,817],{"class":611},[545,4218,814],{"class":647},[545,4220,4212],{"class":611},[545,4222,824],{"class":647},[545,4224,827],{"class":647},[545,4226,4227],{"class":547,"line":708},[545,4228,571],{"emptyLinePlaceholder":570},[545,4230,4231,4233,4236,4239],{"class":547,"line":714},[545,4232,2957],{"class":611},[545,4234,4235],{"class":584}," Cancellable",[545,4237,4238],{"class":866}," schedule",[545,4240,760],{"class":647},[545,4242,4243],{"class":547,"line":720},[545,4244,571],{"emptyLinePlaceholder":570},[545,4246,4247,4249],{"class":547,"line":950},[545,4248,836],{"class":647},[545,4250,839],{"class":611},[545,4252,4253,4255,4257,4259,4261,4263,4265,4267,4269,4271,4273,4275,4277],{"class":547,"line":955},[545,4254,844],{"class":611},[545,4256,847],{"class":611},[545,4258,2993],{"class":555},[545,4260,695],{"class":647},[545,4262,373],{"class":584},[545,4264,590],{"class":647},[545,4266,593],{"class":611},[545,4268,814],{"class":647},[545,4270,4212],{"class":611},[545,4272,824],{"class":647},[545,4274,3332],{"class":866},[545,4276,870],{"class":647},[545,4278,827],{"class":647},[545,4280,4281,4283,4285,4287,4289,4291],{"class":547,"line":960},[545,4282,3014],{"class":3013},[545,4284,334],{"class":647},[545,4286,515],{"class":555},[545,4288,695],{"class":647},[545,4290,3349],{"class":584},[545,4292,2374],{"class":647},[545,4294,4295],{"class":547,"line":2064},[545,4296,3899],{"class":679},[545,4298,4299,4301,4303,4305,4307,4309,4311,4313],{"class":547,"line":2070},[545,4300,3356],{"class":3013},[545,4302,334],{"class":647},[545,4304,3578],{"class":866},[545,4306,648],{"class":647},[545,4308,3332],{"class":866},[545,4310,334],{"class":647},[545,4312,3578],{"class":555},[545,4314,2021],{"class":647},[545,4316,4317,4320,4322,4324,4326,4328],{"class":547,"line":2076},[545,4318,4319],{"class":866},"            Duration",[545,4321,334],{"class":647},[545,4323,3919],{"class":555},[545,4325,695],{"class":647},[545,4327,3924],{"class":3091},[545,4329,2046],{"class":647},[545,4331,4332,4335,4337,4339],{"class":547,"line":2081},[545,4333,4334],{"class":866},"            PunctuationType",[545,4336,334],{"class":647},[545,4338,3669],{"class":866},[545,4340,4341],{"class":647},",\n",[545,4343,4344,4347,4350,4352,4354,4356,4358,4360,4363,4365,4367,4369,4372,4374,4377],{"class":547,"line":2086},[545,4345,4346],{"class":584},"            ts ",[545,4348,4349],{"class":647},"->",[545,4351,3332],{"class":866},[545,4353,334],{"class":647},[545,4355,692],{"class":555},[545,4357,695],{"class":647},[545,4359,1516],{"class":1515},[545,4361,4362],{"class":1407},"heartbeat",[545,4364,1516],{"class":1515},[545,4366,814],{"class":647},[545,4368,390],{"class":647},[545,4370,4371],{"class":611},"int",[545,4373,870],{"class":647},[545,4375,4376],{"class":584}," ts",[545,4378,1524],{"class":647},[545,4380,4381],{"class":547,"line":2459},[545,4382,717],{"class":647},[545,4384,4385],{"class":547,"line":2471},[545,4386,571],{"emptyLinePlaceholder":570},[545,4388,4389,4391],{"class":547,"line":2479},[545,4390,836],{"class":647},[545,4392,839],{"class":611},[545,4394,4395,4397,4399,4401,4403,4405,4407,4409,4411,4413,4415,4417,4419],{"class":547,"line":2484},[545,4396,844],{"class":611},[545,4398,847],{"class":611},[545,4400,618],{"class":555},[545,4402,695],{"class":647},[545,4404,1042],{"class":584},[545,4406,590],{"class":647},[545,4408,593],{"class":611},[545,4410,814],{"class":647},[545,4412,4212],{"class":611},[545,4414,824],{"class":647},[545,4416,867],{"class":866},[545,4418,870],{"class":647},[545,4420,827],{"class":647},[545,4422,4423,4425,4427,4429,4431,4433,4435,4437,4439,4441,4443,4445],{"class":547,"line":2490},[545,4424,1076],{"class":555},[545,4426,689],{"class":647},[545,4428,692],{"class":555},[545,4430,695],{"class":647},[545,4432,3442],{"class":866},[545,4434,334],{"class":647},[545,4436,3447],{"class":555},[545,4438,1279],{"class":647},[545,4440,867],{"class":866},[545,4442,334],{"class":647},[545,4444,665],{"class":555},[545,4446,947],{"class":647},[545,4448,4449],{"class":547,"line":2495},[545,4450,717],{"class":647},[545,4452,4453],{"class":547,"line":4034},[545,4454,571],{"emptyLinePlaceholder":570},[545,4456,4457,4459],{"class":547,"line":4039},[545,4458,836],{"class":647},[545,4460,839],{"class":611},[545,4462,4464,4466,4468,4470,4472],{"class":547,"line":4463},29,[545,4465,844],{"class":611},[545,4467,847],{"class":611},[545,4469,4017],{"class":555},[545,4471,2350],{"class":647},[545,4473,827],{"class":647},[545,4475,4477,4479,4481,4484,4486,4488,4490],{"class":547,"line":4476},30,[545,4478,660],{"class":551},[545,4480,390],{"class":647},[545,4482,4483],{"class":584},"schedule ",[545,4485,902],{"class":611},[545,4487,905],{"class":551},[545,4489,870],{"class":647},[545,4491,827],{"class":647},[545,4493,4495,4498,4500,4502],{"class":547,"line":4494},31,[545,4496,4497],{"class":866},"            schedule",[545,4499,334],{"class":647},[545,4501,4028],{"class":555},[545,4503,890],{"class":647},[545,4505,4507],{"class":547,"line":4506},32,[545,4508,711],{"class":647},[545,4510,4512],{"class":547,"line":4511},33,[545,4513,717],{"class":647},[545,4515,4517],{"class":547,"line":4516},34,[545,4518,723],{"class":647},[1582,4520,4521],{"color":1584,"icon":1585},[320,4522,4523,4525,4526,4529,4530,4533,4534,334],{},[347,4524,393],{}," also has an ",[324,4527,4528],{},"anchored"," overload that takes a ",[347,4531,4532],{},"startTime: Instant",", snapping fire times to a fixed grid aligned to that anchor (KIP-1146) for deterministic, cron-like cadence. For topology-level periodic record generation that isn't tied to a processor, see ",[329,4535,140],{"href":141},[418,4537,399],{"id":4538},"timers",[320,4540,3557,4541,4543,4544,4546,4547,4550,4551,4553],{},[324,4542,3741],{}," fires once for a specific key at a specific instant, in event time or processing time. Unlike punctuators, timer callbacks run in the same per-key context as records — so ",[347,4545,406],{}," has ",[324,4548,4549],{},"full read\u002Fwrite state access"," and forwarding, with the same serialized execution as ",[347,4552,1832],{}," for that key. This follows Flink's timer semantics and is the right tool for per-key timeouts, debounce windows, and scheduled emissions.",[517,4555,4557],{"id":4556},"declaring-timer-types","Declaring timer types",[320,4559,4560,4561,4564,4565,4567,4568,4571],{},"A processor that uses timers must override ",[347,4562,4563],{},"declaredTimerTypes()"," to return the ",[347,4566,3582],{},"s it will register. The engine uses this both to validate at runtime (registering an undeclared type throws ",[347,4569,4570],{},"IllegalStateException",") and to optimise the hot path (it can skip watermark tracking when no processor declares event-time timers). The default is the empty set.",[517,4573,4575],{"id":4574},"registering-and-handling-timers","Registering and handling timers",[320,4577,4578,4579,370,4581,4583,4584,4586,4587,4589,4590,334],{},"Get the timer service in ",[347,4580,515],{},[347,4582,402],{},". Register timers in ",[347,4585,1310],{}," (or ",[347,4588,2880],{},"), and handle them by overriding ",[347,4591,4592],{},"onTimer(timestamp, key, context)",[426,4594,4595,4608],{},[429,4596,4597],{},[432,4598,4599,4605],{},[435,4600,4601,4604],{},[347,4602,4603],{},"TimerService\u003CK>"," method",[435,4606,4607],{},"Effect",[447,4609,4610,4622,4634,4644,4654],{},[432,4611,4612,4617],{},[452,4613,4614],{},[347,4615,4616],{},"registerEventTimeTimer(key, timestamp)",[452,4618,4619,4620],{},"Fire when the watermark advances past ",[347,4621,1290],{},[432,4623,4624,4629],{},[452,4625,4626],{},[347,4627,4628],{},"registerProcessingTimeTimer(key, timestamp)",[452,4630,4631,4632],{},"Fire when wall-clock time reaches ",[347,4633,1290],{},[432,4635,4636,4641],{},[452,4637,4638],{},[347,4639,4640],{},"deleteEventTimeTimer(key, timestamp)",[452,4642,4643],{},"Cancel a pending event-time timer",[432,4645,4646,4651],{},[452,4647,4648],{},[347,4649,4650],{},"deleteProcessingTimeTimer(key, timestamp)",[452,4652,4653],{},"Cancel a pending processing-time timer",[432,4655,4656,4664],{},[452,4657,4658,374,4661],{},[347,4659,4660],{},"currentWatermark()",[347,4662,4663],{},"currentProcessingTime()",[452,4665,4666],{},"Read the current stream time \u002F wall-clock time",[320,4668,4669,4670,4673],{},"Timers are deduplicated by ",[347,4671,4672],{},"(key, timestamp)"," — registering the same pair twice has no extra effect, and the timer fires exactly once.",[320,4675,1588,4676,4678,4679,4682,4683,596,4686,4688,4689,4692,4693,4695,4696,4699],{},[347,4677,2880],{}," callback receives a ",[347,4680,4681],{},"TimerContext",", which provides ",[347,4684,4685],{},"forward(...)",[347,4687,384],{}," (read\u002Fwrite), ",[347,4690,4691],{},"timerService()"," to register follow-up timers, the scheduled ",[347,4694,1731],{},", and ",[347,4697,4698],{},"timeDomain()"," to distinguish event-time from processing-time timers.",[531,4701,4702,5245],{"group":533},[535,4703,4705],{"className":537,"code":4704,"filename":539,"language":540,"meta":541,"style":541},"import io.stoatflow.core.processor.ContextualProcessor\nimport io.stoatflow.core.processor.ProcessorContext\nimport io.stoatflow.core.processor.Record\nimport io.stoatflow.core.processor.TimeNotion\nimport io.stoatflow.core.processor.TimerContext\nimport io.stoatflow.core.processor.TimerService\nimport io.stoatflow.core.state.KeyValueStore\n\nprivate const val SESSION_TIMEOUT_MS = 30_000L\n\nclass SessionProcessor :\n    ContextualProcessor\u003CString, Event, String, Session>() {\n\n    private lateinit var sessions: KeyValueStore\u003CString, Session>\n    private lateinit var timers: TimerService\u003CString>\n\n    override fun declaredTimerTypes(): Set\u003CTimeNotion> = setOf(TimeNotion.EVENT_TIME)\n\n    override fun init(context: ProcessorContext\u003CString, Session>) {\n        super.init(context)\n        sessions = context.getStateStore(\"sessions\")\n        timers = context.timerService()\n    }\n\n    override fun process(record: Record\u003CString, Event>) {\n        val session = sessions.get(record.key)?.add(record.value)\n            ?: Session.start(record.value)\n        sessions.put(record.key, session)\n        \u002F\u002F (re)arm the session-timeout timer\n        timers.registerEventTimeTimer(record.key, record.timestamp + SESSION_TIMEOUT_MS)\n    }\n\n    override fun onTimer(\n        timestamp: Long,\n        key: String,\n        context: TimerContext\u003CString, Session>,\n    ) {\n        val session = context.getStateStore\u003CKeyValueStore\u003CString, Session>>(\"sessions\").get(key)\n        if (session != null && session.lastActivity + SESSION_TIMEOUT_MS \u003C= timestamp) {\n            context.forward(key, session.complete())\n            context.getStateStore\u003CKeyValueStore\u003CString, Session>>(\"sessions\").delete(key)\n        }\n    }\n}\n",[347,4706,4707,4713,4719,4725,4731,4738,4745,4751,4755,4774,4778,4787,4811,4815,4838,4858,4862,4889,4893,4915,4925,4942,4956,4960,4964,4986,5013,5027,5037,5042,5058,5062,5066,5077,5086,5096,5115,5121,5158,5185,5200,5230,5235,5240],{"__ignoreMap":541},[545,4708,4709,4711],{"class":547,"line":548},[545,4710,552],{"class":551},[545,4712,988],{"class":555},[545,4714,4715,4717],{"class":547,"line":559},[545,4716,552],{"class":551},[545,4718,2905],{"class":555},[545,4720,4721,4723],{"class":547,"line":567},[545,4722,552],{"class":551},[545,4724,995],{"class":555},[545,4726,4727,4729],{"class":547,"line":574},[545,4728,552],{"class":551},[545,4730,3798],{"class":555},[545,4732,4733,4735],{"class":547,"line":608},[545,4734,552],{"class":551},[545,4736,4737],{"class":555}," io.stoatflow.core.processor.TimerContext\n",[545,4739,4740,4742],{"class":547,"line":638},[545,4741,552],{"class":551},[545,4743,4744],{"class":555}," io.stoatflow.core.processor.TimerService\n",[545,4746,4747,4749],{"class":547,"line":657},[545,4748,552],{"class":551},[545,4750,2918],{"class":555},[545,4752,4753],{"class":547,"line":676},[545,4754,571],{"emptyLinePlaceholder":570},[545,4756,4757,4760,4763,4766,4769,4771],{"class":547,"line":683},[545,4758,4759],{"class":611},"private",[545,4761,4762],{"class":611}," const",[545,4764,4765],{"class":551}," val",[545,4767,4768],{"class":584}," SESSION_TIMEOUT_MS ",[545,4770,1062],{"class":647},[545,4772,4773],{"class":3091}," 30_000L\n",[545,4775,4776],{"class":547,"line":708},[545,4777,571],{"emptyLinePlaceholder":570},[545,4779,4780,4782,4784],{"class":547,"line":714},[545,4781,577],{"class":551},[545,4783,1977],{"class":580},[545,4785,4786],{"class":584}," :\n",[545,4788,4789,4792,4794,4796,4798,4800,4802,4804,4806,4809],{"class":547,"line":720},[545,4790,4791],{"class":555},"    ContextualProcessor",[545,4793,590],{"class":584},[545,4795,593],{"class":580},[545,4797,596],{"class":584},[545,4799,1019],{"class":580},[545,4801,596],{"class":584},[545,4803,593],{"class":580},[545,4805,596],{"class":584},[545,4807,4808],{"class":580},"Session",[545,4810,605],{"class":584},[545,4812,4813],{"class":547,"line":950},[545,4814,571],{"emptyLinePlaceholder":570},[545,4816,4817,4819,4821,4823,4826,4828,4830,4832,4834,4836],{"class":547,"line":955},[545,4818,2957],{"class":611},[545,4820,2960],{"class":611},[545,4822,2963],{"class":551},[545,4824,4825],{"class":584}," sessions: ",[545,4827,2969],{"class":580},[545,4829,590],{"class":584},[545,4831,593],{"class":580},[545,4833,596],{"class":584},[545,4835,4808],{"class":580},[545,4837,2980],{"class":584},[545,4839,4840,4842,4844,4846,4849,4852,4854,4856],{"class":547,"line":960},[545,4841,2957],{"class":611},[545,4843,2960],{"class":611},[545,4845,2963],{"class":551},[545,4847,4848],{"class":584}," timers: ",[545,4850,4851],{"class":580},"TimerService",[545,4853,590],{"class":584},[545,4855,593],{"class":580},[545,4857,2980],{"class":584},[545,4859,4860],{"class":547,"line":2064},[545,4861,571],{"emptyLinePlaceholder":570},[545,4863,4864,4866,4868,4871,4873,4875,4877,4879,4881,4883,4886],{"class":547,"line":2070},[545,4865,612],{"class":611},[545,4867,615],{"class":551},[545,4869,4870],{"class":555}," declaredTimerTypes",[545,4872,2001],{"class":584},[545,4874,2004],{"class":580},[545,4876,590],{"class":584},[545,4878,3582],{"class":580},[545,4880,1380],{"class":584},[545,4882,1062],{"class":647},[545,4884,4885],{"class":555}," setOf",[545,4887,4888],{"class":584},"(TimeNotion.EVENT_TIME)\n",[545,4890,4891],{"class":547,"line":2076},[545,4892,571],{"emptyLinePlaceholder":570},[545,4894,4895,4897,4899,4901,4903,4905,4907,4909,4911,4913],{"class":547,"line":2081},[545,4896,612],{"class":611},[545,4898,615],{"class":551},[545,4900,2993],{"class":555},[545,4902,2996],{"class":584},[545,4904,373],{"class":580},[545,4906,590],{"class":584},[545,4908,593],{"class":580},[545,4910,596],{"class":584},[545,4912,4808],{"class":580},[545,4914,635],{"class":584},[545,4916,4917,4919,4921,4923],{"class":547,"line":2086},[545,4918,3014],{"class":3013},[545,4920,334],{"class":584},[545,4922,515],{"class":555},[545,4924,3021],{"class":584},[545,4926,4927,4930,4932,4934,4936,4938,4940],{"class":547,"line":2459},[545,4928,4929],{"class":584},"        sessions ",[545,4931,1062],{"class":647},[545,4933,3031],{"class":584},[545,4935,2884],{"class":555},[545,4937,695],{"class":584},[545,4939,1982],{"class":1407},[545,4941,1985],{"class":584},[545,4943,4944,4947,4949,4951,4954],{"class":547,"line":2471},[545,4945,4946],{"class":584},"        timers ",[545,4948,1062],{"class":647},[545,4950,3031],{"class":584},[545,4952,4953],{"class":555},"timerService",[545,4955,4031],{"class":584},[545,4957,4958],{"class":547,"line":2479},[545,4959,717],{"class":584},[545,4961,4962],{"class":547,"line":2484},[545,4963,571],{"emptyLinePlaceholder":570},[545,4965,4966,4968,4970,4972,4974,4976,4978,4980,4982,4984],{"class":547,"line":2490},[545,4967,612],{"class":611},[545,4969,615],{"class":551},[545,4971,618],{"class":555},[545,4973,621],{"class":584},[545,4975,1042],{"class":580},[545,4977,590],{"class":584},[545,4979,593],{"class":580},[545,4981,596],{"class":584},[545,4983,1019],{"class":580},[545,4985,635],{"class":584},[545,4987,4988,4990,4993,4995,4998,5000,5003,5006,5009,5011],{"class":547,"line":2495},[545,4989,641],{"class":551},[545,4991,4992],{"class":584}," session ",[545,4994,1062],{"class":647},[545,4996,4997],{"class":584}," sessions.",[545,4999,3085],{"class":555},[545,5001,5002],{"class":584},"(record.key)?.",[545,5004,5005],{"class":555},"add",[545,5007,5008],{"class":584},"(record.",[545,5010,665],{"class":611},[545,5012,1985],{"class":584},[545,5014,5015,5018,5021,5023,5025],{"class":547,"line":4034},[545,5016,5017],{"class":584},"            ?: Session.",[545,5019,5020],{"class":555},"start",[545,5022,5008],{"class":584},[545,5024,665],{"class":611},[545,5026,1985],{"class":584},[545,5028,5029,5032,5034],{"class":547,"line":4039},[545,5030,5031],{"class":584},"        sessions.",[545,5033,3109],{"class":555},[545,5035,5036],{"class":584},"(record.key, session)\n",[545,5038,5039],{"class":547,"line":4463},[545,5040,5041],{"class":679},"        \u002F\u002F (re)arm the session-timeout timer\n",[545,5043,5044,5047,5050,5053,5055],{"class":547,"line":4476},[545,5045,5046],{"class":584},"        timers.",[545,5048,5049],{"class":555},"registerEventTimeTimer",[545,5051,5052],{"class":584},"(record.key, record.timestamp ",[545,5054,3098],{"class":611},[545,5056,5057],{"class":584}," SESSION_TIMEOUT_MS)\n",[545,5059,5060],{"class":547,"line":4494},[545,5061,717],{"class":584},[545,5063,5064],{"class":547,"line":4506},[545,5065,571],{"emptyLinePlaceholder":570},[545,5067,5068,5070,5072,5075],{"class":547,"line":4511},[545,5069,612],{"class":611},[545,5071,615],{"class":551},[545,5073,5074],{"class":555}," onTimer",[545,5076,2021],{"class":584},[545,5078,5079,5082,5084],{"class":547,"line":4516},[545,5080,5081],{"class":584},"        timestamp: ",[545,5083,2950],{"class":580},[545,5085,4341],{"class":584},[545,5087,5089,5092,5094],{"class":547,"line":5088},35,[545,5090,5091],{"class":584},"        key: ",[545,5093,593],{"class":580},[545,5095,4341],{"class":584},[545,5097,5099,5102,5104,5106,5108,5110,5112],{"class":547,"line":5098},36,[545,5100,5101],{"class":584},"        context: ",[545,5103,4681],{"class":580},[545,5105,590],{"class":584},[545,5107,593],{"class":580},[545,5109,596],{"class":584},[545,5111,4808],{"class":580},[545,5113,5114],{"class":584},">,\n",[545,5116,5118],{"class":547,"line":5117},37,[545,5119,5120],{"class":584},"    ) {\n",[545,5122,5124,5126,5128,5130,5132,5134,5136,5138,5140,5142,5144,5146,5149,5151,5153,5155],{"class":547,"line":5123},38,[545,5125,641],{"class":551},[545,5127,4992],{"class":584},[545,5129,1062],{"class":647},[545,5131,3031],{"class":584},[545,5133,2884],{"class":555},[545,5135,590],{"class":584},[545,5137,2969],{"class":580},[545,5139,590],{"class":584},[545,5141,593],{"class":580},[545,5143,596],{"class":584},[545,5145,4808],{"class":580},[545,5147,5148],{"class":584},">>(",[545,5150,1982],{"class":1407},[545,5152,364],{"class":584},[545,5154,3085],{"class":555},[545,5156,5157],{"class":584},"(key)\n",[545,5159,5161,5163,5166,5168,5170,5172,5175,5177,5179,5182],{"class":547,"line":5160},39,[545,5162,660],{"class":551},[545,5164,5165],{"class":584}," (session ",[545,5167,902],{"class":611},[545,5169,905],{"class":611},[545,5171,908],{"class":611},[545,5173,5174],{"class":584}," session.lastActivity ",[545,5176,3098],{"class":611},[545,5178,4768],{"class":584},[545,5180,5181],{"class":611},"\u003C=",[545,5183,5184],{"class":584}," timestamp) {\n",[545,5186,5188,5190,5192,5195,5198],{"class":547,"line":5187},40,[545,5189,3911],{"class":584},[545,5191,692],{"class":555},[545,5193,5194],{"class":584},"(key, session.",[545,5196,5197],{"class":555},"complete",[545,5199,705],{"class":584},[545,5201,5203,5205,5207,5209,5211,5213,5215,5217,5219,5221,5223,5225,5228],{"class":547,"line":5202},41,[545,5204,3911],{"class":584},[545,5206,2884],{"class":555},[545,5208,590],{"class":584},[545,5210,2969],{"class":580},[545,5212,590],{"class":584},[545,5214,593],{"class":580},[545,5216,596],{"class":584},[545,5218,4808],{"class":580},[545,5220,5148],{"class":584},[545,5222,1982],{"class":1407},[545,5224,364],{"class":584},[545,5226,5227],{"class":555},"delete",[545,5229,5157],{"class":584},[545,5231,5233],{"class":547,"line":5232},42,[545,5234,711],{"class":584},[545,5236,5238],{"class":547,"line":5237},43,[545,5239,717],{"class":584},[545,5241,5243],{"class":547,"line":5242},44,[545,5244,723],{"class":584},[535,5246,5248],{"className":726,"code":5247,"filename":728,"language":729,"meta":541,"style":541},"import io.stoatflow.core.processor.ContextualProcessor;\nimport io.stoatflow.core.processor.ProcessorContext;\nimport io.stoatflow.core.processor.Record;\nimport io.stoatflow.core.processor.TimeNotion;\nimport io.stoatflow.core.processor.TimerContext;\nimport io.stoatflow.core.processor.TimerService;\nimport io.stoatflow.core.state.KeyValueStore;\nimport org.jspecify.annotations.NonNull;\n\nimport java.util.Set;\n\npublic class SessionProcessor\n        extends ContextualProcessor\u003CString, Event, String, Session> {\n\n    private static final long SESSION_TIMEOUT_MS = 30_000L;\n\n    private KeyValueStore\u003CString, Session> sessions;\n    private TimerService\u003CString> timers;\n\n    @Override\n    public @NonNull Set\u003CTimeNotion> declaredTimerTypes() {\n        return Set.of(TimeNotion.EVENT_TIME);\n    }\n\n    @Override\n    public void init(ProcessorContext\u003CString, Session> context) {\n        super.init(context);\n        this.sessions = context.getStateStore(\"sessions\");\n        this.timers = context.timerService();\n    }\n\n    @Override\n    public void process(Record\u003CString, Event> record) {\n        Session existing = sessions.get(record.key());\n        Session session = existing == null\n            ? Session.start(record.value())\n            : existing.add(record.value());\n        sessions.put(record.key(), session);\n        \u002F\u002F (re)arm the session-timeout timer\n        timers.registerEventTimeTimer(record.key(), record.timestamp() + SESSION_TIMEOUT_MS);\n    }\n\n    @Override\n    public void onTimer(long timestamp, String key, @NonNull TimerContext\u003CString, Session> context) {\n        KeyValueStore\u003CString, Session> store = context.getStateStore(\"sessions\");\n        Session session = store.get(key);\n        if (session != null && session.lastActivity() + SESSION_TIMEOUT_MS \u003C= timestamp) {\n            context.forward(key, session.complete());\n            store.delete(key);\n        }\n    }\n}\n",[347,5249,5250,5274,5298,5322,5346,5370,5394,5418,5441,5445,5461,5465,5474,5501,5505,5528,5532,5553,5571,5575,5581,5600,5621,5625,5629,5635,5663,5677,5703,5721,5725,5729,5735,5763,5789,5806,5827,5848,5871,5875,5909,5913,5917,5923,5972,6009,6030,6067,6090,6106,6111,6116],{"__ignoreMap":541},[545,5251,5252,5254,5256,5258,5260,5262,5264,5266,5268,5270,5272],{"class":547,"line":548},[545,5253,552],{"class":551},[545,5255,738],{"class":584},[545,5257,334],{"class":647},[545,5259,743],{"class":584},[545,5261,334],{"class":647},[545,5263,748],{"class":584},[545,5265,334],{"class":647},[545,5267,753],{"class":584},[545,5269,334],{"class":647},[545,5271,504],{"class":584},[545,5273,760],{"class":647},[545,5275,5276,5278,5280,5282,5284,5286,5288,5290,5292,5294,5296],{"class":547,"line":559},[545,5277,552],{"class":551},[545,5279,738],{"class":584},[545,5281,334],{"class":647},[545,5283,743],{"class":584},[545,5285,334],{"class":647},[545,5287,748],{"class":584},[545,5289,334],{"class":647},[545,5291,753],{"class":584},[545,5293,334],{"class":647},[545,5295,373],{"class":584},[545,5297,760],{"class":647},[545,5299,5300,5302,5304,5306,5308,5310,5312,5314,5316,5318,5320],{"class":547,"line":567},[545,5301,552],{"class":551},[545,5303,738],{"class":584},[545,5305,334],{"class":647},[545,5307,743],{"class":584},[545,5309,334],{"class":647},[545,5311,748],{"class":584},[545,5313,334],{"class":647},[545,5315,753],{"class":584},[545,5317,334],{"class":647},[545,5319,1042],{"class":584},[545,5321,760],{"class":647},[545,5323,5324,5326,5328,5330,5332,5334,5336,5338,5340,5342,5344],{"class":547,"line":574},[545,5325,552],{"class":551},[545,5327,738],{"class":584},[545,5329,334],{"class":647},[545,5331,743],{"class":584},[545,5333,334],{"class":647},[545,5335,748],{"class":584},[545,5337,334],{"class":647},[545,5339,753],{"class":584},[545,5341,334],{"class":647},[545,5343,3582],{"class":584},[545,5345,760],{"class":647},[545,5347,5348,5350,5352,5354,5356,5358,5360,5362,5364,5366,5368],{"class":547,"line":608},[545,5349,552],{"class":551},[545,5351,738],{"class":584},[545,5353,334],{"class":647},[545,5355,743],{"class":584},[545,5357,334],{"class":647},[545,5359,748],{"class":584},[545,5361,334],{"class":647},[545,5363,753],{"class":584},[545,5365,334],{"class":647},[545,5367,4681],{"class":584},[545,5369,760],{"class":647},[545,5371,5372,5374,5376,5378,5380,5382,5384,5386,5388,5390,5392],{"class":547,"line":638},[545,5373,552],{"class":551},[545,5375,738],{"class":584},[545,5377,334],{"class":647},[545,5379,743],{"class":584},[545,5381,334],{"class":647},[545,5383,748],{"class":584},[545,5385,334],{"class":647},[545,5387,753],{"class":584},[545,5389,334],{"class":647},[545,5391,4851],{"class":584},[545,5393,760],{"class":647},[545,5395,5396,5398,5400,5402,5404,5406,5408,5410,5412,5414,5416],{"class":547,"line":657},[545,5397,552],{"class":551},[545,5399,738],{"class":584},[545,5401,334],{"class":647},[545,5403,743],{"class":584},[545,5405,334],{"class":647},[545,5407,748],{"class":584},[545,5409,334],{"class":647},[545,5411,2182],{"class":584},[545,5413,334],{"class":647},[545,5415,2969],{"class":584},[545,5417,760],{"class":647},[545,5419,5420,5422,5424,5426,5429,5431,5434,5436,5439],{"class":547,"line":676},[545,5421,552],{"class":551},[545,5423,2219],{"class":584},[545,5425,334],{"class":647},[545,5427,5428],{"class":584},"jspecify",[545,5430,334],{"class":647},[545,5432,5433],{"class":584},"annotations",[545,5435,334],{"class":647},[545,5437,5438],{"class":584},"NonNull",[545,5440,760],{"class":647},[545,5442,5443],{"class":547,"line":683},[545,5444,571],{"emptyLinePlaceholder":570},[545,5446,5447,5449,5451,5453,5455,5457,5459],{"class":547,"line":708},[545,5448,552],{"class":551},[545,5450,2257],{"class":584},[545,5452,334],{"class":647},[545,5454,2262],{"class":584},[545,5456,334],{"class":647},[545,5458,2004],{"class":584},[545,5460,760],{"class":647},[545,5462,5463],{"class":547,"line":714},[545,5464,571],{"emptyLinePlaceholder":570},[545,5466,5467,5469,5471],{"class":547,"line":720},[545,5468,793],{"class":611},[545,5470,796],{"class":611},[545,5472,5473],{"class":580}," SessionProcessor\n",[545,5475,5476,5478,5480,5482,5484,5486,5488,5490,5492,5494,5497,5499],{"class":547,"line":950},[545,5477,804],{"class":611},[545,5479,1168],{"class":555},[545,5481,590],{"class":647},[545,5483,593],{"class":611},[545,5485,814],{"class":647},[545,5487,1177],{"class":611},[545,5489,814],{"class":647},[545,5491,817],{"class":611},[545,5493,814],{"class":647},[545,5495,5496],{"class":611}," Session",[545,5498,824],{"class":647},[545,5500,827],{"class":647},[545,5502,5503],{"class":547,"line":955},[545,5504,571],{"emptyLinePlaceholder":570},[545,5506,5507,5509,5512,5515,5518,5521,5523,5526],{"class":547,"line":960},[545,5508,2957],{"class":611},[545,5510,5511],{"class":611}," static",[545,5513,5514],{"class":611}," final",[545,5516,5517],{"class":611}," long",[545,5519,5520],{"class":866}," SESSION_TIMEOUT_MS",[545,5522,648],{"class":647},[545,5524,5525],{"class":3091}," 30_000L",[545,5527,760],{"class":647},[545,5529,5530],{"class":547,"line":2064},[545,5531,571],{"emptyLinePlaceholder":570},[545,5533,5534,5536,5538,5540,5542,5544,5546,5548,5551],{"class":547,"line":2070},[545,5535,2957],{"class":611},[545,5537,3282],{"class":584},[545,5539,590],{"class":647},[545,5541,593],{"class":611},[545,5543,814],{"class":647},[545,5545,5496],{"class":611},[545,5547,824],{"class":647},[545,5549,5550],{"class":866}," sessions",[545,5552,760],{"class":647},[545,5554,5555,5557,5560,5562,5564,5566,5569],{"class":547,"line":2076},[545,5556,2957],{"class":611},[545,5558,5559],{"class":584}," TimerService",[545,5561,590],{"class":647},[545,5563,593],{"class":611},[545,5565,824],{"class":647},[545,5567,5568],{"class":866}," timers",[545,5570,760],{"class":647},[545,5572,5573],{"class":547,"line":2081},[545,5574,571],{"emptyLinePlaceholder":570},[545,5576,5577,5579],{"class":547,"line":2086},[545,5578,836],{"class":647},[545,5580,839],{"class":611},[545,5582,5583,5585,5588,5590,5592,5594,5596,5598],{"class":547,"line":2459},[545,5584,844],{"class":611},[545,5586,5587],{"class":584}," @NonNull Set",[545,5589,590],{"class":647},[545,5591,3582],{"class":611},[545,5593,824],{"class":647},[545,5595,4870],{"class":555},[545,5597,2350],{"class":647},[545,5599,827],{"class":647},[545,5601,5602,5605,5607,5609,5611,5613,5615,5617,5619],{"class":547,"line":2471},[545,5603,5604],{"class":551},"        return",[545,5606,2395],{"class":866},[545,5608,334],{"class":647},[545,5610,2424],{"class":555},[545,5612,695],{"class":647},[545,5614,3582],{"class":866},[545,5616,334],{"class":647},[545,5618,3632],{"class":866},[545,5620,2374],{"class":647},[545,5622,5623],{"class":547,"line":2479},[545,5624,717],{"class":647},[545,5626,5627],{"class":547,"line":2484},[545,5628,571],{"emptyLinePlaceholder":570},[545,5630,5631,5633],{"class":547,"line":2490},[545,5632,836],{"class":647},[545,5634,839],{"class":611},[545,5636,5637,5639,5641,5643,5645,5647,5649,5651,5653,5655,5657,5659,5661],{"class":547,"line":2495},[545,5638,844],{"class":611},[545,5640,847],{"class":611},[545,5642,2993],{"class":555},[545,5644,695],{"class":647},[545,5646,373],{"class":584},[545,5648,590],{"class":647},[545,5650,593],{"class":611},[545,5652,814],{"class":647},[545,5654,5496],{"class":611},[545,5656,824],{"class":647},[545,5658,3332],{"class":866},[545,5660,870],{"class":647},[545,5662,827],{"class":647},[545,5664,5665,5667,5669,5671,5673,5675],{"class":547,"line":4034},[545,5666,3014],{"class":3013},[545,5668,334],{"class":647},[545,5670,515],{"class":555},[545,5672,695],{"class":647},[545,5674,3349],{"class":584},[545,5676,2374],{"class":647},[545,5678,5679,5681,5683,5685,5687,5689,5691,5693,5695,5697,5699,5701],{"class":547,"line":4039},[545,5680,3356],{"class":3013},[545,5682,334],{"class":647},[545,5684,2369],{"class":866},[545,5686,648],{"class":647},[545,5688,3332],{"class":866},[545,5690,334],{"class":647},[545,5692,2884],{"class":555},[545,5694,695],{"class":647},[545,5696,1516],{"class":1515},[545,5698,2369],{"class":1407},[545,5700,1516],{"class":1515},[545,5702,2374],{"class":647},[545,5704,5705,5707,5709,5711,5713,5715,5717,5719],{"class":547,"line":4463},[545,5706,3356],{"class":3013},[545,5708,334],{"class":647},[545,5710,4538],{"class":866},[545,5712,648],{"class":647},[545,5714,3332],{"class":866},[545,5716,334],{"class":647},[545,5718,4953],{"class":555},[545,5720,890],{"class":647},[545,5722,5723],{"class":547,"line":4476},[545,5724,717],{"class":647},[545,5726,5727],{"class":547,"line":4494},[545,5728,571],{"emptyLinePlaceholder":570},[545,5730,5731,5733],{"class":547,"line":4506},[545,5732,836],{"class":647},[545,5734,839],{"class":611},[545,5736,5737,5739,5741,5743,5745,5747,5749,5751,5753,5755,5757,5759,5761],{"class":547,"line":4511},[545,5738,844],{"class":611},[545,5740,847],{"class":611},[545,5742,618],{"class":555},[545,5744,695],{"class":647},[545,5746,1042],{"class":584},[545,5748,590],{"class":647},[545,5750,593],{"class":611},[545,5752,814],{"class":647},[545,5754,1177],{"class":611},[545,5756,824],{"class":647},[545,5758,867],{"class":866},[545,5760,870],{"class":647},[545,5762,827],{"class":647},[545,5764,5765,5768,5771,5773,5775,5777,5779,5781,5783,5785,5787],{"class":547,"line":4516},[545,5766,5767],{"class":584},"        Session",[545,5769,5770],{"class":866}," existing",[545,5772,648],{"class":647},[545,5774,5550],{"class":866},[545,5776,334],{"class":647},[545,5778,3085],{"class":555},[545,5780,695],{"class":647},[545,5782,3442],{"class":866},[545,5784,334],{"class":647},[545,5786,3447],{"class":555},[545,5788,947],{"class":647},[545,5790,5791,5793,5796,5798,5801,5804],{"class":547,"line":5088},[545,5792,5767],{"class":584},[545,5794,5795],{"class":866}," session",[545,5797,648],{"class":647},[545,5799,5800],{"class":584}," existing ",[545,5802,5803],{"class":611},"==",[545,5805,3858],{"class":551},[545,5807,5808,5811,5813,5815,5817,5819,5821,5823,5825],{"class":547,"line":5098},[545,5809,5810],{"class":551},"            ?",[545,5812,5496],{"class":866},[545,5814,334],{"class":647},[545,5816,5020],{"class":555},[545,5818,695],{"class":647},[545,5820,3442],{"class":866},[545,5822,334],{"class":647},[545,5824,665],{"class":555},[545,5826,705],{"class":647},[545,5828,5829,5832,5834,5836,5838,5840,5842,5844,5846],{"class":547,"line":5117},[545,5830,5831],{"class":551},"            :",[545,5833,5770],{"class":866},[545,5835,334],{"class":647},[545,5837,5005],{"class":555},[545,5839,695],{"class":647},[545,5841,3442],{"class":866},[545,5843,334],{"class":647},[545,5845,665],{"class":555},[545,5847,947],{"class":647},[545,5849,5850,5853,5855,5857,5859,5861,5863,5865,5867,5869],{"class":547,"line":5123},[545,5851,5852],{"class":866},"        sessions",[545,5854,334],{"class":647},[545,5856,3109],{"class":555},[545,5858,695],{"class":647},[545,5860,3442],{"class":866},[545,5862,334],{"class":647},[545,5864,3447],{"class":555},[545,5866,1279],{"class":647},[545,5868,5795],{"class":584},[545,5870,2374],{"class":647},[545,5872,5873],{"class":547,"line":5160},[545,5874,5041],{"class":679},[545,5876,5877,5880,5882,5884,5886,5888,5890,5892,5894,5896,5898,5900,5902,5905,5907],{"class":547,"line":5187},[545,5878,5879],{"class":866},"        timers",[545,5881,334],{"class":647},[545,5883,5049],{"class":555},[545,5885,695],{"class":647},[545,5887,3442],{"class":866},[545,5889,334],{"class":647},[545,5891,3447],{"class":555},[545,5893,1279],{"class":647},[545,5895,867],{"class":866},[545,5897,334],{"class":647},[545,5899,1290],{"class":555},[545,5901,2350],{"class":647},[545,5903,5904],{"class":611}," +",[545,5906,5520],{"class":584},[545,5908,2374],{"class":647},[545,5910,5911],{"class":547,"line":5202},[545,5912,717],{"class":647},[545,5914,5915],{"class":547,"line":5232},[545,5916,571],{"emptyLinePlaceholder":570},[545,5918,5919,5921],{"class":547,"line":5237},[545,5920,836],{"class":647},[545,5922,839],{"class":611},[545,5924,5925,5927,5929,5931,5933,5936,5939,5941,5944,5946,5948,5951,5953,5956,5958,5960,5962,5964,5966,5968,5970],{"class":547,"line":5242},[545,5926,844],{"class":611},[545,5928,847],{"class":611},[545,5930,5074],{"class":555},[545,5932,695],{"class":647},[545,5934,5935],{"class":611},"long",[545,5937,5938],{"class":866}," timestamp",[545,5940,814],{"class":647},[545,5942,5943],{"class":584}," String ",[545,5945,3447],{"class":866},[545,5947,814],{"class":647},[545,5949,5950],{"class":647}," @",[545,5952,5438],{"class":611},[545,5954,5955],{"class":584}," TimerContext",[545,5957,590],{"class":647},[545,5959,593],{"class":611},[545,5961,814],{"class":647},[545,5963,5496],{"class":611},[545,5965,824],{"class":647},[545,5967,3332],{"class":866},[545,5969,870],{"class":647},[545,5971,827],{"class":647},[545,5973,5975,5978,5980,5982,5984,5986,5988,5991,5993,5995,5997,5999,6001,6003,6005,6007],{"class":547,"line":5974},45,[545,5976,5977],{"class":584},"        KeyValueStore",[545,5979,590],{"class":647},[545,5981,593],{"class":611},[545,5983,814],{"class":647},[545,5985,5496],{"class":611},[545,5987,824],{"class":647},[545,5989,5990],{"class":866}," store",[545,5992,648],{"class":647},[545,5994,3332],{"class":866},[545,5996,334],{"class":647},[545,5998,2884],{"class":555},[545,6000,695],{"class":647},[545,6002,1516],{"class":1515},[545,6004,2369],{"class":1407},[545,6006,1516],{"class":1515},[545,6008,2374],{"class":647},[545,6010,6012,6014,6016,6018,6020,6022,6024,6026,6028],{"class":547,"line":6011},46,[545,6013,5767],{"class":584},[545,6015,5795],{"class":866},[545,6017,648],{"class":647},[545,6019,5990],{"class":866},[545,6021,334],{"class":647},[545,6023,3085],{"class":555},[545,6025,695],{"class":647},[545,6027,3447],{"class":584},[545,6029,2374],{"class":647},[545,6031,6033,6035,6037,6040,6042,6044,6046,6048,6050,6053,6055,6057,6059,6061,6063,6065],{"class":547,"line":6032},47,[545,6034,660],{"class":551},[545,6036,390],{"class":647},[545,6038,6039],{"class":584},"session ",[545,6041,902],{"class":611},[545,6043,905],{"class":551},[545,6045,908],{"class":611},[545,6047,5795],{"class":866},[545,6049,334],{"class":647},[545,6051,6052],{"class":555},"lastActivity",[545,6054,2350],{"class":647},[545,6056,5904],{"class":611},[545,6058,4768],{"class":584},[545,6060,5181],{"class":611},[545,6062,5938],{"class":584},[545,6064,870],{"class":647},[545,6066,827],{"class":647},[545,6068,6070,6072,6074,6076,6078,6080,6082,6084,6086,6088],{"class":547,"line":6069},48,[545,6071,686],{"class":866},[545,6073,334],{"class":647},[545,6075,692],{"class":555},[545,6077,695],{"class":647},[545,6079,3447],{"class":584},[545,6081,814],{"class":647},[545,6083,5795],{"class":866},[545,6085,334],{"class":647},[545,6087,5197],{"class":555},[545,6089,947],{"class":647},[545,6091,6093,6096,6098,6100,6102,6104],{"class":547,"line":6092},49,[545,6094,6095],{"class":866},"            store",[545,6097,334],{"class":647},[545,6099,5227],{"class":555},[545,6101,695],{"class":647},[545,6103,3447],{"class":584},[545,6105,2374],{"class":647},[545,6107,6109],{"class":547,"line":6108},50,[545,6110,711],{"class":647},[545,6112,6114],{"class":547,"line":6113},51,[545,6115,717],{"class":647},[545,6117,6119],{"class":547,"line":6118},52,[545,6120,723],{"class":647},[1582,6122,6123],{"color":1584,"icon":70},[320,6124,6125,6126,6129,6130,6133],{},"Pick ",[324,6127,6128],{},"event-time timers"," for data-driven timeouts (sessionization, watermark-aligned flushing) — they advance with your data and are deterministic on replay. Pick ",[324,6131,6132],{},"processing-time timers"," for wall-clock deadlines that must fire regardless of data flow (the news-portal \"publish at scheduled time\" pattern). A persistent (RocksDB) timer backend survives restarts; with an in-memory backend, pending timers are rebuilt from your own state on recovery.",[418,6135,6137],{"id":6136},"a-complete-processor-app","A complete processor app",[320,6139,6140,6141,6143,6144,6146],{},"Putting it together: register the store, attach the processor with ",[347,6142,1832],{},", and run it on the runtime. The processor reads its store by name, forwards results, and the runtime wires up Kafka, the HTTP\u002Fmetrics server, and graceful shutdown — see ",[329,6145,28],{"href":29}," for the runtime entry point.",[531,6148,6149,6512],{"group":533},[535,6150,6152],{"className":537,"code":6151,"filename":539,"language":540,"meta":541,"style":541},"import io.stoatflow.core.state.Stores\nimport io.stoatflow.core.topology.Consumed\nimport io.stoatflow.core.topology.Named\nimport io.stoatflow.core.topology.Produced\nimport 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 = { buildTopology(it) },\n        configure = {\n            streamsConfigOverrides {\n                defaultKeySerde(Serdes.String())\n                defaultValueSerde(Serdes.String())\n            }\n        },\n    )\n    runtime.start()\n    runtime.awaitTermination()\n}\n\nprivate fun buildTopology(builder: StreamsBuilder) {\n    builder.addStateStore(\n        Stores.keyValueStoreBuilder(\n            Stores.persistentKeyValueStore(\"counts\"),\n            Serdes.String(),\n            Serdes.Long(),\n        ),\n    )\n\n    builder\n        .stream\u003CString, String>(\"input\", Consumed.`as`(\"source\"))\n        .process({ CountingProcessor() }, Named.`as`(\"count\"))\n        .to(\"counts-out\", Produced.`as`\u003CString, Long>(\"sink\").withValueSerde(Serdes.Long()))\n}\n",[347,6153,6154,6160,6167,6174,6181,6188,6195,6201,6205,6215,6233,6249,6258,6265,6277,6288,6292,6297,6302,6311,6320,6324,6328,6345,6354,6362,6375,6384,6392,6397,6401,6405,6410,6444,6466,6508],{"__ignoreMap":541},[545,6155,6156,6158],{"class":547,"line":548},[545,6157,552],{"class":551},[545,6159,1910],{"class":555},[545,6161,6162,6164],{"class":547,"line":559},[545,6163,552],{"class":551},[545,6165,6166],{"class":555}," io.stoatflow.core.topology.Consumed\n",[545,6168,6169,6171],{"class":547,"line":567},[545,6170,552],{"class":551},[545,6172,6173],{"class":555}," io.stoatflow.core.topology.Named\n",[545,6175,6176,6178],{"class":547,"line":574},[545,6177,552],{"class":551},[545,6179,6180],{"class":555}," io.stoatflow.core.topology.Produced\n",[545,6182,6183,6185],{"class":547,"line":608},[545,6184,552],{"class":551},[545,6186,6187],{"class":555}," io.stoatflow.core.topology.StreamsBuilder\n",[545,6189,6190,6192],{"class":547,"line":638},[545,6191,552],{"class":551},[545,6193,6194],{"class":555}," io.stoatflow.runtime.StoatFlowRuntime\n",[545,6196,6197,6199],{"class":547,"line":657},[545,6198,552],{"class":551},[545,6200,1917],{"class":555},[545,6202,6203],{"class":547,"line":676},[545,6204,571],{"emptyLinePlaceholder":570},[545,6206,6207,6210,6213],{"class":547,"line":683},[545,6208,6209],{"class":551},"fun",[545,6211,6212],{"class":555}," main",[545,6214,4020],{"class":584},[545,6216,6217,6220,6223,6225,6228,6231],{"class":547,"line":708},[545,6218,6219],{"class":551},"    val",[545,6221,6222],{"class":584}," runtime ",[545,6224,1062],{"class":647},[545,6226,6227],{"class":584}," StoatFlowRuntime.",[545,6229,6230],{"class":555},"fromConfig",[545,6232,2021],{"class":584},[545,6234,6235,6238,6240,6243,6246],{"class":547,"line":714},[545,6236,6237],{"class":584},"        topologyBuilder ",[545,6239,1062],{"class":647},[545,6241,6242],{"class":584}," { ",[545,6244,6245],{"class":555},"buildTopology",[545,6247,6248],{"class":584},"(it) },\n",[545,6250,6251,6254,6256],{"class":547,"line":720},[545,6252,6253],{"class":584},"        configure ",[545,6255,1062],{"class":647},[545,6257,827],{"class":584},[545,6259,6260,6263],{"class":547,"line":950},[545,6261,6262],{"class":555},"            streamsConfigOverrides",[545,6264,827],{"class":584},[545,6266,6267,6270,6273,6275],{"class":547,"line":955},[545,6268,6269],{"class":555},"                defaultKeySerde",[545,6271,6272],{"class":584},"(Serdes.",[545,6274,593],{"class":555},[545,6276,705],{"class":584},[545,6278,6279,6282,6284,6286],{"class":547,"line":960},[545,6280,6281],{"class":555},"                defaultValueSerde",[545,6283,6272],{"class":584},[545,6285,593],{"class":555},[545,6287,705],{"class":584},[545,6289,6290],{"class":547,"line":2064},[545,6291,3955],{"class":584},[545,6293,6294],{"class":547,"line":2070},[545,6295,6296],{"class":584},"        },\n",[545,6298,6299],{"class":547,"line":2076},[545,6300,6301],{"class":584},"    )\n",[545,6303,6304,6307,6309],{"class":547,"line":2081},[545,6305,6306],{"class":584},"    runtime.",[545,6308,5020],{"class":555},[545,6310,4031],{"class":584},[545,6312,6313,6315,6318],{"class":547,"line":2086},[545,6314,6306],{"class":584},[545,6316,6317],{"class":555},"awaitTermination",[545,6319,4031],{"class":584},[545,6321,6322],{"class":547,"line":2459},[545,6323,723],{"class":584},[545,6325,6326],{"class":547,"line":2471},[545,6327,571],{"emptyLinePlaceholder":570},[545,6329,6330,6332,6334,6337,6340,6342],{"class":547,"line":2479},[545,6331,4759],{"class":611},[545,6333,615],{"class":551},[545,6335,6336],{"class":555}," buildTopology",[545,6338,6339],{"class":584},"(builder: ",[545,6341,2552],{"class":580},[545,6343,6344],{"class":584},") {\n",[545,6346,6347,6350,6352],{"class":547,"line":2484},[545,6348,6349],{"class":584},"    builder.",[545,6351,2597],{"class":555},[545,6353,2021],{"class":584},[545,6355,6356,6358,6360],{"class":547,"line":2490},[545,6357,2613],{"class":584},[545,6359,2029],{"class":555},[545,6361,2021],{"class":584},[545,6363,6364,6367,6369,6371,6373],{"class":547,"line":2495},[545,6365,6366],{"class":584},"            Stores.",[545,6368,2039],{"class":555},[545,6370,695],{"class":584},[545,6372,3038],{"class":1407},[545,6374,2046],{"class":584},[545,6376,6377,6380,6382],{"class":547,"line":4034},[545,6378,6379],{"class":584},"            Serdes.",[545,6381,593],{"class":555},[545,6383,2056],{"class":584},[545,6385,6386,6388,6390],{"class":547,"line":4039},[545,6387,6379],{"class":584},[545,6389,2950],{"class":555},[545,6391,2056],{"class":584},[545,6393,6394],{"class":547,"line":4463},[545,6395,6396],{"class":584},"        ),\n",[545,6398,6399],{"class":547,"line":4476},[545,6400,6301],{"class":584},[545,6402,6403],{"class":547,"line":4494},[545,6404,571],{"emptyLinePlaceholder":570},[545,6406,6407],{"class":547,"line":4506},[545,6408,6409],{"class":584},"    builder\n",[545,6411,6412,6415,6418,6420,6422,6424,6426,6429,6432,6435,6437,6439,6442],{"class":547,"line":4511},[545,6413,6414],{"class":584},"        .",[545,6416,6417],{"class":555},"stream",[545,6419,590],{"class":584},[545,6421,593],{"class":580},[545,6423,596],{"class":584},[545,6425,593],{"class":580},[545,6427,6428],{"class":584},">(",[545,6430,6431],{"class":1407},"\"input\"",[545,6433,6434],{"class":584},", Consumed.",[545,6436,1402],{"class":555},[545,6438,695],{"class":584},[545,6440,6441],{"class":1407},"\"source\"",[545,6443,1411],{"class":584},[545,6445,6446,6448,6450,6452,6455,6457,6459,6461,6464],{"class":547,"line":4516},[545,6447,6414],{"class":584},[545,6449,1310],{"class":555},[545,6451,1393],{"class":584},[545,6453,6454],{"class":555},"CountingProcessor",[545,6456,1399],{"class":584},[545,6458,1402],{"class":555},[545,6460,695],{"class":584},[545,6462,6463],{"class":1407},"\"count\"",[545,6465,1411],{"class":584},[545,6467,6468,6470,6473,6475,6478,6481,6483,6485,6487,6489,6491,6493,6496,6498,6501,6503,6505],{"class":547,"line":5088},[545,6469,6414],{"class":584},[545,6471,6472],{"class":555},"to",[545,6474,695],{"class":584},[545,6476,6477],{"class":1407},"\"counts-out\"",[545,6479,6480],{"class":584},", Produced.",[545,6482,1402],{"class":555},[545,6484,590],{"class":584},[545,6486,593],{"class":580},[545,6488,596],{"class":584},[545,6490,2950],{"class":580},[545,6492,6428],{"class":584},[545,6494,6495],{"class":1407},"\"sink\"",[545,6497,364],{"class":584},[545,6499,6500],{"class":555},"withValueSerde",[545,6502,6272],{"class":584},[545,6504,2950],{"class":555},[545,6506,6507],{"class":584},"()))\n",[545,6509,6510],{"class":547,"line":5098},[545,6511,723],{"class":584},[535,6513,6515],{"className":726,"code":6514,"filename":728,"language":729,"meta":541,"style":541},"import io.stoatflow.core.state.Stores;\nimport io.stoatflow.core.topology.Consumed;\nimport io.stoatflow.core.topology.KStream;\nimport io.stoatflow.core.topology.Named;\nimport io.stoatflow.core.topology.Produced;\nimport io.stoatflow.core.topology.StreamsBuilder;\nimport io.stoatflow.runtime.StoatFlowRuntime;\nimport org.apache.kafka.common.serialization.Serdes;\n\npublic class Main {\n\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        runtime.start();\n        runtime.awaitTermination();\n    }\n\n    private static void buildTopology(StreamsBuilder builder) {\n        builder.addStateStore(Stores.keyValueStoreBuilder(\n            Stores.persistentKeyValueStore(\"counts\"),\n            Serdes.String(),\n            Serdes.Long()));\n\n        KStream\u003CString, String> input = builder.stream(\"input\", Consumed.as(\"source\"));\n        input\n            .process(CountingProcessor::new, Named.as(\"count\"))\n            .to(\"counts-out\", Produced.\u003CString, Long>as(\"sink\").withValueSerde(Serdes.Long()));\n    }\n}\n",[347,6516,6517,6541,6567,6591,6615,6640,6664,6686,6714,6718,6729,6733,6757,6776,6788,6812,6832,6851,6856,6861,6872,6882,6886,6890,6911,6930,6949,6960,6970,6974,7029,7034,7066,7123,7127],{"__ignoreMap":541},[545,6518,6519,6521,6523,6525,6527,6529,6531,6533,6535,6537,6539],{"class":547,"line":548},[545,6520,552],{"class":551},[545,6522,738],{"class":584},[545,6524,334],{"class":647},[545,6526,743],{"class":584},[545,6528,334],{"class":647},[545,6530,748],{"class":584},[545,6532,334],{"class":647},[545,6534,2182],{"class":584},[545,6536,334],{"class":647},[545,6538,1878],{"class":584},[545,6540,760],{"class":647},[545,6542,6543,6545,6547,6549,6551,6553,6555,6557,6560,6562,6565],{"class":547,"line":559},[545,6544,552],{"class":551},[545,6546,738],{"class":584},[545,6548,334],{"class":647},[545,6550,743],{"class":584},[545,6552,334],{"class":647},[545,6554,748],{"class":584},[545,6556,334],{"class":647},[545,6558,6559],{"class":584},"topology",[545,6561,334],{"class":647},[545,6563,6564],{"class":584},"Consumed",[545,6566,760],{"class":647},[545,6568,6569,6571,6573,6575,6577,6579,6581,6583,6585,6587,6589],{"class":547,"line":567},[545,6570,552],{"class":551},[545,6572,738],{"class":584},[545,6574,334],{"class":647},[545,6576,743],{"class":584},[545,6578,334],{"class":647},[545,6580,748],{"class":584},[545,6582,334],{"class":647},[545,6584,6559],{"class":584},[545,6586,334],{"class":647},[545,6588,1369],{"class":584},[545,6590,760],{"class":647},[545,6592,6593,6595,6597,6599,6601,6603,6605,6607,6609,6611,6613],{"class":547,"line":574},[545,6594,552],{"class":551},[545,6596,738],{"class":584},[545,6598,334],{"class":647},[545,6600,743],{"class":584},[545,6602,334],{"class":647},[545,6604,748],{"class":584},[545,6606,334],{"class":647},[545,6608,6559],{"class":584},[545,6610,334],{"class":647},[545,6612,1591],{"class":584},[545,6614,760],{"class":647},[545,6616,6617,6619,6621,6623,6625,6627,6629,6631,6633,6635,6638],{"class":547,"line":608},[545,6618,552],{"class":551},[545,6620,738],{"class":584},[545,6622,334],{"class":647},[545,6624,743],{"class":584},[545,6626,334],{"class":647},[545,6628,748],{"class":584},[545,6630,334],{"class":647},[545,6632,6559],{"class":584},[545,6634,334],{"class":647},[545,6636,6637],{"class":584},"Produced",[545,6639,760],{"class":647},[545,6641,6642,6644,6646,6648,6650,6652,6654,6656,6658,6660,6662],{"class":547,"line":638},[545,6643,552],{"class":551},[545,6645,738],{"class":584},[545,6647,334],{"class":647},[545,6649,743],{"class":584},[545,6651,334],{"class":647},[545,6653,748],{"class":584},[545,6655,334],{"class":647},[545,6657,6559],{"class":584},[545,6659,334],{"class":647},[545,6661,2552],{"class":584},[545,6663,760],{"class":647},[545,6665,6666,6668,6670,6672,6674,6676,6679,6681,6684],{"class":547,"line":657},[545,6667,552],{"class":551},[545,6669,738],{"class":584},[545,6671,334],{"class":647},[545,6673,743],{"class":584},[545,6675,334],{"class":647},[545,6677,6678],{"class":584},"runtime",[545,6680,334],{"class":647},[545,6682,6683],{"class":584},"StoatFlowRuntime",[545,6685,760],{"class":647},[545,6687,6688,6690,6692,6694,6696,6698,6700,6702,6704,6706,6708,6710,6712],{"class":547,"line":676},[545,6689,552],{"class":551},[545,6691,2219],{"class":584},[545,6693,334],{"class":647},[545,6695,2224],{"class":584},[545,6697,334],{"class":647},[545,6699,2229],{"class":584},[545,6701,334],{"class":647},[545,6703,2234],{"class":584},[545,6705,334],{"class":647},[545,6707,2239],{"class":584},[545,6709,334],{"class":647},[545,6711,2244],{"class":584},[545,6713,760],{"class":647},[545,6715,6716],{"class":547,"line":683},[545,6717,571],{"emptyLinePlaceholder":570},[545,6719,6720,6722,6724,6727],{"class":547,"line":708},[545,6721,793],{"class":611},[545,6723,796],{"class":611},[545,6725,6726],{"class":580}," Main",[545,6728,827],{"class":647},[545,6730,6731],{"class":547,"line":714},[545,6732,571],{"emptyLinePlaceholder":570},[545,6734,6735,6737,6739,6741,6743,6745,6747,6750,6753,6755],{"class":547,"line":720},[545,6736,844],{"class":611},[545,6738,5511],{"class":611},[545,6740,847],{"class":611},[545,6742,6212],{"class":555},[545,6744,695],{"class":647},[545,6746,593],{"class":611},[545,6748,6749],{"class":647},"[]",[545,6751,6752],{"class":866}," args",[545,6754,870],{"class":647},[545,6756,827],{"class":647},[545,6758,6759,6762,6765,6767,6770,6772,6774],{"class":547,"line":950},[545,6760,6761],{"class":611},"        var",[545,6763,6764],{"class":866}," runtime",[545,6766,648],{"class":647},[545,6768,6769],{"class":866}," StoatFlowRuntime",[545,6771,334],{"class":647},[545,6773,6230],{"class":555},[545,6775,2021],{"class":647},[545,6777,6778,6781,6784,6786],{"class":547,"line":955},[545,6779,6780],{"class":584},"            Main",[545,6782,6783],{"class":551},"::",[545,6785,6245],{"class":584},[545,6787,4341],{"class":647},[545,6789,6790,6793,6795,6798,6800,6803,6805,6808,6810],{"class":547,"line":960},[545,6791,6792],{"class":584},"            builder ",[545,6794,4349],{"class":647},[545,6796,6797],{"class":866}," builder",[545,6799,334],{"class":647},[545,6801,6802],{"class":555},"streamsConfigOverrides",[545,6804,695],{"class":647},[545,6806,6807],{"class":584},"cfg ",[545,6809,4349],{"class":647},[545,6811,827],{"class":647},[545,6813,6814,6817,6819,6822,6824,6826,6828,6830],{"class":547,"line":2064},[545,6815,6816],{"class":866},"                cfg",[545,6818,334],{"class":647},[545,6820,6821],{"class":555},"defaultKeySerde",[545,6823,695],{"class":647},[545,6825,2244],{"class":866},[545,6827,334],{"class":647},[545,6829,593],{"class":555},[545,6831,947],{"class":647},[545,6833,6834,6836,6838,6841,6843,6845,6847,6849],{"class":547,"line":2070},[545,6835,6816],{"class":866},[545,6837,334],{"class":647},[545,6839,6840],{"class":555},"defaultValueSerde",[545,6842,695],{"class":647},[545,6844,2244],{"class":866},[545,6846,334],{"class":647},[545,6848,593],{"class":555},[545,6850,947],{"class":647},[545,6852,6853],{"class":547,"line":2076},[545,6854,6855],{"class":647},"            })\n",[545,6857,6858],{"class":547,"line":2081},[545,6859,6860],{"class":647},"        );\n",[545,6862,6863,6866,6868,6870],{"class":547,"line":2086},[545,6864,6865],{"class":866},"        runtime",[545,6867,334],{"class":647},[545,6869,5020],{"class":555},[545,6871,890],{"class":647},[545,6873,6874,6876,6878,6880],{"class":547,"line":2459},[545,6875,6865],{"class":866},[545,6877,334],{"class":647},[545,6879,6317],{"class":555},[545,6881,890],{"class":647},[545,6883,6884],{"class":547,"line":2471},[545,6885,717],{"class":647},[545,6887,6888],{"class":547,"line":2479},[545,6889,571],{"emptyLinePlaceholder":570},[545,6891,6892,6894,6896,6898,6900,6902,6905,6907,6909],{"class":547,"line":2484},[545,6893,2957],{"class":611},[545,6895,5511],{"class":611},[545,6897,847],{"class":611},[545,6899,6336],{"class":555},[545,6901,695],{"class":647},[545,6903,6904],{"class":584},"StreamsBuilder ",[545,6906,2746],{"class":866},[545,6908,870],{"class":647},[545,6910,827],{"class":647},[545,6912,6913,6916,6918,6920,6922,6924,6926,6928],{"class":547,"line":2490},[545,6914,6915],{"class":866},"        builder",[545,6917,334],{"class":647},[545,6919,2597],{"class":555},[545,6921,695],{"class":647},[545,6923,1878],{"class":866},[545,6925,334],{"class":647},[545,6927,2029],{"class":555},[545,6929,2021],{"class":647},[545,6931,6932,6935,6937,6939,6941,6943,6945,6947],{"class":547,"line":2495},[545,6933,6934],{"class":866},"            Stores",[545,6936,334],{"class":647},[545,6938,2039],{"class":555},[545,6940,695],{"class":647},[545,6942,1516],{"class":1515},[545,6944,3361],{"class":1407},[545,6946,1516],{"class":1515},[545,6948,2046],{"class":647},[545,6950,6951,6954,6956,6958],{"class":547,"line":4034},[545,6952,6953],{"class":866},"            Serdes",[545,6955,334],{"class":647},[545,6957,593],{"class":555},[545,6959,2056],{"class":647},[545,6961,6962,6964,6966,6968],{"class":547,"line":4039},[545,6963,6953],{"class":866},[545,6965,334],{"class":647},[545,6967,2950],{"class":555},[545,6969,1293],{"class":647},[545,6971,6972],{"class":547,"line":4463},[545,6973,571],{"emptyLinePlaceholder":570},[545,6975,6976,6979,6981,6983,6985,6987,6989,6992,6994,6996,6998,7000,7002,7004,7007,7009,7011,7014,7016,7018,7020,7022,7025,7027],{"class":547,"line":4476},[545,6977,6978],{"class":584},"        KStream",[545,6980,590],{"class":647},[545,6982,593],{"class":611},[545,6984,814],{"class":647},[545,6986,817],{"class":611},[545,6988,824],{"class":647},[545,6990,6991],{"class":866}," input",[545,6993,648],{"class":647},[545,6995,6797],{"class":866},[545,6997,334],{"class":647},[545,6999,6417],{"class":555},[545,7001,695],{"class":647},[545,7003,1516],{"class":1515},[545,7005,7006],{"class":1407},"input",[545,7008,1516],{"class":1515},[545,7010,814],{"class":647},[545,7012,7013],{"class":866}," Consumed",[545,7015,334],{"class":647},[545,7017,1510],{"class":555},[545,7019,695],{"class":647},[545,7021,1516],{"class":1515},[545,7023,7024],{"class":1407},"source",[545,7026,1516],{"class":1515},[545,7028,1524],{"class":647},[545,7030,7031],{"class":547,"line":4494},[545,7032,7033],{"class":584},"        input\n",[545,7035,7036,7039,7041,7043,7045,7047,7049,7051,7053,7055,7057,7059,7062,7064],{"class":547,"line":4506},[545,7037,7038],{"class":647},"            .",[545,7040,1310],{"class":555},[545,7042,695],{"class":647},[545,7044,6454],{"class":584},[545,7046,1500],{"class":551},[545,7048,814],{"class":647},[545,7050,1505],{"class":866},[545,7052,334],{"class":647},[545,7054,1510],{"class":555},[545,7056,695],{"class":647},[545,7058,1516],{"class":1515},[545,7060,7061],{"class":1407},"count",[545,7063,1516],{"class":1515},[545,7065,1411],{"class":647},[545,7067,7068,7070,7072,7074,7076,7079,7081,7083,7086,7088,7090,7092,7094,7096,7098,7100,7102,7104,7107,7109,7111,7113,7115,7117,7119,7121],{"class":547,"line":4511},[545,7069,7038],{"class":647},[545,7071,6472],{"class":555},[545,7073,695],{"class":647},[545,7075,1516],{"class":1515},[545,7077,7078],{"class":1407},"counts-out",[545,7080,1516],{"class":1515},[545,7082,814],{"class":647},[545,7084,7085],{"class":584}," Produced",[545,7087,334],{"class":647},[545,7089,590],{"class":611},[545,7091,593],{"class":584},[545,7093,814],{"class":647},[545,7095,3267],{"class":584},[545,7097,824],{"class":611},[545,7099,1510],{"class":555},[545,7101,695],{"class":647},[545,7103,1516],{"class":1515},[545,7105,7106],{"class":1407},"sink",[545,7108,1516],{"class":1515},[545,7110,364],{"class":647},[545,7112,6500],{"class":555},[545,7114,695],{"class":647},[545,7116,2244],{"class":866},[545,7118,334],{"class":647},[545,7120,2950],{"class":555},[545,7122,1293],{"class":647},[545,7124,7125],{"class":547,"line":4516},[545,7126,717],{"class":647},[545,7128,7129],{"class":547,"line":5088},[545,7130,723],{"class":647},[418,7132,7134],{"id":7133},"next-steps","Next steps",[339,7136,7137,7144,7154,7162,7169],{},[342,7138,7139,7143],{},[324,7140,7141],{},[329,7142,100],{"href":101}," — store types, serdes, changelog backing, and querying.",[342,7145,7146,7150,7151,364],{},[324,7147,7148],{},[329,7149,140],{"href":141}," — topology-level periodic record generation (",[347,7152,7153],{},"StreamsBuilder.scheduled()",[342,7155,7156,7161],{},[324,7157,7158],{},[329,7159,7160],{"href":106},"Testing"," — drive processors, advance time, and trigger punctuators with the in-memory test driver.",[342,7163,7164,7168],{},[324,7165,7166],{},[329,7167,1851],{"href":63}," — the execution model behind per-key serialized processing and timer callbacks.",[342,7170,7171,7175],{},[324,7172,7173],{},[329,7174,82],{"href":83}," — Processor API parity and the StoatFlow-specific extensions (timers, time notions).",[7177,7178,7179],"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 .sUxyF, html code.shiki .sUxyF{--shiki-default:#2E8F82}html pre.shiki code .suHK_, html code.shiki .suHK_{--shiki-default:#393A34}html pre.shiki code .si04Y, html code.shiki .si04Y{--shiki-default:#AB5959}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 .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 .spphp, html code.shiki .spphp{--shiki-default:#B56959}html pre.shiki code .sSP4y, html code.shiki .sSP4y{--shiki-default:#B5695977}html pre.shiki code .sEi1f, html code.shiki .sEi1f{--shiki-default:#A65E2B}html pre.shiki code .s-TwI, html code.shiki .s-TwI{--shiki-default:#2F798A}",{"title":541,"searchDepth":559,"depth":559,"links":7181},[7182,7186,7187,7191,7196,7201,7205,7206],{"id":420,"depth":559,"text":421,"children":7183},[7184,7185],{"id":519,"depth":567,"text":520},{"id":965,"depth":567,"text":966},{"id":1304,"depth":559,"text":1305},{"id":1597,"depth":559,"text":373,"children":7188},[7189,7190],{"id":1613,"depth":567,"text":1614},{"id":1707,"depth":567,"text":1708},{"id":1854,"depth":559,"text":1351,"children":7192},[7193,7194,7195],{"id":1864,"depth":567,"text":1865},{"id":2545,"depth":567,"text":2546},{"id":2867,"depth":567,"text":2868},{"id":3554,"depth":559,"text":389,"children":7197},[7198,7199,7200],{"id":3590,"depth":567,"text":3591},{"id":3684,"depth":567,"text":3685},{"id":3751,"depth":567,"text":3752},{"id":4538,"depth":559,"text":399,"children":7202},[7203,7204],{"id":4556,"depth":567,"text":4557},{"id":4574,"depth":567,"text":4575},{"id":6136,"depth":559,"text":6137},{"id":7133,"depth":559,"text":7134},"Write custom record-by-record logic with Processor and FixedKeyProcessor — forward, access state, schedule punctuators, and register key-based timers.","md",{},{"icon":138},"how-to",{"title":135,"description":7207},"Hmd5n3uwG6_SEhk5ORv_oIlmtGslSlzg7wFT__HYDBw",[7215,7217],{"title":130,"path":131,"stem":132,"description":7216,"icon":133,"children":-1},"Combine two streams or tables on a shared key — stream-stream windowed joins, stream-table enrichment lookups, table-table joins, foreign-key joins, and co-grouping.",{"title":140,"path":141,"stem":142,"description":7218,"icon":143,"children":-1},"Generate records on an interval or a cron schedule with StreamsBuilder.scheduled() — a topology source that emits without consuming from Kafka.",1783713359250]