[{"data":1,"prerenderedAt":4758},["ShallowReactive",2],{"highlight:import \"github.com/zoobz-io/flume\"\n\n// 1. Register components once\nfactory := flume.New[Order]()\nfactory.Add(\n    pipz.Apply(\"validate\", func(ctx context.Context, o Order) (Order, error) {\n        if o.Total \u003C= 0 { return o, fmt.Errorf(\"invalid total\") }\n        return o, nil\n    }),\n    pipz.Apply(\"apply-discount\", func(ctx context.Context, o Order) (Order, error) {\n        o.Total *= 0.9\n        return o, nil\n    }),\n)\nfactory.AddPredicate(flume.Predicate[Order]{\n    Name: \"is-premium\",\n    Predicate: func(_ context.Context, o Order) bool { return o.Tier == \"premium\" },\n})\n\n// 2. Define structure in YAML — not in code\npipeline, _ := factory.BuildFromYAML(`\ntype: sequence\nchildren:\n  - ref: validate\n  - type: filter\n    predicate: is-premium\n    then:\n      ref: apply-discount\n`)\n\n// 3. Process data\nresult, _ := pipeline.Process(ctx, order)\n\n// 4. Update behavior at runtime — no restart\nfactory.SetSchema(\"order-pipeline\", newSchema)":3,"footer-resources":4,"search-sections-flume":2897,"nav-flume":4653,"content-tree-flume":4706,"content-table-nav-flume":4732},"\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-keyword)\">import\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\"> \"github.com/zoobz-io/flume\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-comment)\">// 1. Register components once\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-text)\">factory\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> :=\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> flume\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">New\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">[\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\">Order\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">]()\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-text)\">factory\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">Add\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-text)\">    pipz\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">Apply\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\">\"validate\"\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-keyword)\"> func\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003Cspan style=\"color:var(--shiki-parameter)\">ctx\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\"> context\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\">Context\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-parameter)\"> o\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\"> Order\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\"> (\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\">Order\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\"> error\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-operator)\">        if\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> o\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\">Total\u003C/span>\u003Cspan style=\"color:var(--shiki-operator)\"> &#x3C;=\u003C/span>\u003Cspan style=\"color:var(--shiki-number)\"> 0\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\"> {\u003C/span>\u003Cspan style=\"color:var(--shiki-operator)\"> return\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> o\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> fmt\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">Errorf\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\">\"invalid total\"\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-operator)\">        return\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> o\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-keyword)\"> nil\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-punctuation)\">    }),\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-text)\">    pipz\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">Apply\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\">\"apply-discount\"\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-keyword)\"> func\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003Cspan style=\"color:var(--shiki-parameter)\">ctx\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\"> context\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\">Context\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-parameter)\"> o\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\"> Order\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\"> (\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\">Order\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\"> error\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-text)\">        o\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\">Total\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> *=\u003C/span>\u003Cspan style=\"color:var(--shiki-number)\"> 0.9\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-operator)\">        return\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> o\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-keyword)\"> nil\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-punctuation)\">    }),\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-text)\">factory\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">AddPredicate\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\">flume\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\">Predicate\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">[\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\">Order\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">]{\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-property)\">    Name\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">:\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\"> \"is-premium\"\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-property)\">    Predicate\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">:\u003C/span>\u003Cspan style=\"color:var(--shiki-keyword)\"> func\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003Cspan style=\"color:var(--shiki-parameter)\">_\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\"> context\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\">Context\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-parameter)\"> o\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\"> Order\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003Cspan style=\"color:var(--shiki-type)\"> bool\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\"> {\u003C/span>\u003Cspan style=\"color:var(--shiki-operator)\"> return\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> o\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\">Tier\u003C/span>\u003Cspan style=\"color:var(--shiki-operator)\"> ==\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\"> \"premium\"\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-punctuation)\">})\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-comment)\">// 2. Define structure in YAML — not in code\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-text)\">pipeline\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> _\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> :=\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> factory\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">BuildFromYAML\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\">`\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-string)\">type: sequence\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-string)\">children:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-string)\">  - ref: validate\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-string)\">  - type: filter\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-string)\">    predicate: is-premium\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-string)\">    then:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-string)\">      ref: apply-discount\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-string)\">`\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-comment)\">// 3. Process data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-text)\">result\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> _\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> :=\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> pipeline\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">Process\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\">ctx\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> order\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-comment)\">// 4. Update behavior at runtime — no restart\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:var(--shiki-text)\">factory\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">.\u003C/span>\u003Cspan style=\"color:var(--shiki-function)\">SetSchema\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">(\u003C/span>\u003Cspan style=\"color:var(--shiki-string)\">\"order-pipeline\"\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">,\u003C/span>\u003Cspan style=\"color:var(--shiki-text)\"> newSchema\u003C/span>\u003Cspan style=\"color:var(--shiki-punctuation)\">)\u003C/span>\u003C/span>",[5,1864,2317],{"id":6,"title":7,"body":8,"description":104,"extension":1857,"icon":1858,"meta":1859,"navigation":494,"path":1860,"seo":1861,"stem":1862,"__hash__":1863},"resources/readme.md","README",{"type":9,"value":10,"toc":1840},"minimark",[11,16,84,93,98,621,625,628,645,649,1250,1254,1360,1364,1411,1415,1421,1424,1532,1544,1547,1550,1693,1697,1704,1709,1739,1743,1774,1778,1787,1791,1815,1819,1827,1830,1836],[12,13,15],"h1",{"id":14},"flume","Flume",[17,18,19,30,38,46,54,62,69,76],"p",{},[20,21,25],"a",{"href":22,"rel":23},"https://github.com/zoobz-io/flume/actions/workflows/ci.yml",[24],"nofollow",[26,27],"img",{"alt":28,"src":29},"CI Status","https://github.com/zoobz-io/flume/workflows/CI/badge.svg",[20,31,34],{"href":32,"rel":33},"https://codecov.io/gh/zoobz-io/flume",[24],[26,35],{"alt":36,"src":37},"codecov","https://codecov.io/gh/zoobz-io/flume/graph/badge.svg?branch=main",[20,39,42],{"href":40,"rel":41},"https://goreportcard.com/report/github.com/zoobz-io/flume",[24],[26,43],{"alt":44,"src":45},"Go Report Card","https://goreportcard.com/badge/github.com/zoobz-io/flume",[20,47,50],{"href":48,"rel":49},"https://github.com/zoobz-io/flume/security/code-scanning",[24],[26,51],{"alt":52,"src":53},"CodeQL","https://github.com/zoobz-io/flume/workflows/CodeQL/badge.svg",[20,55,58],{"href":56,"rel":57},"https://pkg.go.dev/github.com/zoobz-io/flume",[24],[26,59],{"alt":60,"src":61},"Go Reference","https://pkg.go.dev/badge/github.com/zoobz-io/flume.svg",[20,63,65],{"href":64},"LICENSE",[26,66],{"alt":67,"src":68},"License","https://img.shields.io/github/license/zoobz-io/flume",[20,70,72],{"href":71},"go.mod",[26,73],{"alt":74,"src":75},"Go Version","https://img.shields.io/github/go-mod/go-version/zoobz-io/flume",[20,77,80],{"href":78,"rel":79},"https://github.com/zoobz-io/flume/releases",[24],[26,81],{"alt":82,"src":83},"Release","https://img.shields.io/github/v/release/zoobz-io/flume",[17,85,86,87,92],{},"A dynamic pipeline factory for ",[20,88,91],{"href":89,"rel":90},"https://github.com/zoobz-io/pipz",[24],"pipz"," that enables schema-driven pipeline construction with hot-reloading capabilities.",[94,95,97],"h2",{"id":96},"logic-in-code-structure-in-schema","Logic in Code, Structure in Schema",[99,100,105],"pre",{"className":101,"code":102,"language":103,"meta":104,"style":104},"language-go shiki shiki-themes","// 1. Register components\nfactory := flume.New[Order]()\nfactory.Add(\n    pipz.Apply(\"validate\", func(ctx context.Context, o Order) (Order, error) {\n        if o.Total \u003C= 0 {\n            return o, fmt.Errorf(\"invalid total\")\n        }\n        return o, nil\n    }),\n    pipz.Apply(\"apply-discount\", func(ctx context.Context, o Order) (Order, error) {\n        o.Total *= 0.9 // 10% discount\n        return o, nil\n    }),\n)\nfactory.AddPredicate(flume.Predicate[Order]{\n    Name:      \"is-premium\",\n    Predicate: func(ctx context.Context, o Order) bool { return o.Tier == \"premium\" },\n})\n\n// 2. Build from schema\npipeline, _ := factory.BuildFromYAML(`\ntype: sequence\nchildren:\n  - ref: validate\n  - type: filter\n    predicate: is-premium\n    then:\n      ref: apply-discount\n`)\n\n// 3. Process data\nresult, err := pipeline.Process(ctx, order)\n","go","",[106,107,108,117,148,161,226,249,275,281,294,300,348,367,378,383,388,414,430,483,489,496,502,528,534,540,546,552,558,564,570,578,583,589],"code",{"__ignoreMap":104},[109,110,113],"span",{"class":111,"line":112},"line",1,[109,114,116],{"class":115},"sLkEo","// 1. Register components\n",[109,118,120,124,127,130,134,138,141,145],{"class":111,"line":119},2,[109,121,123],{"class":122},"sh8_p","factory",[109,125,126],{"class":122}," :=",[109,128,129],{"class":122}," flume",[109,131,133],{"class":132},"sq5bi",".",[109,135,137],{"class":136},"s5klm","New",[109,139,140],{"class":132},"[",[109,142,144],{"class":143},"sYBwO","Order",[109,146,147],{"class":132},"]()\n",[109,149,151,153,155,158],{"class":111,"line":150},3,[109,152,123],{"class":122},[109,154,133],{"class":132},[109,156,157],{"class":136},"Add",[109,159,160],{"class":132},"(\n",[109,162,164,167,169,172,175,179,182,186,188,192,195,197,200,202,205,208,211,214,216,218,221,223],{"class":111,"line":163},4,[109,165,166],{"class":122},"    pipz",[109,168,133],{"class":132},[109,170,171],{"class":136},"Apply",[109,173,174],{"class":132},"(",[109,176,178],{"class":177},"sxAnc","\"validate\"",[109,180,181],{"class":132},",",[109,183,185],{"class":184},"sUt3r"," func",[109,187,174],{"class":132},[109,189,191],{"class":190},"sSYET","ctx",[109,193,194],{"class":143}," context",[109,196,133],{"class":132},[109,198,199],{"class":143},"Context",[109,201,181],{"class":132},[109,203,204],{"class":190}," o",[109,206,207],{"class":143}," Order",[109,209,210],{"class":132},")",[109,212,213],{"class":132}," (",[109,215,144],{"class":143},[109,217,181],{"class":132},[109,219,220],{"class":143}," error",[109,222,210],{"class":132},[109,224,225],{"class":132}," {\n",[109,227,229,233,235,237,240,243,247],{"class":111,"line":228},5,[109,230,232],{"class":231},"sW3Qg","        if",[109,234,204],{"class":122},[109,236,133],{"class":132},[109,238,239],{"class":122},"Total",[109,241,242],{"class":231}," \u003C=",[109,244,246],{"class":245},"sMAmT"," 0",[109,248,225],{"class":132},[109,250,252,255,257,259,262,264,267,269,272],{"class":111,"line":251},6,[109,253,254],{"class":231},"            return",[109,256,204],{"class":122},[109,258,181],{"class":132},[109,260,261],{"class":122}," fmt",[109,263,133],{"class":132},[109,265,266],{"class":136},"Errorf",[109,268,174],{"class":132},[109,270,271],{"class":177},"\"invalid total\"",[109,273,274],{"class":132},")\n",[109,276,278],{"class":111,"line":277},7,[109,279,280],{"class":132},"        }\n",[109,282,284,287,289,291],{"class":111,"line":283},8,[109,285,286],{"class":231},"        return",[109,288,204],{"class":122},[109,290,181],{"class":132},[109,292,293],{"class":184}," nil\n",[109,295,297],{"class":111,"line":296},9,[109,298,299],{"class":132},"    }),\n",[109,301,303,305,307,309,311,314,316,318,320,322,324,326,328,330,332,334,336,338,340,342,344,346],{"class":111,"line":302},10,[109,304,166],{"class":122},[109,306,133],{"class":132},[109,308,171],{"class":136},[109,310,174],{"class":132},[109,312,313],{"class":177},"\"apply-discount\"",[109,315,181],{"class":132},[109,317,185],{"class":184},[109,319,174],{"class":132},[109,321,191],{"class":190},[109,323,194],{"class":143},[109,325,133],{"class":132},[109,327,199],{"class":143},[109,329,181],{"class":132},[109,331,204],{"class":190},[109,333,207],{"class":143},[109,335,210],{"class":132},[109,337,213],{"class":132},[109,339,144],{"class":143},[109,341,181],{"class":132},[109,343,220],{"class":143},[109,345,210],{"class":132},[109,347,225],{"class":132},[109,349,351,354,356,358,361,364],{"class":111,"line":350},11,[109,352,353],{"class":122},"        o",[109,355,133],{"class":132},[109,357,239],{"class":122},[109,359,360],{"class":122}," *=",[109,362,363],{"class":245}," 0.9",[109,365,366],{"class":115}," // 10% discount\n",[109,368,370,372,374,376],{"class":111,"line":369},12,[109,371,286],{"class":231},[109,373,204],{"class":122},[109,375,181],{"class":132},[109,377,293],{"class":184},[109,379,381],{"class":111,"line":380},13,[109,382,299],{"class":132},[109,384,386],{"class":111,"line":385},14,[109,387,274],{"class":132},[109,389,391,393,395,398,400,402,404,407,409,411],{"class":111,"line":390},15,[109,392,123],{"class":122},[109,394,133],{"class":132},[109,396,397],{"class":136},"AddPredicate",[109,399,174],{"class":132},[109,401,14],{"class":143},[109,403,133],{"class":132},[109,405,406],{"class":143},"Predicate",[109,408,140],{"class":132},[109,410,144],{"class":143},[109,412,413],{"class":132},"]{\n",[109,415,417,421,424,427],{"class":111,"line":416},16,[109,418,420],{"class":419},"sBGCq","    Name",[109,422,423],{"class":132},":",[109,425,426],{"class":177},"      \"is-premium\"",[109,428,429],{"class":132},",\n",[109,431,433,436,438,440,442,444,446,448,450,452,454,456,458,461,464,467,469,471,474,477,480],{"class":111,"line":432},17,[109,434,435],{"class":419},"    Predicate",[109,437,423],{"class":132},[109,439,185],{"class":184},[109,441,174],{"class":132},[109,443,191],{"class":190},[109,445,194],{"class":143},[109,447,133],{"class":132},[109,449,199],{"class":143},[109,451,181],{"class":132},[109,453,204],{"class":190},[109,455,207],{"class":143},[109,457,210],{"class":132},[109,459,460],{"class":143}," bool",[109,462,463],{"class":132}," {",[109,465,466],{"class":231}," return",[109,468,204],{"class":122},[109,470,133],{"class":132},[109,472,473],{"class":122},"Tier",[109,475,476],{"class":231}," ==",[109,478,479],{"class":177}," \"premium\"",[109,481,482],{"class":132}," },\n",[109,484,486],{"class":111,"line":485},18,[109,487,488],{"class":132},"})\n",[109,490,492],{"class":111,"line":491},19,[109,493,495],{"emptyLinePlaceholder":494},true,"\n",[109,497,499],{"class":111,"line":498},20,[109,500,501],{"class":115},"// 2. Build from schema\n",[109,503,505,508,510,513,515,518,520,523,525],{"class":111,"line":504},21,[109,506,507],{"class":122},"pipeline",[109,509,181],{"class":132},[109,511,512],{"class":122}," _",[109,514,126],{"class":122},[109,516,517],{"class":122}," factory",[109,519,133],{"class":132},[109,521,522],{"class":136},"BuildFromYAML",[109,524,174],{"class":132},[109,526,527],{"class":177},"`\n",[109,529,531],{"class":111,"line":530},22,[109,532,533],{"class":177},"type: sequence\n",[109,535,537],{"class":111,"line":536},23,[109,538,539],{"class":177},"children:\n",[109,541,543],{"class":111,"line":542},24,[109,544,545],{"class":177},"  - ref: validate\n",[109,547,549],{"class":111,"line":548},25,[109,550,551],{"class":177},"  - type: filter\n",[109,553,555],{"class":111,"line":554},26,[109,556,557],{"class":177},"    predicate: is-premium\n",[109,559,561],{"class":111,"line":560},27,[109,562,563],{"class":177},"    then:\n",[109,565,567],{"class":111,"line":566},28,[109,568,569],{"class":177},"      ref: apply-discount\n",[109,571,573,576],{"class":111,"line":572},29,[109,574,575],{"class":177},"`",[109,577,274],{"class":132},[109,579,581],{"class":111,"line":580},30,[109,582,495],{"emptyLinePlaceholder":494},[109,584,586],{"class":111,"line":585},31,[109,587,588],{"class":115},"// 3. Process data\n",[109,590,592,595,597,600,602,605,607,610,612,614,616,619],{"class":111,"line":591},32,[109,593,594],{"class":122},"result",[109,596,181],{"class":132},[109,598,599],{"class":122}," err",[109,601,126],{"class":122},[109,603,604],{"class":122}," pipeline",[109,606,133],{"class":132},[109,608,609],{"class":136},"Process",[109,611,174],{"class":132},[109,613,191],{"class":122},[109,615,181],{"class":132},[109,617,618],{"class":122}," order",[109,620,274],{"class":132},[94,622,624],{"id":623},"installation","Installation",[17,626,627],{},"Requires Go 1.24+",[99,629,633],{"className":630,"code":631,"language":632,"meta":104,"style":104},"language-bash shiki shiki-themes","go get github.com/zoobz-io/flume\n","bash",[106,634,635],{"__ignoreMap":104},[109,636,637,639,642],{"class":111,"line":112},[109,638,103],{"class":136},[109,640,641],{"class":177}," get",[109,643,644],{"class":177}," github.com/zoobz-io/flume\n",[94,646,648],{"id":647},"quick-start","Quick Start",[99,650,652],{"className":101,"code":651,"language":103,"meta":104,"style":104},"package main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"github.com/zoobz-io/flume\"\n    \"github.com/zoobz-io/pipz\"\n)\n\ntype Order struct {\n    ID    string\n    Total float64\n}\n\nfunc (o Order) Clone() Order { return Order{ID: o.ID, Total: o.Total} }\n\nfunc main() {\n    factory := flume.New[Order]()\n\n    // Register processors\n    factory.Add(\n        pipz.Apply(\"validate\", func(ctx context.Context, o Order) (Order, error) {\n            if o.Total \u003C= 0 {\n                return o, fmt.Errorf(\"invalid total\")\n            }\n            return o, nil\n        }),\n        pipz.Transform(\"enrich\", func(ctx context.Context, o Order) Order {\n            o.ID = \"ORD-\" + o.ID\n            return o\n        }),\n    )\n\n    // Build pipeline from YAML\n    pipeline, err := factory.BuildFromYAML(`\ntype: sequence\nchildren:\n  - ref: validate\n  - ref: enrich\n`)\n    if err != nil {\n        panic(err)\n    }\n\n    // Process\n    result, err := pipeline.Process(context.Background(), Order{ID: \"123\", Total: 99.99})\n    fmt.Printf(\"Result: %+v, Error: %v\\n\", result, err)\n}\n",[106,653,654,662,666,675,680,685,690,695,699,703,715,723,731,736,740,801,805,816,835,839,844,854,901,918,939,944,954,959,999,1024,1031,1035,1040,1045,1051,1073,1078,1083,1088,1094,1101,1117,1131,1137,1142,1148,1201,1245],{"__ignoreMap":104},[109,655,656,659],{"class":111,"line":112},[109,657,658],{"class":184},"package",[109,660,661],{"class":143}," main\n",[109,663,664],{"class":111,"line":119},[109,665,495],{"emptyLinePlaceholder":494},[109,667,668,671],{"class":111,"line":150},[109,669,670],{"class":184},"import",[109,672,674],{"class":673},"soy-K"," (\n",[109,676,677],{"class":111,"line":163},[109,678,679],{"class":177},"    \"context\"\n",[109,681,682],{"class":111,"line":228},[109,683,684],{"class":177},"    \"fmt\"\n",[109,686,687],{"class":111,"line":251},[109,688,689],{"class":177},"    \"github.com/zoobz-io/flume\"\n",[109,691,692],{"class":111,"line":277},[109,693,694],{"class":177},"    \"github.com/zoobz-io/pipz\"\n",[109,696,697],{"class":111,"line":283},[109,698,274],{"class":673},[109,700,701],{"class":111,"line":296},[109,702,495],{"emptyLinePlaceholder":494},[109,704,705,708,710,713],{"class":111,"line":302},[109,706,707],{"class":184},"type",[109,709,207],{"class":143},[109,711,712],{"class":184}," struct",[109,714,225],{"class":132},[109,716,717,720],{"class":111,"line":350},[109,718,719],{"class":419},"    ID",[109,721,722],{"class":143},"    string\n",[109,724,725,728],{"class":111,"line":369},[109,726,727],{"class":419},"    Total",[109,729,730],{"class":143}," float64\n",[109,732,733],{"class":111,"line":380},[109,734,735],{"class":132},"}\n",[109,737,738],{"class":111,"line":385},[109,739,495],{"emptyLinePlaceholder":494},[109,741,742,745,747,750,752,754,757,760,762,764,766,768,771,774,776,778,780,782,784,787,789,791,793,795,798],{"class":111,"line":390},[109,743,744],{"class":184},"func",[109,746,213],{"class":132},[109,748,749],{"class":190},"o ",[109,751,144],{"class":143},[109,753,210],{"class":132},[109,755,756],{"class":136}," Clone",[109,758,759],{"class":132},"()",[109,761,207],{"class":143},[109,763,463],{"class":132},[109,765,466],{"class":231},[109,767,207],{"class":143},[109,769,770],{"class":132},"{",[109,772,773],{"class":419},"ID",[109,775,423],{"class":132},[109,777,204],{"class":122},[109,779,133],{"class":132},[109,781,773],{"class":122},[109,783,181],{"class":132},[109,785,786],{"class":419}," Total",[109,788,423],{"class":132},[109,790,204],{"class":122},[109,792,133],{"class":132},[109,794,239],{"class":122},[109,796,797],{"class":132},"}",[109,799,800],{"class":132}," }\n",[109,802,803],{"class":111,"line":416},[109,804,495],{"emptyLinePlaceholder":494},[109,806,807,809,812,814],{"class":111,"line":432},[109,808,744],{"class":184},[109,810,811],{"class":136}," main",[109,813,759],{"class":132},[109,815,225],{"class":132},[109,817,818,821,823,825,827,829,831,833],{"class":111,"line":485},[109,819,820],{"class":122},"    factory",[109,822,126],{"class":122},[109,824,129],{"class":122},[109,826,133],{"class":132},[109,828,137],{"class":136},[109,830,140],{"class":132},[109,832,144],{"class":143},[109,834,147],{"class":132},[109,836,837],{"class":111,"line":491},[109,838,495],{"emptyLinePlaceholder":494},[109,840,841],{"class":111,"line":498},[109,842,843],{"class":115},"    // Register processors\n",[109,845,846,848,850,852],{"class":111,"line":504},[109,847,820],{"class":122},[109,849,133],{"class":132},[109,851,157],{"class":136},[109,853,160],{"class":132},[109,855,856,859,861,863,865,867,869,871,873,875,877,879,881,883,885,887,889,891,893,895,897,899],{"class":111,"line":530},[109,857,858],{"class":122},"        pipz",[109,860,133],{"class":132},[109,862,171],{"class":136},[109,864,174],{"class":132},[109,866,178],{"class":177},[109,868,181],{"class":132},[109,870,185],{"class":184},[109,872,174],{"class":132},[109,874,191],{"class":190},[109,876,194],{"class":143},[109,878,133],{"class":132},[109,880,199],{"class":143},[109,882,181],{"class":132},[109,884,204],{"class":190},[109,886,207],{"class":143},[109,888,210],{"class":132},[109,890,213],{"class":132},[109,892,144],{"class":143},[109,894,181],{"class":132},[109,896,220],{"class":143},[109,898,210],{"class":132},[109,900,225],{"class":132},[109,902,903,906,908,910,912,914,916],{"class":111,"line":536},[109,904,905],{"class":231},"            if",[109,907,204],{"class":122},[109,909,133],{"class":132},[109,911,239],{"class":122},[109,913,242],{"class":231},[109,915,246],{"class":245},[109,917,225],{"class":132},[109,919,920,923,925,927,929,931,933,935,937],{"class":111,"line":542},[109,921,922],{"class":231},"                return",[109,924,204],{"class":122},[109,926,181],{"class":132},[109,928,261],{"class":122},[109,930,133],{"class":132},[109,932,266],{"class":136},[109,934,174],{"class":132},[109,936,271],{"class":177},[109,938,274],{"class":132},[109,940,941],{"class":111,"line":548},[109,942,943],{"class":132},"            }\n",[109,945,946,948,950,952],{"class":111,"line":554},[109,947,254],{"class":231},[109,949,204],{"class":122},[109,951,181],{"class":132},[109,953,293],{"class":184},[109,955,956],{"class":111,"line":560},[109,957,958],{"class":132},"        }),\n",[109,960,961,963,965,968,970,973,975,977,979,981,983,985,987,989,991,993,995,997],{"class":111,"line":566},[109,962,858],{"class":122},[109,964,133],{"class":132},[109,966,967],{"class":136},"Transform",[109,969,174],{"class":132},[109,971,972],{"class":177},"\"enrich\"",[109,974,181],{"class":132},[109,976,185],{"class":184},[109,978,174],{"class":132},[109,980,191],{"class":190},[109,982,194],{"class":143},[109,984,133],{"class":132},[109,986,199],{"class":143},[109,988,181],{"class":132},[109,990,204],{"class":190},[109,992,207],{"class":143},[109,994,210],{"class":132},[109,996,207],{"class":143},[109,998,225],{"class":132},[109,1000,1001,1004,1006,1008,1011,1014,1017,1019,1021],{"class":111,"line":572},[109,1002,1003],{"class":122},"            o",[109,1005,133],{"class":132},[109,1007,773],{"class":122},[109,1009,1010],{"class":122}," =",[109,1012,1013],{"class":177}," \"ORD-\"",[109,1015,1016],{"class":122}," +",[109,1018,204],{"class":122},[109,1020,133],{"class":132},[109,1022,1023],{"class":122},"ID\n",[109,1025,1026,1028],{"class":111,"line":580},[109,1027,254],{"class":231},[109,1029,1030],{"class":122}," o\n",[109,1032,1033],{"class":111,"line":585},[109,1034,958],{"class":132},[109,1036,1037],{"class":111,"line":591},[109,1038,1039],{"class":132},"    )\n",[109,1041,1043],{"class":111,"line":1042},33,[109,1044,495],{"emptyLinePlaceholder":494},[109,1046,1048],{"class":111,"line":1047},34,[109,1049,1050],{"class":115},"    // Build pipeline from YAML\n",[109,1052,1054,1057,1059,1061,1063,1065,1067,1069,1071],{"class":111,"line":1053},35,[109,1055,1056],{"class":122},"    pipeline",[109,1058,181],{"class":132},[109,1060,599],{"class":122},[109,1062,126],{"class":122},[109,1064,517],{"class":122},[109,1066,133],{"class":132},[109,1068,522],{"class":136},[109,1070,174],{"class":132},[109,1072,527],{"class":177},[109,1074,1076],{"class":111,"line":1075},36,[109,1077,533],{"class":177},[109,1079,1081],{"class":111,"line":1080},37,[109,1082,539],{"class":177},[109,1084,1086],{"class":111,"line":1085},38,[109,1087,545],{"class":177},[109,1089,1091],{"class":111,"line":1090},39,[109,1092,1093],{"class":177},"  - ref: enrich\n",[109,1095,1097,1099],{"class":111,"line":1096},40,[109,1098,575],{"class":177},[109,1100,274],{"class":132},[109,1102,1104,1107,1109,1112,1115],{"class":111,"line":1103},41,[109,1105,1106],{"class":231},"    if",[109,1108,599],{"class":122},[109,1110,1111],{"class":231}," !=",[109,1113,1114],{"class":184}," nil",[109,1116,225],{"class":132},[109,1118,1120,1124,1126,1129],{"class":111,"line":1119},42,[109,1121,1123],{"class":1122},"skxcq","        panic",[109,1125,174],{"class":132},[109,1127,1128],{"class":122},"err",[109,1130,274],{"class":132},[109,1132,1134],{"class":111,"line":1133},43,[109,1135,1136],{"class":132},"    }\n",[109,1138,1140],{"class":111,"line":1139},44,[109,1141,495],{"emptyLinePlaceholder":494},[109,1143,1145],{"class":111,"line":1144},45,[109,1146,1147],{"class":115},"    // Process\n",[109,1149,1151,1154,1156,1158,1160,1162,1164,1166,1168,1171,1173,1176,1179,1181,1183,1185,1187,1190,1192,1194,1196,1199],{"class":111,"line":1150},46,[109,1152,1153],{"class":122},"    result",[109,1155,181],{"class":132},[109,1157,599],{"class":122},[109,1159,126],{"class":122},[109,1161,604],{"class":122},[109,1163,133],{"class":132},[109,1165,609],{"class":136},[109,1167,174],{"class":132},[109,1169,1170],{"class":122},"context",[109,1172,133],{"class":132},[109,1174,1175],{"class":136},"Background",[109,1177,1178],{"class":132},"(),",[109,1180,207],{"class":143},[109,1182,770],{"class":132},[109,1184,773],{"class":419},[109,1186,423],{"class":132},[109,1188,1189],{"class":177}," \"123\"",[109,1191,181],{"class":132},[109,1193,786],{"class":419},[109,1195,423],{"class":132},[109,1197,1198],{"class":245}," 99.99",[109,1200,488],{"class":132},[109,1202,1204,1207,1209,1212,1214,1217,1221,1224,1227,1231,1234,1236,1239,1241,1243],{"class":111,"line":1203},47,[109,1205,1206],{"class":122},"    fmt",[109,1208,133],{"class":132},[109,1210,1211],{"class":136},"Printf",[109,1213,174],{"class":132},[109,1215,1216],{"class":177},"\"Result: ",[109,1218,1220],{"class":1219},"scyPU","%+v",[109,1222,1223],{"class":177},", Error: ",[109,1225,1226],{"class":1219},"%v",[109,1228,1230],{"class":1229},"suWN2","\\n",[109,1232,1233],{"class":177},"\"",[109,1235,181],{"class":132},[109,1237,1238],{"class":122}," result",[109,1240,181],{"class":132},[109,1242,599],{"class":122},[109,1244,274],{"class":132},[109,1246,1248],{"class":111,"line":1247},48,[109,1249,735],{"class":132},[94,1251,1253],{"id":1252},"capabilities","Capabilities",[1255,1256,1257,1273],"table",{},[1258,1259,1260],"thead",{},[1261,1262,1263,1267,1270],"tr",{},[1264,1265,1266],"th",{},"Feature",[1264,1268,1269],{},"Description",[1264,1271,1272],{},"Docs",[1274,1275,1276,1291,1304,1318,1332,1346],"tbody",{},[1261,1277,1278,1282,1285],{},[1279,1280,1281],"td",{},"Schema-Driven Construction",[1279,1283,1284],{},"Define pipelines in YAML/JSON, build at runtime",[1279,1286,1287],{},[20,1288,1290],{"href":1289},"docs/reference/schema-format","Schema Format",[1261,1292,1293,1296,1299],{},[1279,1294,1295],{},"Hot Reloading",[1279,1297,1298],{},"Update pipeline behavior without restarts",[1279,1300,1301],{},[20,1302,1295],{"href":1303},"docs/guides/hot-reloading",[1261,1305,1306,1309,1312],{},[1279,1307,1308],{},"Lock-Free Bindings",[1279,1310,1311],{},"Concurrent-safe pipeline access with auto-sync",[1279,1313,1314],{},[20,1315,1317],{"href":1316},"docs/reference/api","API Reference",[1261,1319,1320,1323,1326],{},[1279,1321,1322],{},"Comprehensive Validation",[1279,1324,1325],{},"Schema validation with detailed error messages",[1279,1327,1328],{},[20,1329,1331],{"href":1330},"docs/guides/schema-design","Schema Design",[1261,1333,1334,1337,1340],{},[1279,1335,1336],{},"14 Connector Types",[1279,1338,1339],{},"Sequence, filter, retry, timeout, circuit breaker, and more",[1279,1341,1342],{},[20,1343,1345],{"href":1344},"docs/reference/connector-types","Connector Types",[1261,1347,1348,1351,1354],{},[1279,1349,1350],{},"Event Emission",[1279,1352,1353],{},"Built-in observability signals",[1279,1355,1356],{},[20,1357,1359],{"href":1358},"docs/guides/observability","Observability",[94,1361,1363],{"id":1362},"why-flume","Why Flume?",[1365,1366,1367,1375,1381,1387,1393,1405],"ul",{},[1368,1369,1370,1374],"li",{},[1371,1372,1373],"strong",{},"Schema-driven",": Define pipelines in YAML/JSON, not code",[1368,1376,1377,1380],{},[1371,1378,1379],{},"Hot-reloadable",": Update pipeline behavior without restarts",[1368,1382,1383,1386],{},[1371,1384,1385],{},"Type-safe",": Full generics support with compile-time safety",[1368,1388,1389,1392],{},[1371,1390,1391],{},"Composable",": Build complex flows from simple, tested components",[1368,1394,1395,1398,1399,1404],{},[1371,1396,1397],{},"Observable",": Built-in ",[20,1400,1403],{"href":1401,"rel":1402},"https://github.com/zoobz-io/capitan",[24],"capitan"," event emission",[1368,1406,1407,1410],{},[1371,1408,1409],{},"Validated",": Comprehensive schema validation with detailed error messages",[94,1412,1414],{"id":1413},"configuration-as-code","Configuration as Code",[17,1416,1417,1418,133],{},"Flume enables a pattern: ",[1371,1419,1420],{},"define once, reconfigure anywhere",[17,1422,1423],{},"Register your processing components at startup. Define pipeline structure in configuration files. Update behavior at runtime without redeployment.",[99,1425,1427],{"className":101,"code":1426,"language":103,"meta":104,"style":104},"// Components registered once\nfactory.Add(validate, enrich, notify, discount)\n\n// Structure defined in config\nfactory.SetSchema(\"checkout\", loadYAML(\"pipelines/checkout.yaml\"))\n\n// Behavior changes without restart\nfactory.SetSchema(\"checkout\", loadYAML(\"pipelines/checkout-v2.yaml\"))\n",[106,1428,1429,1434,1464,1468,1473,1500,1504,1509],{"__ignoreMap":104},[109,1430,1431],{"class":111,"line":112},[109,1432,1433],{"class":115},"// Components registered once\n",[109,1435,1436,1438,1440,1442,1444,1447,1449,1452,1454,1457,1459,1462],{"class":111,"line":119},[109,1437,123],{"class":122},[109,1439,133],{"class":132},[109,1441,157],{"class":136},[109,1443,174],{"class":132},[109,1445,1446],{"class":122},"validate",[109,1448,181],{"class":132},[109,1450,1451],{"class":122}," enrich",[109,1453,181],{"class":132},[109,1455,1456],{"class":122}," notify",[109,1458,181],{"class":132},[109,1460,1461],{"class":122}," discount",[109,1463,274],{"class":132},[109,1465,1466],{"class":111,"line":150},[109,1467,495],{"emptyLinePlaceholder":494},[109,1469,1470],{"class":111,"line":163},[109,1471,1472],{"class":115},"// Structure defined in config\n",[109,1474,1475,1477,1479,1482,1484,1487,1489,1492,1494,1497],{"class":111,"line":228},[109,1476,123],{"class":122},[109,1478,133],{"class":132},[109,1480,1481],{"class":136},"SetSchema",[109,1483,174],{"class":132},[109,1485,1486],{"class":177},"\"checkout\"",[109,1488,181],{"class":132},[109,1490,1491],{"class":136}," loadYAML",[109,1493,174],{"class":132},[109,1495,1496],{"class":177},"\"pipelines/checkout.yaml\"",[109,1498,1499],{"class":132},"))\n",[109,1501,1502],{"class":111,"line":251},[109,1503,495],{"emptyLinePlaceholder":494},[109,1505,1506],{"class":111,"line":277},[109,1507,1508],{"class":115},"// Behavior changes without restart\n",[109,1510,1511,1513,1515,1517,1519,1521,1523,1525,1527,1530],{"class":111,"line":283},[109,1512,123],{"class":122},[109,1514,133],{"class":132},[109,1516,1481],{"class":136},[109,1518,174],{"class":132},[109,1520,1486],{"class":177},[109,1522,181],{"class":132},[109,1524,1491],{"class":136},[109,1526,174],{"class":132},[109,1528,1529],{"class":177},"\"pipelines/checkout-v2.yaml\"",[109,1531,1499],{"class":132},[17,1533,1534,1535,1539,1540,1543],{},"The code defines ",[1536,1537,1538],"em",{},"what"," processors do. Configuration defines ",[1536,1541,1542],{},"how"," they combine.",[94,1545,1295],{"id":1546},"hot-reloading",[17,1548,1549],{},"Update pipelines at runtime without restarts:",[99,1551,1553],{"className":101,"code":1552,"language":103,"meta":104,"style":104},"// Register a named schema\nfactory.SetSchema(\"order-pipeline\", schema)\n\n// Create a binding with auto-sync enabled\nbinding, _ := factory.Bind(pipelineID, \"order-pipeline\", flume.WithAutoSync())\n\n// Process requests (lock-free)\nresult, _ := binding.Process(ctx, order)\n\n// Update schema - all auto-sync bindings rebuild automatically\nfactory.SetSchema(\"order-pipeline\", newSchema)\n",[106,1554,1555,1560,1580,1584,1589,1629,1633,1638,1665,1669,1674],{"__ignoreMap":104},[109,1556,1557],{"class":111,"line":112},[109,1558,1559],{"class":115},"// Register a named schema\n",[109,1561,1562,1564,1566,1568,1570,1573,1575,1578],{"class":111,"line":119},[109,1563,123],{"class":122},[109,1565,133],{"class":132},[109,1567,1481],{"class":136},[109,1569,174],{"class":132},[109,1571,1572],{"class":177},"\"order-pipeline\"",[109,1574,181],{"class":132},[109,1576,1577],{"class":122}," schema",[109,1579,274],{"class":132},[109,1581,1582],{"class":111,"line":150},[109,1583,495],{"emptyLinePlaceholder":494},[109,1585,1586],{"class":111,"line":163},[109,1587,1588],{"class":115},"// Create a binding with auto-sync enabled\n",[109,1590,1591,1594,1596,1598,1600,1602,1604,1607,1609,1612,1614,1617,1619,1621,1623,1626],{"class":111,"line":228},[109,1592,1593],{"class":122},"binding",[109,1595,181],{"class":132},[109,1597,512],{"class":122},[109,1599,126],{"class":122},[109,1601,517],{"class":122},[109,1603,133],{"class":132},[109,1605,1606],{"class":136},"Bind",[109,1608,174],{"class":132},[109,1610,1611],{"class":122},"pipelineID",[109,1613,181],{"class":132},[109,1615,1616],{"class":177}," \"order-pipeline\"",[109,1618,181],{"class":132},[109,1620,129],{"class":122},[109,1622,133],{"class":132},[109,1624,1625],{"class":136},"WithAutoSync",[109,1627,1628],{"class":132},"())\n",[109,1630,1631],{"class":111,"line":251},[109,1632,495],{"emptyLinePlaceholder":494},[109,1634,1635],{"class":111,"line":277},[109,1636,1637],{"class":115},"// Process requests (lock-free)\n",[109,1639,1640,1642,1644,1646,1648,1651,1653,1655,1657,1659,1661,1663],{"class":111,"line":283},[109,1641,594],{"class":122},[109,1643,181],{"class":132},[109,1645,512],{"class":122},[109,1647,126],{"class":122},[109,1649,1650],{"class":122}," binding",[109,1652,133],{"class":132},[109,1654,609],{"class":136},[109,1656,174],{"class":132},[109,1658,191],{"class":122},[109,1660,181],{"class":132},[109,1662,618],{"class":122},[109,1664,274],{"class":132},[109,1666,1667],{"class":111,"line":296},[109,1668,495],{"emptyLinePlaceholder":494},[109,1670,1671],{"class":111,"line":302},[109,1672,1673],{"class":115},"// Update schema - all auto-sync bindings rebuild automatically\n",[109,1675,1676,1678,1680,1682,1684,1686,1688,1691],{"class":111,"line":350},[109,1677,123],{"class":122},[109,1679,133],{"class":132},[109,1681,1481],{"class":136},[109,1683,174],{"class":132},[109,1685,1572],{"class":177},[109,1687,181],{"class":132},[109,1689,1690],{"class":122}," newSchema",[109,1692,274],{"class":132},[94,1694,1696],{"id":1695},"documentation","Documentation",[17,1698,1699,1700,1703],{},"Full documentation is available in the ",[20,1701,1702],{"href":1702},"docs/"," directory:",[1705,1706,1708],"h3",{"id":1707},"learn","Learn",[1365,1710,1711,1718,1725,1732],{},[1368,1712,1713,1717],{},[20,1714,1716],{"href":1715},"docs/learn/quickstart","Quickstart"," — Your first pipeline in 5 minutes",[1368,1719,1720,1724],{},[20,1721,1723],{"href":1722},"docs/learn/core-concepts","Core Concepts"," — Factories, schemas, and components",[1368,1726,1727,1731],{},[20,1728,1730],{"href":1729},"docs/learn/architecture","Architecture"," — How Flume works under the hood",[1368,1733,1734,1738],{},[20,1735,1737],{"href":1736},"docs/learn/building-pipelines","Building Pipelines"," — From simple to complex",[1705,1740,1742],{"id":1741},"guides","Guides",[1365,1744,1745,1750,1755,1762,1769],{},[1368,1746,1747,1749],{},[20,1748,1331],{"href":1330}," — Best practices for schema structure",[1368,1751,1752,1754],{},[20,1753,1295],{"href":1303}," — Runtime pipeline updates",[1368,1756,1757,1761],{},[20,1758,1760],{"href":1759},"docs/guides/error-handling","Error Handling"," — Retry, fallback, circuit breakers",[1368,1763,1764,1768],{},[20,1765,1767],{"href":1766},"docs/guides/testing","Testing"," — Testing strategies and CI/CD linting",[1368,1770,1771,1773],{},[20,1772,1359],{"href":1358}," — Monitoring with capitan events",[1705,1775,1777],{"id":1776},"cookbook","Cookbook",[1365,1779,1780],{},[1368,1781,1782,1786],{},[20,1783,1785],{"href":1784},"docs/cookbook/common-patterns","Common Patterns"," — Recipes and patterns",[1705,1788,1790],{"id":1789},"reference","Reference",[1365,1792,1793,1798,1803,1808],{},[1368,1794,1795,1797],{},[20,1796,1317],{"href":1316}," — Complete API documentation",[1368,1799,1800,1802],{},[20,1801,1290],{"href":1289}," — YAML/JSON specification",[1368,1804,1805,1807],{},[20,1806,1345],{"href":1344}," — All 14 connectors",[1368,1809,1810,1814],{},[20,1811,1813],{"href":1812},"docs/reference/events","Events"," — Observability signals",[94,1816,1818],{"id":1817},"contributing","Contributing",[17,1820,1821,1822,1826],{},"See ",[20,1823,1825],{"href":1824},"CONTRIBUTING","CONTRIBUTING.md"," for development guidelines.",[94,1828,67],{"id":1829},"license",[17,1831,1832,1833,1835],{},"MIT License - see ",[20,1834,64],{"href":64}," file.",[1837,1838,1839],"style",{},"html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}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 .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .skxcq, html code.shiki .skxcq{--shiki-default:var(--shiki-builtin)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}html pre.shiki code .suWN2, html code.shiki .suWN2{--shiki-default:var(--shiki-tag)}",{"title":104,"searchDepth":119,"depth":119,"links":1841},[1842,1843,1844,1845,1846,1847,1848,1849,1855,1856],{"id":96,"depth":119,"text":97},{"id":623,"depth":119,"text":624},{"id":647,"depth":119,"text":648},{"id":1252,"depth":119,"text":1253},{"id":1362,"depth":119,"text":1363},{"id":1413,"depth":119,"text":1414},{"id":1546,"depth":119,"text":1295},{"id":1695,"depth":119,"text":1696,"children":1850},[1851,1852,1853,1854],{"id":1707,"depth":150,"text":1708},{"id":1741,"depth":150,"text":1742},{"id":1776,"depth":150,"text":1777},{"id":1789,"depth":150,"text":1790},{"id":1817,"depth":119,"text":1818},{"id":1829,"depth":119,"text":67},"md","book-open",{},"/readme",{"title":7,"description":104},"readme","LjAqx_lMY-Zlq3kuqe9-dcIyrawIt1pBffmeMtv78rE",{"id":1865,"title":1866,"body":1867,"description":104,"extension":1857,"icon":2311,"meta":2312,"navigation":494,"path":2313,"seo":2314,"stem":2315,"__hash__":2316},"resources/security.md","Security",{"type":9,"value":1868,"toc":2297},[1869,1873,1877,1880,1919,1923,1926,1930,1935,1938,1977,1981,1984,2033,2037,2063,2067,2070,2074,2077,2175,2179,2182,2219,2223,2226,2255,2259,2273,2277,2280,2285,2288,2294],[12,1870,1872],{"id":1871},"security-policy","Security Policy",[94,1874,1876],{"id":1875},"supported-versions","Supported Versions",[17,1878,1879],{},"We release patches for security vulnerabilities. Which versions are eligible for receiving such patches depends on the CVSS v3.0 Rating:",[1255,1881,1882,1895],{},[1258,1883,1884],{},[1261,1885,1886,1889,1892],{},[1264,1887,1888],{},"Version",[1264,1890,1891],{},"Supported",[1264,1893,1894],{},"Status",[1274,1896,1897,1908],{},[1261,1898,1899,1902,1905],{},[1279,1900,1901],{},"latest",[1279,1903,1904],{},"✅",[1279,1906,1907],{},"Active development",[1261,1909,1910,1913,1916],{},[1279,1911,1912],{},"\u003C latest",[1279,1914,1915],{},"❌",[1279,1917,1918],{},"Security fixes only for critical issues",[94,1920,1922],{"id":1921},"reporting-a-vulnerability","Reporting a Vulnerability",[17,1924,1925],{},"We take the security of flume seriously. If you have discovered a security vulnerability in this project, please report it responsibly.",[1705,1927,1929],{"id":1928},"how-to-report","How to Report",[17,1931,1932],{},[1371,1933,1934],{},"Please DO NOT report security vulnerabilities through public GitHub issues.",[17,1936,1937],{},"Instead, please report them via one of the following methods:",[1939,1940,1941,1964],"ol",{},[1368,1942,1943,1946,1947],{},[1371,1944,1945],{},"GitHub Security Advisories"," (Preferred)",[1365,1948,1949,1958,1961],{},[1368,1950,1951,1952,1957],{},"Go to the ",[20,1953,1956],{"href":1954,"rel":1955},"https://github.com/zoobz-io/flume/security",[24],"Security tab"," of this repository",[1368,1959,1960],{},"Click \"Report a vulnerability\"",[1368,1962,1963],{},"Fill out the form with details about the vulnerability",[1368,1965,1966,1969],{},[1371,1967,1968],{},"Email",[1365,1970,1971,1974],{},[1368,1972,1973],{},"Send details to the repository maintainer through GitHub profile contact information",[1368,1975,1976],{},"Use PGP encryption if possible for sensitive details",[1705,1978,1980],{"id":1979},"what-to-include","What to Include",[17,1982,1983],{},"Please include the following information (as much as you can provide) to help us better understand the nature and scope of the possible issue:",[1365,1985,1986,1992,1998,2004,2010,2015,2021,2027],{},[1368,1987,1988,1991],{},[1371,1989,1990],{},"Type of issue"," (e.g., race condition, schema injection, validation bypass, etc.)",[1368,1993,1994,1997],{},[1371,1995,1996],{},"Full paths of source file(s)"," related to the manifestation of the issue",[1368,1999,2000,2003],{},[1371,2001,2002],{},"The location of the affected source code"," (tag/branch/commit or direct URL)",[1368,2005,2006,2009],{},[1371,2007,2008],{},"Any special configuration required"," to reproduce the issue",[1368,2011,2012,2009],{},[1371,2013,2014],{},"Step-by-step instructions",[1368,2016,2017,2020],{},[1371,2018,2019],{},"Proof-of-concept or exploit code"," (if possible)",[1368,2022,2023,2026],{},[1371,2024,2025],{},"Impact of the issue",", including how an attacker might exploit the issue",[1368,2028,2029,2032],{},[1371,2030,2031],{},"Your name and affiliation"," (optional)",[1705,2034,2036],{"id":2035},"what-to-expect","What to Expect",[1365,2038,2039,2045,2051,2057],{},[1368,2040,2041,2044],{},[1371,2042,2043],{},"Acknowledgment",": We will acknowledge receipt of your vulnerability report within 48 hours",[1368,2046,2047,2050],{},[1371,2048,2049],{},"Initial Assessment",": Within 7 days, we will provide an initial assessment of the report",[1368,2052,2053,2056],{},[1371,2054,2055],{},"Resolution Timeline",": We aim to resolve critical issues within 30 days",[1368,2058,2059,2062],{},[1371,2060,2061],{},"Disclosure",": We will coordinate with you on the disclosure timeline",[1705,2064,2066],{"id":2065},"preferred-languages","Preferred Languages",[17,2068,2069],{},"We prefer all communications to be in English.",[94,2071,2073],{"id":2072},"security-best-practices","Security Best Practices",[17,2075,2076],{},"When using flume in your applications, we recommend:",[1939,2078,2079,2100,2123,2139,2155],{},[1368,2080,2081,2084],{},[1371,2082,2083],{},"Keep Dependencies Updated",[99,2085,2087],{"className":630,"code":2086,"language":632,"meta":104,"style":104},"go get -u github.com/zoobz-io/flume\n",[106,2088,2089],{"__ignoreMap":104},[109,2090,2091,2093,2095,2098],{"class":111,"line":112},[109,2092,103],{"class":136},[109,2094,641],{"class":177},[109,2096,2097],{"class":184}," -u",[109,2099,644],{"class":177},[1368,2101,2102,2105],{},[1371,2103,2104],{},"Schema Validation",[1365,2106,2107,2113,2120],{},[1368,2108,2109,2110],{},"Always validate schemas before deployment using ",[106,2111,2112],{},"ValidateSchemaStructure",[1368,2114,2115,2116,2119],{},"Use ",[106,2117,2118],{},"ValidateSchema"," at runtime with a configured factory",[1368,2121,2122],{},"Don't load schemas from untrusted sources without validation",[1368,2124,2125,2128],{},[1371,2126,2127],{},"Hot Reload Security",[1365,2129,2130,2133,2136],{},[1368,2131,2132],{},"Secure the source of schema updates (e.g., authenticated API endpoints)",[1368,2134,2135],{},"Log all schema changes for audit purposes",[1368,2137,2138],{},"Consider schema versioning for rollback capability",[1368,2140,2141,2144],{},[1371,2142,2143],{},"Resource Management",[1365,2145,2146,2149,2152],{},[1368,2147,2148],{},"Close channels when no longer needed",[1368,2150,2151],{},"Set appropriate timeouts for pipeline operations",[1368,2153,2154],{},"Configure circuit breakers for external dependencies",[1368,2156,2157,2160],{},[1371,2158,2159],{},"Concurrency Safety",[1365,2161,2162,2169,2172],{},[1368,2163,2164,2165,2168],{},"Ensure your data type's ",[106,2166,2167],{},"Clone()"," method creates deep copies",[1368,2170,2171],{},"Don't share mutable state across processors without synchronization",[1368,2173,2174],{},"Be aware that concurrent/race nodes run in parallel",[94,2176,2178],{"id":2177},"security-features","Security Features",[17,2180,2181],{},"flume includes several built-in security features:",[1365,2183,2184,2190,2195,2201,2207,2213],{},[1368,2185,2186,2189],{},[1371,2187,2188],{},"Type Safety",": Go generics ensure compile-time type checking",[1368,2191,2192,2194],{},[1371,2193,2104],{},": Comprehensive validation catches errors before building",[1368,2196,2197,2200],{},[1371,2198,2199],{},"Reference Validation",": All processor/predicate/condition references verified",[1368,2202,2203,2206],{},[1371,2204,2205],{},"Thread Safety",": Atomic operations for hot-reload scenarios",[1368,2208,2209,2212],{},[1371,2210,2211],{},"Timeout Enforcement",": Built-in timeout connector prevents runaway operations",[1368,2214,2215,2218],{},[1371,2216,2217],{},"Circuit Breakers",": Built-in circuit breaker pattern for fault isolation",[94,2220,2222],{"id":2221},"automated-security-scanning","Automated Security Scanning",[17,2224,2225],{},"This project uses:",[1365,2227,2228,2233,2239,2245],{},[1368,2229,2230,2232],{},[1371,2231,52],{},": GitHub's semantic code analysis for security vulnerabilities",[1368,2234,2235,2238],{},[1371,2236,2237],{},"golangci-lint",": Static analysis including security linters (gosec)",[1368,2240,2241,2244],{},[1371,2242,2243],{},"Codecov",": Coverage tracking to ensure security-critical code is tested",[1368,2246,2247,2250,2251,2254],{},[1371,2248,2249],{},"Race Detection",": Tests run with ",[106,2252,2253],{},"-race"," flag to detect data races",[94,2256,2258],{"id":2257},"vulnerability-disclosure-policy","Vulnerability Disclosure Policy",[1365,2260,2261,2264,2267,2270],{},[1368,2262,2263],{},"Security vulnerabilities will be disclosed via GitHub Security Advisories",[1368,2265,2266],{},"We follow a 90-day disclosure timeline for non-critical issues",[1368,2268,2269],{},"Critical vulnerabilities may be disclosed sooner after patches are available",[1368,2271,2272],{},"We will credit reporters who follow responsible disclosure practices",[94,2274,2276],{"id":2275},"credits","Credits",[17,2278,2279],{},"We thank the following individuals for responsibly disclosing security issues:",[17,2281,2282],{},[1536,2283,2284],{},"This list is currently empty. Be the first to help improve our security!",[2286,2287],"hr",{},[17,2289,2290,2293],{},[1371,2291,2292],{},"Last Updated",": 2025-12-12",[1837,2295,2296],{},"html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}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);}",{"title":104,"searchDepth":119,"depth":119,"links":2298},[2299,2300,2306,2307,2308,2309,2310],{"id":1875,"depth":119,"text":1876},{"id":1921,"depth":119,"text":1922,"children":2301},[2302,2303,2304,2305],{"id":1928,"depth":150,"text":1929},{"id":1979,"depth":150,"text":1980},{"id":2035,"depth":150,"text":2036},{"id":2065,"depth":150,"text":2066},{"id":2072,"depth":119,"text":2073},{"id":2177,"depth":119,"text":2178},{"id":2221,"depth":119,"text":2222},{"id":2257,"depth":119,"text":2258},{"id":2275,"depth":119,"text":2276},"shield",{},"/security",{"title":1866,"description":104},"security","8Hgch7Pp-e-NyfBxgZdJF8RyzhItCJT0gGPopLjI8Wk",{"id":2318,"title":1818,"body":2319,"description":2327,"extension":1857,"icon":106,"meta":2893,"navigation":494,"path":2894,"seo":2895,"stem":1817,"__hash__":2896},"resources/contributing.md",{"type":9,"value":2320,"toc":2868},[2321,2325,2328,2332,2335,2339,2377,2381,2385,2403,2406,2422,2424,2435,2439,2443,2457,2461,2472,2476,2481,2484,2501,2505,2508,2526,2530,2533,2547,2551,2579,2582,2585,2600,2603,2619,2622,2638,2641,2654,2658,2666,2670,2673,2717,2721,2725,2728,2739,2742,2756,2760,2763,2791,2795,2823,2829,2833,2836,2847,2851,2862,2865],[12,2322,2324],{"id":2323},"contributing-to-flume","Contributing to flume",[17,2326,2327],{},"Thank you for your interest in contributing to flume! This guide will help you get started.",[94,2329,2331],{"id":2330},"code-of-conduct","Code of Conduct",[17,2333,2334],{},"By participating in this project, you agree to maintain a respectful and inclusive environment for all contributors.",[94,2336,2338],{"id":2337},"getting-started","Getting Started",[1939,2340,2341,2344,2350,2356,2359,2365,2368,2374],{},[1368,2342,2343],{},"Fork the repository",[1368,2345,2346,2347],{},"Clone your fork: ",[106,2348,2349],{},"git clone https://github.com/yourusername/flume.git",[1368,2351,2352,2353],{},"Create a feature branch: ",[106,2354,2355],{},"git checkout -b feature/your-feature-name",[1368,2357,2358],{},"Make your changes",[1368,2360,2361,2362],{},"Run tests: ",[106,2363,2364],{},"go test ./...",[1368,2366,2367],{},"Commit your changes with a descriptive message",[1368,2369,2370,2371],{},"Push to your fork: ",[106,2372,2373],{},"git push origin feature/your-feature-name",[1368,2375,2376],{},"Create a Pull Request",[94,2378,2380],{"id":2379},"development-guidelines","Development Guidelines",[1705,2382,2384],{"id":2383},"code-style","Code Style",[1365,2386,2387,2390,2397,2400],{},[1368,2388,2389],{},"Follow standard Go conventions",[1368,2391,2392,2393,2396],{},"Run ",[106,2394,2395],{},"go fmt"," before committing",[1368,2398,2399],{},"Add comments for exported functions and types",[1368,2401,2402],{},"Keep functions small and focused",[1705,2404,1767],{"id":2405},"testing",[1365,2407,2408,2411,2416,2419],{},[1368,2409,2410],{},"Write tests for new functionality",[1368,2412,2413,2414],{},"Ensure all tests pass: ",[106,2415,2364],{},[1368,2417,2418],{},"Include benchmarks for performance-critical code",[1368,2420,2421],{},"Aim for good test coverage",[1705,2423,1696],{"id":1695},[1365,2425,2426,2429,2432],{},[1368,2427,2428],{},"Update documentation for API changes",[1368,2430,2431],{},"Add examples for new features",[1368,2433,2434],{},"Keep doc comments clear and concise",[94,2436,2438],{"id":2437},"types-of-contributions","Types of Contributions",[1705,2440,2442],{"id":2441},"bug-reports","Bug Reports",[1365,2444,2445,2448,2451,2454],{},[1368,2446,2447],{},"Use GitHub Issues",[1368,2449,2450],{},"Include minimal reproduction code",[1368,2452,2453],{},"Describe expected vs actual behavior",[1368,2455,2456],{},"Include Go version and OS",[1705,2458,2460],{"id":2459},"feature-requests","Feature Requests",[1365,2462,2463,2466,2469],{},[1368,2464,2465],{},"Open an issue for discussion first",[1368,2467,2468],{},"Explain the use case",[1368,2470,2471],{},"Consider backwards compatibility",[1705,2473,2475],{"id":2474},"code-contributions","Code Contributions",[2477,2478,2480],"h4",{"id":2479},"adding-processors","Adding Processors",[17,2482,2483],{},"New processor builders should:",[1365,2485,2486,2492,2495,2498],{},[1368,2487,2488,2489],{},"Follow the existing pattern in ",[106,2490,2491],{},"builders.go",[1368,2493,2494],{},"Include comprehensive tests",[1368,2496,2497],{},"Add documentation with examples",[1368,2499,2500],{},"Update schema validation if needed",[2477,2502,2504],{"id":2503},"adding-schema-features","Adding Schema Features",[17,2506,2507],{},"New schema features should:",[1365,2509,2510,2517,2520,2523],{},[1368,2511,2512,2513,2516],{},"Extend the ",[106,2514,2515],{},"Node"," type appropriately",[1368,2518,2519],{},"Include validation rules",[1368,2521,2522],{},"Add builder support",[1368,2524,2525],{},"Document the YAML/JSON format",[2477,2527,2529],{"id":2528},"examples","Examples",[17,2531,2532],{},"New examples should:",[1365,2534,2535,2538,2541,2544],{},[1368,2536,2537],{},"Solve a real-world problem",[1368,2539,2540],{},"Include tests",[1368,2542,2543],{},"Have clear documentation",[1368,2545,2546],{},"Follow the existing structure",[94,2548,2550],{"id":2549},"pull-request-process","Pull Request Process",[1939,2552,2553,2559,2564,2569,2574],{},[1368,2554,2555,2558],{},[1371,2556,2557],{},"Keep PRs focused"," - One feature/fix per PR",[1368,2560,2561],{},[1371,2562,2563],{},"Write descriptive commit messages",[1368,2565,2566],{},[1371,2567,2568],{},"Update tests and documentation",[1368,2570,2571],{},[1371,2572,2573],{},"Ensure CI passes",[1368,2575,2576],{},[1371,2577,2578],{},"Respond to review feedback",[94,2580,1767],{"id":2581},"testing-1",[17,2583,2584],{},"Run the full test suite:",[99,2586,2588],{"className":630,"code":2587,"language":632,"meta":104,"style":104},"go test ./...\n",[106,2589,2590],{"__ignoreMap":104},[109,2591,2592,2594,2597],{"class":111,"line":112},[109,2593,103],{"class":136},[109,2595,2596],{"class":177}," test",[109,2598,2599],{"class":177}," ./...\n",[17,2601,2602],{},"Run with race detection:",[99,2604,2606],{"className":630,"code":2605,"language":632,"meta":104,"style":104},"go test -race ./...\n",[106,2607,2608],{"__ignoreMap":104},[109,2609,2610,2612,2614,2617],{"class":111,"line":112},[109,2611,103],{"class":136},[109,2613,2596],{"class":177},[109,2615,2616],{"class":184}," -race",[109,2618,2599],{"class":177},[17,2620,2621],{},"Run benchmarks:",[99,2623,2625],{"className":630,"code":2624,"language":632,"meta":104,"style":104},"go test -bench=. ./...\n",[106,2626,2627],{"__ignoreMap":104},[109,2628,2629,2631,2633,2636],{"class":111,"line":112},[109,2630,103],{"class":136},[109,2632,2596],{"class":177},[109,2634,2635],{"class":184}," -bench=.",[109,2637,2599],{"class":177},[17,2639,2640],{},"Run linter:",[99,2642,2644],{"className":630,"code":2643,"language":632,"meta":104,"style":104},"make lint\n",[106,2645,2646],{"__ignoreMap":104},[109,2647,2648,2651],{"class":111,"line":112},[109,2649,2650],{"class":136},"make",[109,2652,2653],{"class":177}," lint\n",[94,2655,2657],{"id":2656},"project-structure","Project Structure",[99,2659,2664],{"className":2660,"code":2662,"language":2663},[2661],"language-text","flume/\n├── factory.go        # Core factory type and registration\n├── builders.go       # Schema node to pipeline builders\n├── schema.go         # Schema types and parsing\n├── validation.go     # Schema validation\n├── loader.go         # File/JSON/YAML loading\n├── observability.go  # Event emission\n├── spec.go           # Factory introspection\n└── *_test.go         # Tests\n","text",[106,2665,2662],{"__ignoreMap":104},[94,2667,2669],{"id":2668},"commit-messages","Commit Messages",[17,2671,2672],{},"Follow conventional commits:",[1365,2674,2675,2681,2687,2693,2699,2705,2711],{},[1368,2676,2677,2680],{},[106,2678,2679],{},"feat:"," New feature",[1368,2682,2683,2686],{},[106,2684,2685],{},"fix:"," Bug fix",[1368,2688,2689,2692],{},[106,2690,2691],{},"docs:"," Documentation changes",[1368,2694,2695,2698],{},[106,2696,2697],{},"test:"," Test additions/changes",[1368,2700,2701,2704],{},[106,2702,2703],{},"refactor:"," Code refactoring",[1368,2706,2707,2710],{},[106,2708,2709],{},"perf:"," Performance improvements",[1368,2712,2713,2716],{},[106,2714,2715],{},"chore:"," Maintenance tasks",[94,2718,2720],{"id":2719},"release-process","Release Process",[1705,2722,2724],{"id":2723},"automated-releases","Automated Releases",[17,2726,2727],{},"This project uses automated release versioning. To create a release:",[1939,2729,2730,2733,2736],{},[1368,2731,2732],{},"Go to Actions -> Release -> Run workflow",[1368,2734,2735],{},"Leave \"Version override\" empty for automatic version inference",[1368,2737,2738],{},"Click \"Run workflow\"",[17,2740,2741],{},"The system will:",[1365,2743,2744,2747,2750,2753],{},[1368,2745,2746],{},"Automatically determine the next version from conventional commits",[1368,2748,2749],{},"Create a git tag",[1368,2751,2752],{},"Generate release notes via GoReleaser",[1368,2754,2755],{},"Publish the release to GitHub",[1705,2757,2759],{"id":2758},"manual-release-legacy","Manual Release (Legacy)",[17,2761,2762],{},"You can still create releases manually:",[99,2764,2766],{"className":630,"code":2765,"language":632,"meta":104,"style":104},"git tag v1.2.3\ngit push origin v1.2.3\n",[106,2767,2768,2779],{"__ignoreMap":104},[109,2769,2770,2773,2776],{"class":111,"line":112},[109,2771,2772],{"class":136},"git",[109,2774,2775],{"class":177}," tag",[109,2777,2778],{"class":177}," v1.2.3\n",[109,2780,2781,2783,2786,2789],{"class":111,"line":119},[109,2782,2772],{"class":136},[109,2784,2785],{"class":177}," push",[109,2787,2788],{"class":177}," origin",[109,2790,2778],{"class":177},[1705,2792,2794],{"id":2793},"commit-conventions-for-versioning","Commit Conventions for Versioning",[1365,2796,2797,2802,2807,2813],{},[1368,2798,2799,2801],{},[106,2800,2679],{}," new features (minor version: 1.2.0 -> 1.3.0)",[1368,2803,2804,2806],{},[106,2805,2685],{}," bug fixes (patch version: 1.2.0 -> 1.2.1)",[1368,2808,2809,2812],{},[106,2810,2811],{},"feat!:"," breaking changes (major version: 1.2.0 -> 2.0.0)",[1368,2814,2815,2817,2818,2817,2820,2822],{},[106,2816,2691],{},", ",[106,2819,2697],{},[106,2821,2715],{}," no version change",[17,2824,2825,2826],{},"Example: ",[106,2827,2828],{},"feat(schema): add support for custom connector types",[1705,2830,2832],{"id":2831},"version-preview-on-pull-requests","Version Preview on Pull Requests",[17,2834,2835],{},"Every PR automatically shows the next version that will be created:",[1365,2837,2838,2841,2844],{},[1368,2839,2840],{},"Check PR comments for \"Version Preview\"",[1368,2842,2843],{},"Updates automatically as you add commits",[1368,2845,2846],{},"Helps verify your commits have the intended effect",[94,2848,2850],{"id":2849},"questions","Questions?",[1365,2852,2853,2856,2859],{},[1368,2854,2855],{},"Open an issue for questions",[1368,2857,2858],{},"Check existing issues first",[1368,2860,2861],{},"Be patient and respectful",[17,2863,2864],{},"Thank you for contributing to flume!",[1837,2866,2867],{},"html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}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 .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}",{"title":104,"searchDepth":119,"depth":119,"links":2869},[2870,2871,2872,2877,2882,2883,2884,2885,2886,2892],{"id":2330,"depth":119,"text":2331},{"id":2337,"depth":119,"text":2338},{"id":2379,"depth":119,"text":2380,"children":2873},[2874,2875,2876],{"id":2383,"depth":150,"text":2384},{"id":2405,"depth":150,"text":1767},{"id":1695,"depth":150,"text":1696},{"id":2437,"depth":119,"text":2438,"children":2878},[2879,2880,2881],{"id":2441,"depth":150,"text":2442},{"id":2459,"depth":150,"text":2460},{"id":2474,"depth":150,"text":2475},{"id":2549,"depth":119,"text":2550},{"id":2581,"depth":119,"text":1767},{"id":2656,"depth":119,"text":2657},{"id":2668,"depth":119,"text":2669},{"id":2719,"depth":119,"text":2720,"children":2887},[2888,2889,2890,2891],{"id":2723,"depth":150,"text":2724},{"id":2758,"depth":150,"text":2759},{"id":2793,"depth":150,"text":2794},{"id":2831,"depth":150,"text":2832},{"id":2849,"depth":119,"text":2850},{},"/contributing",{"title":1818,"description":2327},"XNSK9mlai_COIso6Z9bL54kGavHd1YbB2SBaSuGIqdk",[2898,2903,2907,2911,2915,2920,2925,2929,2933,2937,2942,2947,2950,2954,2958,2962,2966,2970,2974,2979,2984,2989,2994,2999,3004,3009,3014,3019,3024,3029,3034,3038,3042,3047,3052,3057,3062,3067,3072,3077,3082,3087,3091,3096,3100,3104,3109,3114,3119,3123,3127,3131,3135,3140,3144,3148,3153,3158,3163,3168,3173,3178,3183,3187,3192,3197,3202,3206,3210,3214,3219,3224,3228,3233,3238,3241,3246,3251,3256,3261,3266,3270,3275,3280,3285,3289,3293,3298,3303,3308,3313,3317,3321,3325,3329,3334,3339,3344,3349,3353,3358,3363,3368,3372,3377,3382,3386,3391,3396,3401,3405,3410,3415,3420,3424,3429,3434,3438,3443,3448,3453,3457,3461,3465,3469,3473,3478,3483,3488,3492,3497,3502,3506,3511,3516,3520,3525,3530,3534,3539,3543,3547,3552,3557,3561,3566,3571,3576,3581,3585,3589,3593,3597,3602,3607,3612,3617,3621,3626,3631,3635,3639,3644,3648,3653,3657,3661,3666,3670,3674,3678,3682,3687,3691,3695,3699,3704,3709,3714,3719,3722,3727,3732,3737,3742,3747,3751,3755,3759,3764,3769,3774,3779,3784,3789,3794,3799,3804,3808,3813,3818,3823,3828,3833,3838,3842,3846,3850,3854,3858,3862,3867,3872,3877,3882,3887,3891,3896,3901,3906,3910,3915,3920,3925,3929,3934,3939,3943,3948,3953,3958,3963,3967,3971,3975,3980,3985,3990,3995,4000,4005,4010,4014,4018,4022,4026,4030,4034,4039,4044,4049,4054,4058,4062,4067,4072,4077,4081,4086,4091,4096,4101,4105,4110,4115,4120,4125,4130,4133,4138,4142,4147,4152,4156,4160,4165,4170,4175,4179,4184,4189,4193,4197,4202,4205,4209,4213,4217,4222,4226,4230,4235,4240,4245,4250,4255,4260,4264,4269,4273,4277,4281,4285,4289,4294,4299,4302,4307,4312,4317,4322,4327,4332,4337,4342,4347,4352,4357,4362,4367,4372,4377,4382,4387,4392,4397,4401,4405,4409,4413,4417,4421,4425,4428,4432,4436,4440,4444,4448,4452,4456,4460,4464,4468,4472,4476,4480,4484,4488,4493,4497,4501,4505,4509,4514,4518,4523,4527,4532,4536,4541,4546,4551,4556,4560,4565,4570,4575,4580,4585,4590,4595,4600,4605,4610,4615,4620,4625,4629,4634,4639,4644,4649],{"id":2899,"title":2900,"titles":2901,"content":2902,"level":112},"/v1.0.1/overview","Overview",[],"Schema-driven pipeline factory for pipz with hot-reloading capabilities",{"id":2904,"title":2900,"titles":2905,"content":2906,"level":112},"/v1.0.1/overview#overview",[],"Building data pipelines in Go typically means hardcoding structure at compile time. Change the flow? Rebuild and redeploy. Flume offers a different approach: define pipeline structure in configuration, update it at runtime. factory := flume.New[Order]()\n\n// Register reusable components\nfactory.Add(pipz.Apply(\"validate\", validateOrder))\nfactory.Add(pipz.Transform(\"enrich\", enrichOrder))\nfactory.AddPredicate(flume.Predicate[Order]{\n    Name:      \"high-value\",\n    Predicate: func(ctx context.Context, o Order) bool { return o.Total > 1000 },\n})\n\n// Build from schema\npipeline, _ := factory.BuildFromYAML(`\ntype: sequence\nchildren:\n  - ref: validate\n  - type: filter\n    predicate: high-value\n    then:\n      ref: enrich\n`)\n\n// Update at runtime - no restart required\nfactory.SetSchema(\"orders\", newSchema) Type-safe, hot-reloadable, zero external dependencies.",{"id":2908,"title":1730,"titles":2909,"content":2910,"level":119},"/v1.0.1/overview#architecture",[2900],"┌──────────────────────────────────────────────────────────────┐\n│                         Factory[T]                           │\n│                                                              │\n│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐          │\n│  │ Processors  │  │ Predicates  │  │ Conditions  │          │\n│  │ (Chainable) │  │  (bool fn)  │  │ (string fn) │          │\n│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘          │\n│         │                │                │                  │\n│         └────────────────┼────────────────┘                  │\n│                          ▼                                   │\n│  ┌───────────────────────────────────────────────────────┐  │\n│  │                   Schema (YAML/JSON)                  │  │\n│  │   type: sequence                                      │  │\n│  │   children:                                           │  │\n│  │     - ref: validate                                   │  │\n│  │     - type: filter ...                                │  │\n│  └───────────────────────────────────────────────────────┘  │\n│                          │                                   │\n│                    Build │ Validate                          │\n│                          ▼                                   │\n│  ┌───────────────────────────────────────────────────────┐  │\n│  │              pipz.Chainable[T] Pipeline               │  │\n│  └───────────────────────────────────────────────────────┘  │\n└──────────────────────────────────────────────────────────────┘ Register components once, compose them via schemas, build executable pipelines. Schemas validate against registered components before building.",{"id":2912,"title":2913,"titles":2914,"content":104,"level":119},"/v1.0.1/overview#philosophy","Philosophy",[2900],{"id":2916,"title":2917,"titles":2918,"content":2919,"level":150},"/v1.0.1/overview#configuration-over-code","Configuration Over Code",[2900,2913],"Pipeline structure belongs in configuration. Business logic belongs in code. # Configuration: structure\ntype: sequence\nchildren:\n  - ref: validate\n  - ref: process // Code: behaviour\nfactory.Add(pipz.Apply(\"validate\", func(ctx context.Context, o Order) (Order, error) {\n    if o.Total \u003C= 0 {\n        return o, errors.New(\"invalid total\")\n    }\n    return o, nil\n}))",{"id":2921,"title":2922,"titles":2923,"content":2924,"level":150},"/v1.0.1/overview#zero-magic","Zero Magic",[2900,2913],"Processors name themselves via pipz.NameSchemas are plain YAML/JSONValidation errors include full pathsNo reflection at runtime",{"id":2926,"title":1253,"titles":2927,"content":2928,"level":119},"/v1.0.1/overview#capabilities",[2900],"Schema-driven pipelines open possibilities: Hot Reloading - Update pipeline behaviour without restarts. A/B test processing logic, toggle features, respond to changing requirements. Multi-tenant Processing - Different schemas per tenant. Same registered components, different compositions based on customer tier or configuration. Channel Integration - Route pipeline outputs to Go channels. Fan-out to multiple streams, integrate with async consumers. Resilience Patterns - Retry, timeout, circuit breaker, rate limiting - all declarative in schema. Change resilience strategy without code changes. Flume provides the composition layer. What pipelines you build is up to you.",{"id":2930,"title":2931,"titles":2932,"content":104,"level":119},"/v1.0.1/overview#priorities","Priorities",[2900],{"id":2934,"title":2188,"titles":2935,"content":2936,"level":150},"/v1.0.1/overview#type-safety",[2900,2931],"Full generics from factory to pipeline. The type flows through: factory := flume.New[Order]()      // Factory[Order]\nfactory.Add(orderProcessor)         // Only accepts Chainable[Order]\npipeline, _ := factory.Build(schema)\nresult, _ := pipeline.Process(ctx, order) // Returns (Order, error)",{"id":2938,"title":2939,"titles":2940,"content":2941,"level":150},"/v1.0.1/overview#validation","Validation",[2900,2931],"Schemas validate before building. Missing references, invalid configurations, structural errors - caught early with clear messages: 3 validation errors:\n  1. root.children[0]: processor 'missing' not found\n  2. root.children[1]: predicate 'unknown' not found\n  3. root.children[2].timeout: invalid duration \"bad\"",{"id":2943,"title":2944,"titles":2945,"content":2946,"level":150},"/v1.0.1/overview#performance","Performance",[2900,2931],"Built pipelines execute with zero overhead - the result is a pipz pipeline. Cost is only at build time: OperationTimePipeline execution (3-step sequence)~459 nsSchema build (10-step sequence)~6.7 µs Build once, execute many times.",{"id":2948,"title":1696,"titles":2949,"content":104,"level":119},"/v1.0.1/overview#documentation",[2900],{"id":2951,"title":1708,"titles":2952,"content":2953,"level":150},"/v1.0.1/overview#learn",[2900,1696],"Quickstart - Your first pipeline in 5 minutesCore Concepts - Factories, schemas, and componentsArchitecture - How Flume works under the hoodBuilding Pipelines - From simple to complex",{"id":2955,"title":1742,"titles":2956,"content":2957,"level":150},"/v1.0.1/overview#guides",[2900,1696],"Schema Design - Best practices for schema structureHot Reloading - Update pipelines without restartsError Handling - Retry, fallback, circuit breakersTesting - Testing schema-driven pipelinesObservability - Monitoring with capitan events",{"id":2959,"title":1790,"titles":2960,"content":2961,"level":150},"/v1.0.1/overview#reference",[2900,1696],"API Reference - Factory methods and typesSchema Format - YAML/JSON specificationConnector Types - All 14 connectorsEvents - Observability signals html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}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 .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}",{"id":2963,"title":1716,"titles":2964,"content":2965,"level":112},"/v1.0.1/learn/quickstart",[],"Build your first Flume pipeline in 5 minutes",{"id":2967,"title":1716,"titles":2968,"content":2969,"level":112},"/v1.0.1/learn/quickstart#quickstart",[],"Build your first schema-driven pipeline in 5 minutes.",{"id":2971,"title":624,"titles":2972,"content":2973,"level":119},"/v1.0.1/learn/quickstart#installation",[1716],"go get github.com/zoobz-io/flume",{"id":2975,"title":2976,"titles":2977,"content":2978,"level":119},"/v1.0.1/learn/quickstart#step-1-define-your-data-type","Step 1: Define Your Data Type",[1716],"Your data type must implement pipz.Cloner[T]: package main\n\nimport (\n    \"context\"\n    \"fmt\"\n\n    \"github.com/zoobz-io/flume\"\n    \"github.com/zoobz-io/pipz\"\n)\n\ntype Order struct {\n    ID       string\n    Customer string\n    Total    float64\n    Status   string\n}\n\nfunc (o Order) Clone() Order {\n    return Order{\n        ID:       o.ID,\n        Customer: o.Customer,\n        Total:    o.Total,\n        Status:   o.Status,\n    }\n}",{"id":2980,"title":2981,"titles":2982,"content":2983,"level":119},"/v1.0.1/learn/quickstart#step-2-create-a-factory","Step 2: Create a Factory",[1716],"func main() {\n    factory := flume.New[Order]()\n}",{"id":2985,"title":2986,"titles":2987,"content":2988,"level":119},"/v1.0.1/learn/quickstart#step-3-register-processors","Step 3: Register Processors",[1716],"// Validate order\n    factory.Add(pipz.Apply(\"validate\", func(ctx context.Context, o Order) (Order, error) {\n        if o.Total \u003C= 0 {\n            return o, fmt.Errorf(\"invalid total: %f\", o.Total)\n        }\n        return o, nil\n    }))\n\n    // Enrich with status\n    factory.Add(pipz.Transform(\"enrich\", func(ctx context.Context, o Order) Order {\n        o.Status = \"validated\"\n        return o\n    }))\n\n    // Log order\n    factory.Add(pipz.Effect(\"log\", func(ctx context.Context, o Order) error {\n        fmt.Printf(\"Processing order: %s for %s ($%.2f)\\n\", o.ID, o.Customer, o.Total)\n        return nil\n    }))",{"id":2990,"title":2991,"titles":2992,"content":2993,"level":119},"/v1.0.1/learn/quickstart#step-4-define-schema","Step 4: Define Schema",[1716],"schema := `\ntype: sequence\nchildren:\n  - ref: validate\n  - ref: enrich\n  - ref: log\n`",{"id":2995,"title":2996,"titles":2997,"content":2998,"level":119},"/v1.0.1/learn/quickstart#step-5-build-and-use","Step 5: Build and Use",[1716],"pipeline, err := factory.BuildFromYAML(schema)\n    if err != nil {\n        panic(err)\n    }\n\n    order := Order{\n        ID:       \"ORD-001\",\n        Customer: \"Alice\",\n        Total:    99.99,\n    }\n\n    result, err := pipeline.Process(context.Background(), order)\n    if err != nil {\n        panic(err)\n    }\n\n    fmt.Printf(\"Result: %+v\\n\", result)\n}",{"id":3000,"title":3001,"titles":3002,"content":3003,"level":119},"/v1.0.1/learn/quickstart#complete-example","Complete Example",[1716],"package main\n\nimport (\n    \"context\"\n    \"fmt\"\n\n    \"github.com/zoobz-io/flume\"\n    \"github.com/zoobz-io/pipz\"\n)\n\ntype Order struct {\n    ID       string\n    Customer string\n    Total    float64\n    Status   string\n}\n\nfunc (o Order) Clone() Order {\n    return Order{ID: o.ID, Customer: o.Customer, Total: o.Total, Status: o.Status}\n}\n\nfunc main() {\n    factory := flume.New[Order]()\n\n    // Register processors\n    factory.Add(\n        pipz.Apply(\"validate\", func(ctx context.Context, o Order) (Order, error) {\n            if o.Total \u003C= 0 {\n                return o, fmt.Errorf(\"invalid total: %f\", o.Total)\n            }\n            return o, nil\n        }),\n        pipz.Transform(\"enrich\", func(ctx context.Context, o Order) Order {\n            o.Status = \"validated\"\n            return o\n        }),\n        pipz.Effect(\"log\", func(ctx context.Context, o Order) error {\n            fmt.Printf(\"Order: %s ($%.2f)\\n\", o.ID, o.Total)\n            return nil\n        }),\n    )\n\n    // Define and build pipeline\n    schema := `\ntype: sequence\nchildren:\n  - ref: validate\n  - ref: enrich\n  - ref: log\n`\n\n    pipeline, err := factory.BuildFromYAML(schema)\n    if err != nil {\n        panic(err)\n    }\n\n    // Process\n    result, err := pipeline.Process(context.Background(), Order{\n        ID:       \"ORD-001\",\n        Customer: \"Alice\",\n        Total:    99.99,\n    })\n    if err != nil {\n        panic(err)\n    }\n\n    fmt.Printf(\"Final: %+v\\n\", result)\n} Output: Order: ORD-001 ($99.99)\nFinal: {ID:ORD-001 Customer:Alice Total:99.99 Status:validated}",{"id":3005,"title":3006,"titles":3007,"content":3008,"level":119},"/v1.0.1/learn/quickstart#adding-conditional-logic","Adding Conditional Logic",[1716],"Add a predicate for conditional processing: factory.AddPredicate(flume.Predicate[Order]{\n        Name: \"high-value\",\n        Predicate: func(ctx context.Context, o Order) bool {\n            return o.Total > 100\n        },\n    })\n\n    factory.Add(pipz.Effect(\"premium-notify\", func(ctx context.Context, o Order) error {\n        fmt.Println(\"High-value order detected!\")\n        return nil\n    }))\n\n    schema := `\ntype: sequence\nchildren:\n  - ref: validate\n  - type: filter\n    predicate: high-value\n    then:\n      ref: premium-notify\n  - ref: log\n`",{"id":3010,"title":3011,"titles":3012,"content":3013,"level":119},"/v1.0.1/learn/quickstart#adding-error-handling","Adding Error Handling",[1716],"Wrap processors with retry: schema := `\ntype: sequence\nchildren:\n  - ref: validate\n  - type: retry\n    attempts: 3\n    child:\n      ref: external-api-call\n  - ref: log\n`",{"id":3015,"title":3016,"titles":3017,"content":3018,"level":119},"/v1.0.1/learn/quickstart#merging-concurrent-results","Merging Concurrent Results",[1716],"When running processors concurrently, use a reducer to merge results: // Register parallel enrichment processors\n    factory.Add(\n        pipz.Transform(\"fetch-customer\", func(ctx context.Context, o Order) Order {\n            o.Customer = \"Alice (Premium)\"\n            return o\n        }),\n        pipz.Transform(\"fetch-inventory\", func(ctx context.Context, o Order) Order {\n            o.Status = \"in-stock\"\n            return o\n        }),\n    )\n\n    // Register a reducer to merge results\n    factory.AddReducer(flume.Reducer[Order]{\n        Name: \"merge-enrichments\",\n        Reducer: func(original Order, results map[pipz.Name]Order, errors map[pipz.Name]error) Order {\n            for _, result := range results {\n                if result.Customer != \"\" {\n                    original.Customer = result.Customer\n                }\n                if result.Status != \"\" {\n                    original.Status = result.Status\n                }\n            }\n            return original\n        },\n    })\n\n    schema := `\ntype: sequence\nchildren:\n  - ref: validate\n  - type: concurrent\n    reducer: merge-enrichments\n    children:\n      - ref: fetch-customer\n      - ref: fetch-inventory\n  - ref: log\n`",{"id":3020,"title":3021,"titles":3022,"content":3023,"level":119},"/v1.0.1/learn/quickstart#loading-from-files","Loading from Files",[1716],"pipeline, err := factory.BuildFromFile(\"pipeline.yaml\")",{"id":3025,"title":3026,"titles":3027,"content":3028,"level":119},"/v1.0.1/learn/quickstart#using-named-schemas","Using Named Schemas",[1716],"For hot-reloading support: // Register named schema\n    err := factory.SetSchema(\"order-processing\", schema)\n    if err != nil {\n        panic(err)\n    }\n\n    // Create binding with auto-sync\n    pipelineID := factory.Identity(\"order-processor\", \"Processes orders\")\n    binding, err := factory.Bind(pipelineID, \"order-processing\", flume.WithAutoSync())\n    if err != nil {\n        panic(err)\n    }\n\n    // Process requests\n    result, err := binding.Process(ctx, order)\n\n    // Update schema at runtime - binding rebuilds automatically\n    newSchema := Schema{...}\n    factory.SetSchema(\"order-processing\", newSchema)",{"id":3030,"title":3031,"titles":3032,"content":3033,"level":119},"/v1.0.1/learn/quickstart#next-steps","Next Steps",[1716],"Building Pipelines - Complex schema patternsCore Concepts - Deeper understandingSchema Format - Complete reference html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}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 .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}html pre.shiki code .suWN2, html code.shiki .suWN2{--shiki-default:var(--shiki-tag)}html pre.shiki code .skxcq, html code.shiki .skxcq{--shiki-default:var(--shiki-builtin)}",{"id":3035,"title":1723,"titles":3036,"content":3037,"level":112},"/v1.0.1/learn/core-concepts",[],"Understanding Flume's fundamental building blocks - factories, schemas, and components",{"id":3039,"title":1723,"titles":3040,"content":3041,"level":112},"/v1.0.1/learn/core-concepts#core-concepts",[],"Flume is built around three core concepts: the Factory, Schemas, and Components.",{"id":3043,"title":3044,"titles":3045,"content":3046,"level":119},"/v1.0.1/learn/core-concepts#the-factory","The Factory",[1723],"The factory is Flume's central registry. It holds all registered components and builds pipelines from schemas. factory := flume.New[Order]() The factory is generic over your data type T. This type must implement pipz.Cloner[T] to support parallel processing: type Order struct {\n    ID    string\n    Total float64\n}\n\nfunc (o Order) Clone() Order {\n    return Order{ID: o.ID, Total: o.Total}\n}",{"id":3048,"title":3049,"titles":3050,"content":3051,"level":150},"/v1.0.1/learn/core-concepts#factory-responsibilities","Factory Responsibilities",[1723,3044],"Component Registry - Store processors, predicates, and conditionsSchema Storage - Manage named schemas with hot-reload supportPipeline Building - Construct pipz pipelines from schemasValidation - Verify schemas before building",{"id":3053,"title":3054,"titles":3055,"content":3056,"level":119},"/v1.0.1/learn/core-concepts#components","Components",[1723],"Components are the building blocks registered with the factory. There are three types:",{"id":3058,"title":3059,"titles":3060,"content":3061,"level":150},"/v1.0.1/learn/core-concepts#processors","Processors",[1723,3054],"Processors are pipz Chainable[T] implementations - the actual processing logic: // Using pipz constructors\nfactory.Add(\n    pipz.Apply(\"validate\", validateOrder),      // T -> (T, error)\n    pipz.Transform(\"normalize\", normalizeOrder), // T -> T\n    pipz.Effect(\"log\", logOrder),               // T -> error (no modification)\n) Reference in schemas: ref: validate",{"id":3063,"title":3064,"titles":3065,"content":3066,"level":150},"/v1.0.1/learn/core-concepts#predicates","Predicates",[1723,3054],"Predicates are boolean functions for conditional processing: factory.AddPredicate(flume.Predicate[Order]{\n    Name:        \"is-premium\",\n    Description: \"Checks if customer has premium tier\",\n    Predicate: func(ctx context.Context, o Order) bool {\n        return o.CustomerTier == \"premium\"\n    },\n}) Used in filter nodes: type: filter\npredicate: is-premium\nthen:\n  ref: premium-handler",{"id":3068,"title":3069,"titles":3070,"content":3071,"level":150},"/v1.0.1/learn/core-concepts#conditions","Conditions",[1723,3054],"Conditions return strings for multi-way routing: factory.AddCondition(flume.Condition[Order]{\n    Name:        \"order-status\",\n    Description: \"Returns the current order status\",\n    Values:      []string{\"pending\", \"approved\", \"rejected\"},\n    Condition: func(ctx context.Context, o Order) string {\n        return o.Status\n    },\n}) Used in switch nodes: type: switch\ncondition: order-status\nroutes:\n  pending:\n    ref: handle-pending\n  approved:\n    ref: handle-approved\ndefault:\n  ref: handle-unknown",{"id":3073,"title":3074,"titles":3075,"content":3076,"level":119},"/v1.0.1/learn/core-concepts#schemas","Schemas",[1723],"Schemas define pipeline structure as YAML or JSON documents.",{"id":3078,"title":3079,"titles":3080,"content":3081,"level":150},"/v1.0.1/learn/core-concepts#schema-structure","Schema Structure",[1723,3074],"version: \"1.0.0\"    # Optional version tracking\ntype: sequence      # Connector type\nname: my-pipeline   # Optional name override\nchildren:           # Child nodes\n  - ref: step1\n  - ref: step2",{"id":3083,"title":3084,"titles":3085,"content":3086,"level":150},"/v1.0.1/learn/core-concepts#node-types","Node Types",[1723,3074],"Nodes are either references or connectors: # Reference: points to registered processor\nref: validate\n\n# Connector: defines structure\ntype: sequence\nchildren:\n  - ref: step1\n  - ref: step2",{"id":3088,"title":1737,"titles":3089,"content":3090,"level":150},"/v1.0.1/learn/core-concepts#building-pipelines",[1723,3074],"Build from strings or files: // From YAML string\npipeline, err := factory.BuildFromYAML(yamlStr)\n\n// From JSON string\npipeline, err := factory.BuildFromJSON(jsonStr)\n\n// From file (auto-detects format)\npipeline, err := factory.BuildFromFile(\"pipeline.yaml\")\n\n// From Schema struct\npipeline, err := factory.Build(schema)",{"id":3092,"title":3093,"titles":3094,"content":3095,"level":119},"/v1.0.1/learn/core-concepts#dynamic-schema-management","Dynamic Schema Management",[1723],"Flume supports named schemas that can be updated at runtime: // Register a named schema\nerr := factory.SetSchema(\"order-pipeline\", schema)\n\n// Create a binding with auto-sync enabled\npipelineID := factory.Identity(\"order-processor\", \"Processes orders\")\nbinding, err := factory.Bind(pipelineID, \"order-pipeline\", flume.WithAutoSync())\n\n// Process requests (lock-free)\nresult, err := binding.Process(ctx, order)\n\n// Update the schema - auto-sync bindings rebuild automatically\nerr = factory.SetSchema(\"order-pipeline\", newSchema)\n\n// Remove a schema\nremoved := factory.RemoveSchema(\"order-pipeline\")\n\n// List all schemas\nnames := factory.ListSchemas()",{"id":3097,"title":1295,"titles":3098,"content":3099,"level":150},"/v1.0.1/learn/core-concepts#hot-reloading",[1723,3093],"When you update a schema: New pipeline is built and validatedAll auto-sync bindings rebuild atomicallyIn-flight requests complete with old pipelineNew requests use updated pipeline // Watcher pattern\nfor schemaChange := range watcher.Changes() {\n    if err := factory.SetSchema(schemaChange.Name, schemaChange.Schema); err != nil {\n        log.Printf(\"failed to update schema: %v\", err)\n        continue\n    }\n    log.Printf(\"schema %s updated to version %s\",\n        schemaChange.Name, schemaChange.Schema.Version)\n}",{"id":3101,"title":2939,"titles":3102,"content":3103,"level":119},"/v1.0.1/learn/core-concepts#validation",[1723],"Flume validates schemas before building, catching errors early: err := factory.ValidateSchema(schema)\nif err != nil {\n    // ValidationErrors with detailed paths\n    fmt.Println(err)\n    // Output:\n    // 3 validation errors:\n    //   1. root.children[0]: processor 'missing' not found\n    //   2. root.children[1]: predicate 'unknown' not found\n    //   3. root.children[1].then: processor 'also-missing' not found\n}",{"id":3105,"title":3106,"titles":3107,"content":3108,"level":150},"/v1.0.1/learn/core-concepts#what-gets-validated","What Gets Validated",[1723,2939],"All processor/predicate/condition references existRequired fields are presentConnector constraints are met (e.g., fallback needs 2 children)Configuration values are valid (e.g., positive retry attempts)Duration strings are parseableNo circular references",{"id":3110,"title":3111,"titles":3112,"content":3113,"level":119},"/v1.0.1/learn/core-concepts#component-introspection","Component Introspection",[1723],"Query the factory's registrations: // Check existence\nfactory.HasProcessor(\"validate\")\nfactory.HasPredicate(\"is-premium\")\nfactory.HasCondition(\"order-status\")\n\n// List all\nprocessors := factory.ListProcessors()  // []pipz.Name\npredicates := factory.ListPredicates()\nconditions := factory.ListConditions()",{"id":3115,"title":3116,"titles":3117,"content":3118,"level":119},"/v1.0.1/learn/core-concepts#component-removal","Component Removal",[1723],"Remove components when no longer needed: // Remove processors (returns count removed)\nremoved := factory.Remove(\"old-processor\", \"deprecated\")\n\n// Remove predicates\nfactory.RemovePredicate(\"old-predicate\")\n\n// Remove conditions\nfactory.RemoveCondition(\"old-condition\") Note: Removing a component doesn't affect already-built pipelines, but will cause validation errors if you try to build schemas that reference them.",{"id":3120,"title":3031,"titles":3121,"content":3122,"level":119},"/v1.0.1/learn/core-concepts#next-steps",[1723],"Architecture - How Flume works under the hoodQuickstart - Build your first pipelineAPI Reference - Complete method documentation html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}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 .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}",{"id":3124,"title":1730,"titles":3125,"content":3126,"level":112},"/v1.0.1/learn/architecture",[],"How Flume works under the hood - from schema to pipeline",{"id":3128,"title":1730,"titles":3129,"content":3130,"level":112},"/v1.0.1/learn/architecture#architecture",[],"Understanding Flume's internal architecture helps you use it effectively and debug issues.",{"id":3132,"title":2900,"titles":3133,"content":3134,"level":119},"/v1.0.1/learn/architecture#overview",[1730],"┌─────────────────────────────────────────────────────────────┐\n│                         Factory[T]                          │\n├─────────────────────────────────────────────────────────────┤\n│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │\n│  │ Processors  │  │ Predicates  │  │ Conditions  │         │\n│  │  map[Name]  │  │  map[Name]  │  │  map[Name]  │         │\n│  └─────────────┘  └─────────────┘  └─────────────┘         │\n│                                                             │\n│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │\n│  │  Schemas    │  │  Pipelines  │  │  Channels   │         │\n│  │ map[string] │  │ atomic.Ptr  │  │ map[string] │         │\n│  └─────────────┘  └─────────────┘  └─────────────┘         │\n└─────────────────────────────────────────────────────────────┘\n                           │\n                           ▼\n              ┌────────────────────────┐\n              │    Schema Document     │\n              │  (YAML/JSON/Struct)    │\n              └────────────────────────┘\n                           │\n            ┌──────────────┼──────────────┐\n            ▼              ▼              ▼\n      ┌──────────┐  ┌──────────┐  ┌──────────┐\n      │  Parse   │  │ Validate │  │  Build   │\n      └──────────┘  └──────────┘  └──────────┘\n                           │\n                           ▼\n              ┌────────────────────────┐\n              │   pipz.Chainable[T]    │\n              │    (ready to use)      │\n              └────────────────────────┘",{"id":3136,"title":3137,"titles":3138,"content":3139,"level":119},"/v1.0.1/learn/architecture#factory-structure","Factory Structure",[1730],"The factory maintains six internal maps protected by a read-write mutex: type Factory[T pipz.Cloner[T]] struct {\n    processors map[pipz.Name]processorMeta[T]\n    predicates map[pipz.Name]predicateMeta[T]\n    conditions map[pipz.Name]conditionMeta[T]\n    schemas    map[string]*Schema\n    pipelines  map[string]*atomic.Pointer[pipz.Chainable[T]]\n    channels   map[string]chan\u003C- T\n    mu         sync.RWMutex\n}",{"id":3141,"title":2205,"titles":3142,"content":3143,"level":150},"/v1.0.1/learn/architecture#thread-safety",[1730,3137],"Read operations (lookups, list, build) acquire read locksWrite operations (add, remove, set schema) acquire write locksPipeline access uses atomic pointers for lock-free retrieval",{"id":3145,"title":3146,"titles":3147,"content":104,"level":119},"/v1.0.1/learn/architecture#schema-processing-pipeline","Schema Processing Pipeline",[1730],{"id":3149,"title":3150,"titles":3151,"content":3152,"level":150},"/v1.0.1/learn/architecture#_1-parsing","1. Parsing",[1730,3146],"Schemas can be loaded from multiple sources: // String parsing\nfactory.BuildFromYAML(yamlStr)\nfactory.BuildFromJSON(jsonStr)\n\n// File loading (detects format from extension)\nfactory.BuildFromFile(\"pipeline.yaml\")\n\n// Direct struct\nfactory.Build(schema) The parser converts YAML/JSON into the Schema struct: type Schema struct {\n    Version string\n    Node    // embedded\n}\n\ntype Node struct {\n    Ref       string\n    Type      string\n    Name      string\n    Children  []Node\n    Child     *Node\n    // ... connector-specific fields\n}",{"id":3154,"title":3155,"titles":3156,"content":3157,"level":150},"/v1.0.1/learn/architecture#_2-validation","2. Validation",[1730,3146],"Before building, the factory validates the entire schema tree: func (f *Factory[T]) ValidateSchema(schema Schema) error {\n    var errors ValidationErrors\n    f.validateNode(&schema.Node, []string{\"root\"}, &errors)\n    if len(errors) > 0 {\n        return errors\n    }\n    return nil\n} Validation traverses the tree recursively, checking: References exist - All ref: values point to registered processorsPredicates exist - All predicate: values are registeredConditions exist - All condition: values are registeredRequired fields - Each node type has its required fieldsConstraints - Type-specific rules (e.g., fallback needs exactly 2 children)No cycles - Reference chains don't loop back",{"id":3159,"title":3160,"titles":3161,"content":3162,"level":150},"/v1.0.1/learn/architecture#_3-building","3. Building",[1730,3146],"The builder recursively constructs pipz chainables: func (f *Factory[T]) buildNode(node *Node) (pipz.Chainable[T], error) {\n    // Handle processor reference\n    if node.Ref != \"\" {\n        return f.processors[pipz.Name(node.Ref)].processor, nil\n    }\n\n    // Handle connector types\n    switch node.Type {\n    case \"sequence\":\n        return f.buildSequence(node)\n    case \"concurrent\":\n        return f.buildConcurrent(node)\n    // ... other types\n    }\n} Each connector type has a dedicated builder that: Validates connector-specific requirementsRecursively builds child nodesConstructs the pipz connector with appropriate options",{"id":3164,"title":3165,"titles":3166,"content":3167,"level":119},"/v1.0.1/learn/architecture#connector-mapping","Connector Mapping",[1730],"Flume schema types map directly to pipz constructors: Schema Typepipz Constructorsequencepipz.NewSequenceconcurrentpipz.NewConcurrentracepipz.NewRacefallbackpipz.NewFallbackretrypipz.NewRetry or pipz.NewBackofftimeoutpipz.NewTimeoutfilterpipz.NewFilter or custom routingswitchpipz.NewSwitchcircuit-breakerpipz.NewCircuitBreakerrate-limitpipz.NewRateLimiter + pipz.NewSequence",{"id":3169,"title":3170,"titles":3171,"content":3172,"level":119},"/v1.0.1/learn/architecture#hot-reload-mechanism","Hot Reload Mechanism",[1730],"Named schemas support atomic updates: func (f *Factory[T]) SetSchema(name string, schema Schema) error {\n    // 1. Validate first\n    if err := f.ValidateSchema(schema); err != nil {\n        return err\n    }\n\n    // 2. Build pipeline\n    pipeline, err := f.Build(schema)\n    if err != nil {\n        return err\n    }\n\n    // 3. Atomic update\n    f.mu.Lock()\n    defer f.mu.Unlock()\n\n    f.schemas[name] = &schema\n    if ptr, exists := f.pipelines[name]; exists {\n        ptr.Store(&pipeline)  // Atomic swap\n    } else {\n        ptr := &atomic.Pointer[pipz.Chainable[T]]{}\n        ptr.Store(&pipeline)\n        f.pipelines[name] = ptr\n    }\n    return nil\n} Retrieval is lock-free after the initial lookup: func (f *Factory[T]) Pipeline(name string) (pipz.Chainable[T], bool) {\n    f.mu.RLock()\n    ptr := f.pipelines[name]\n    f.mu.RUnlock()\n\n    if ptr == nil {\n        return nil, false\n    }\n    return *ptr.Load(), true  // Atomic load\n}",{"id":3174,"title":3175,"titles":3176,"content":3177,"level":119},"/v1.0.1/learn/architecture#observability-integration","Observability Integration",[1730],"Flume emits Capitan events throughout its lifecycle: // Factory events\nFactoryCreated\nProcessorRegistered\nPredicateRegistered\nConditionRegistered\n\n// Schema events\nSchemaValidationStarted\nSchemaValidationCompleted\nSchemaValidationFailed\nSchemaBuildStarted\nSchemaBuildCompleted\nSchemaBuildFailed\n\n// Dynamic schema events\nSchemaRegistered\nSchemaUpdated\nSchemaRemoved\nPipelineRetrieved Events include typed fields: capitan.Emit(ctx, SchemaRegistered,\n    KeyName.Field(name),\n    KeyVersion.Field(schema.Version))",{"id":3179,"title":3180,"titles":3181,"content":3182,"level":119},"/v1.0.1/learn/architecture#channel-integration","Channel Integration",[1730],"Channels enable stream processing patterns: factory.AddChannel(\"output\", outputChan) Stream nodes wrap channels in pipz effects: func (f *Factory[T]) buildStream(node *Node) (pipz.Chainable[T], error) {\n    channel := f.channels[node.Stream]\n\n    return pipz.Effect(\n        pipz.Name(fmt.Sprintf(\"stream:%s\", node.Stream)),\n        func(_ context.Context, item T) error {\n            channel \u003C- item\n            return nil\n        },\n    ), nil\n}",{"id":3184,"title":3185,"titles":3186,"content":104,"level":119},"/v1.0.1/learn/architecture#memory-model","Memory Model",[1730],{"id":3188,"title":3189,"titles":3190,"content":3191,"level":150},"/v1.0.1/learn/architecture#component-storage","Component Storage",[1730,3185],"Components are stored by value in maps: type processorMeta[T any] struct {\n    processor   pipz.Chainable[T]  // Interface value\n    description string\n    tags        []string\n}",{"id":3193,"title":3194,"titles":3195,"content":3196,"level":150},"/v1.0.1/learn/architecture#pipeline-lifecycle","Pipeline Lifecycle",[1730,3185],"Registration - Components stored in factory mapsBuild - New pipeline created from current registrationsStorage - Pipeline stored via atomic pointer (for named schemas)Usage - Pipeline used directly, no factory reference neededUpdate - New pipeline built, pointer atomically swappedRemoval - Schema removed, pipeline garbage collected when unreferenced",{"id":3198,"title":3199,"titles":3200,"content":3201,"level":150},"/v1.0.1/learn/architecture#concurrency","Concurrency",[1730,3185],"Multiple goroutines can safely call Pipeline() concurrentlyBuild operations are serialized through the write lockBuilt pipelines are independent of the factory",{"id":3203,"title":3031,"titles":3204,"content":3205,"level":119},"/v1.0.1/learn/architecture#next-steps",[1730],"Quickstart - Build your first pipelineSchema Design - Best practicesEvents Reference - All observability signals html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}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 .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .skxcq, html code.shiki .skxcq{--shiki-default:var(--shiki-builtin)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}",{"id":3207,"title":1737,"titles":3208,"content":3209,"level":112},"/v1.0.1/learn/building-pipelines",[],"From simple sequences to complex nested pipelines",{"id":3211,"title":1737,"titles":3212,"content":3213,"level":112},"/v1.0.1/learn/building-pipelines#building-pipelines",[],"Learn to construct increasingly sophisticated pipelines with Flume schemas.",{"id":3215,"title":3216,"titles":3217,"content":3218,"level":119},"/v1.0.1/learn/building-pipelines#simple-sequences","Simple Sequences",[1737],"The most basic pipeline chains processors sequentially: type: sequence\nchildren:\n  - ref: validate\n  - ref: enrich\n  - ref: save Each processor receives the output of the previous one.",{"id":3220,"title":3221,"titles":3222,"content":3223,"level":119},"/v1.0.1/learn/building-pipelines#parallel-execution","Parallel Execution",[1737],"Process data concurrently with the concurrent type: type: sequence\nchildren:\n  - ref: validate\n  - type: concurrent\n    children:\n      - ref: enrich-from-db\n      - ref: enrich-from-api\n      - ref: calculate-score\n  - ref: save All concurrent children receive cloned data and execute in parallel. Results are merged.",{"id":3225,"title":3226,"titles":3227,"content":104,"level":119},"/v1.0.1/learn/building-pipelines#conditional-processing","Conditional Processing",[1737],{"id":3229,"title":3230,"titles":3231,"content":3232,"level":150},"/v1.0.1/learn/building-pipelines#filter","Filter",[1737,3226],"Execute a branch only when a condition is met: type: filter\npredicate: is-premium\nthen:\n  ref: apply-discount With else branch: type: filter\npredicate: is-premium\nthen:\n  ref: premium-handler\nelse:\n  ref: standard-handler",{"id":3234,"title":3235,"titles":3236,"content":3237,"level":150},"/v1.0.1/learn/building-pipelines#switch","Switch",[1737,3226],"Route to different handlers based on a condition value: type: switch\ncondition: order-type\nroutes:\n  subscription:\n    ref: handle-subscription\n  one-time:\n    ref: handle-single-purchase\n  gift:\n    type: sequence\n    children:\n      - ref: validate-gift\n      - ref: handle-gift\ndefault:\n  ref: handle-unknown Register the condition: factory.AddCondition(flume.Condition[Order]{\n    Name: \"order-type\",\n    Condition: func(ctx context.Context, o Order) string {\n        return o.Type // \"subscription\", \"one-time\", \"gift\", etc.\n    },\n})",{"id":3239,"title":1760,"titles":3240,"content":104,"level":119},"/v1.0.1/learn/building-pipelines#error-handling",[1737],{"id":3242,"title":3243,"titles":3244,"content":3245,"level":150},"/v1.0.1/learn/building-pipelines#retry","Retry",[1737,1760],"Retry failed operations: type: retry\nattempts: 3\nchild:\n  ref: flaky-api With exponential backoff: type: retry\nattempts: 5\nbackoff: \"100ms\"\nchild:\n  ref: external-service",{"id":3247,"title":3248,"titles":3249,"content":3250,"level":150},"/v1.0.1/learn/building-pipelines#fallback","Fallback",[1737,1760],"Use a backup handler on failure: type: fallback\nchildren:\n  - ref: primary-service\n  - ref: backup-service",{"id":3252,"title":3253,"titles":3254,"content":3255,"level":150},"/v1.0.1/learn/building-pipelines#timeout","Timeout",[1737,1760],"Enforce time limits: type: timeout\nduration: \"5s\"\nchild:\n  ref: slow-operation",{"id":3257,"title":3258,"titles":3259,"content":3260,"level":150},"/v1.0.1/learn/building-pipelines#circuit-breaker","Circuit Breaker",[1737,1760],"Prevent cascading failures: type: circuit-breaker\nfailure_threshold: 5\nrecovery_timeout: \"30s\"\nchild:\n  ref: unreliable-service",{"id":3262,"title":3263,"titles":3264,"content":3265,"level":150},"/v1.0.1/learn/building-pipelines#rate-limiting","Rate Limiting",[1737,1760],"Control throughput: type: rate-limit\nrequests_per_second: 100.0\nburst_size: 10\nchild:\n  ref: rate-sensitive-api",{"id":3267,"title":3268,"titles":3269,"content":104,"level":119},"/v1.0.1/learn/building-pipelines#nesting-patterns","Nesting Patterns",[1737],{"id":3271,"title":3272,"titles":3273,"content":3274,"level":150},"/v1.0.1/learn/building-pipelines#resilient-external-calls","Resilient External Calls",[1737,3268],"type: circuit-breaker\nfailure_threshold: 3\nrecovery_timeout: \"60s\"\nchild:\n  type: timeout\n  duration: \"10s\"\n  child:\n    type: retry\n    attempts: 3\n    backoff: \"200ms\"\n    child:\n      ref: external-api",{"id":3276,"title":3277,"titles":3278,"content":3279,"level":150},"/v1.0.1/learn/building-pipelines#conditional-with-fallback","Conditional with Fallback",[1737,3268],"type: filter\npredicate: has-cache\nthen:\n  type: fallback\n  children:\n    - ref: get-from-cache\n    - ref: get-from-db\nelse:\n  ref: get-from-db",{"id":3281,"title":3282,"titles":3283,"content":3284,"level":150},"/v1.0.1/learn/building-pipelines#parallel-with-error-handling","Parallel with Error Handling",[1737,3268],"type: concurrent\nchildren:\n  - type: retry\n    attempts: 2\n    child:\n      ref: service-a\n  - type: fallback\n    children:\n      - ref: service-b-primary\n      - ref: service-b-backup\n  - ref: service-c",{"id":3286,"title":3001,"titles":3287,"content":3288,"level":119},"/v1.0.1/learn/building-pipelines#complete-example",[1737],"An order processing pipeline: version: \"2.0.0\"\ntype: sequence\nname: order-processing\nchildren:\n  # Step 1: Validate\n  - ref: validate-order\n\n  # Step 2: Parallel enrichment\n  - type: concurrent\n    name: enrich\n    children:\n      - ref: fetch-customer\n      - ref: fetch-inventory\n      - ref: calculate-tax\n\n  # Step 3: Premium handling\n  - type: filter\n    predicate: is-premium-customer\n    then:\n      type: sequence\n      children:\n        - ref: apply-loyalty-discount\n        - ref: priority-queue\n\n  # Step 4: Payment routing\n  - type: switch\n    condition: payment-method\n    routes:\n      credit:\n        type: circuit-breaker\n        failure_threshold: 3\n        recovery_timeout: \"60s\"\n        child:\n          type: retry\n          attempts: 3\n          backoff: \"500ms\"\n          child:\n            ref: charge-credit-card\n      paypal:\n        type: timeout\n        duration: \"30s\"\n        child:\n          ref: paypal-checkout\n      crypto:\n        ref: crypto-payment\n    default:\n      ref: manual-payment-review\n\n  # Step 5: Post-payment\n  - type: concurrent\n    children:\n      - ref: update-inventory\n      - ref: send-confirmation\n      - type: filter\n        predicate: requires-shipping\n        then:\n          ref: create-shipment\n\n  # Step 6: Finalize\n  - ref: complete-order Registrations: // Processors\nfactory.Add(\n    pipz.Apply(\"validate-order\", validateOrder),\n    pipz.Apply(\"fetch-customer\", fetchCustomer),\n    pipz.Apply(\"fetch-inventory\", fetchInventory),\n    // ... more processors\n)\n\n// Predicates\nfactory.AddPredicate(\n    flume.Predicate[Order]{Name: \"is-premium-customer\", Predicate: isPremium},\n    flume.Predicate[Order]{Name: \"requires-shipping\", Predicate: needsShipping},\n)\n\n// Conditions\nfactory.AddCondition(flume.Condition[Order]{\n    Name:   \"payment-method\",\n    Values: []string{\"credit\", \"paypal\", \"crypto\"},\n    Condition: func(ctx context.Context, o Order) string {\n        return o.PaymentMethod\n    },\n})",{"id":3290,"title":3291,"titles":3292,"content":104,"level":119},"/v1.0.1/learn/building-pipelines#schema-design-tips","Schema Design Tips",[1737],{"id":3294,"title":3295,"titles":3296,"content":3297,"level":150},"/v1.0.1/learn/building-pipelines#_1-name-complex-nodes","1. Name Complex Nodes",[1737,3291],"type: sequence\nname: payment-handling  # Helps with debugging\nchildren:\n  - ref: charge\n  - ref: confirm",{"id":3299,"title":3300,"titles":3301,"content":3302,"level":150},"/v1.0.1/learn/building-pipelines#_2-keep-depth-manageable","2. Keep Depth Manageable",[1737,3291],"Break deeply nested schemas into named sub-pipelines: // Register sub-pipeline\nfactory.SetSchema(\"payment-flow\", paymentSchema)",{"id":3304,"title":3305,"titles":3306,"content":3307,"level":150},"/v1.0.1/learn/building-pipelines#_3-version-your-schemas","3. Version Your Schemas",[1737,3291],"version: \"1.2.0\"\ntype: sequence\n# ...",{"id":3309,"title":3310,"titles":3311,"content":3312,"level":150},"/v1.0.1/learn/building-pipelines#_4-document-with-comments","4. Document with Comments",[1737,3291],"YAML comments aren't preserved, but you can add documentation in companion files or use the description fields when registering components: factory.AddPredicate(flume.Predicate[Order]{\n    Name:        \"high-value\",\n    Description: \"Orders over $1000 for premium handling\",\n    Predicate:   isHighValue,\n})",{"id":3314,"title":3031,"titles":3315,"content":3316,"level":119},"/v1.0.1/learn/building-pipelines#next-steps",[1737],"Schema Design Guide - Best practicesError Handling Guide - Resilience patternsConnector Types Reference - All options html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}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 .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}",{"id":3318,"title":1331,"titles":3319,"content":3320,"level":112},"/v1.0.1/guides/schema-design",[],"Best practices for designing maintainable Flume schemas",{"id":3322,"title":1331,"titles":3323,"content":3324,"level":112},"/v1.0.1/guides/schema-design#schema-design",[],"Best practices for designing clear, maintainable Flume schemas.",{"id":3326,"title":3327,"titles":3328,"content":104,"level":119},"/v1.0.1/guides/schema-design#naming-conventions","Naming Conventions",[1331],{"id":3330,"title":3331,"titles":3332,"content":3333,"level":150},"/v1.0.1/guides/schema-design#processor-names","Processor Names",[1331,3327],"Use kebab-case with verb-noun patterns: // Good\npipz.Apply(\"validate-order\", ...)\npipz.Apply(\"fetch-customer\", ...)\npipz.Apply(\"send-notification\", ...)\n\n// Avoid\npipz.Apply(\"OrderValidation\", ...)\npipz.Apply(\"customer\", ...)\npipz.Apply(\"doStuff\", ...)",{"id":3335,"title":3336,"titles":3337,"content":3338,"level":150},"/v1.0.1/guides/schema-design#predicate-names","Predicate Names",[1331,3327],"Use is-/has-/can- prefixes: // Good\nflume.Predicate[T]{Name: \"is-premium\", ...}\nflume.Predicate[T]{Name: \"has-discount-code\", ...}\nflume.Predicate[T]{Name: \"can-ship-internationally\", ...}\n\n// Avoid\nflume.Predicate[T]{Name: \"premium\", ...}\nflume.Predicate[T]{Name: \"check-discount\", ...}",{"id":3340,"title":3341,"titles":3342,"content":3343,"level":150},"/v1.0.1/guides/schema-design#condition-names","Condition Names",[1331,3327],"Use get- prefix or descriptive nouns: // Good\nflume.Condition[T]{Name: \"get-order-type\", ...}\nflume.Condition[T]{Name: \"payment-method\", ...}\nflume.Condition[T]{Name: \"customer-tier\", ...}",{"id":3345,"title":3346,"titles":3347,"content":3348,"level":150},"/v1.0.1/guides/schema-design#schema-names","Schema Names",[1331,3327],"Use descriptive kebab-case: factory.SetSchema(\"order-processing\", ...)\nfactory.SetSchema(\"user-onboarding\", ...)\nfactory.SetSchema(\"payment-v2\", ...)",{"id":3350,"title":3351,"titles":3352,"content":104,"level":119},"/v1.0.1/guides/schema-design#structure-guidelines","Structure Guidelines",[1331],{"id":3354,"title":3355,"titles":3356,"content":3357,"level":150},"/v1.0.1/guides/schema-design#keep-depth-shallow","Keep Depth Shallow",[1331,3351],"Deeply nested schemas are hard to read and debug: # Hard to follow (5+ levels)\ntype: sequence\nchildren:\n  - type: filter\n    predicate: a\n    then:\n      type: switch\n        condition: b\n        routes:\n          x:\n            type: retry\n            child:\n              type: timeout\n                child:\n                  ref: processor Break into logical sub-schemas: # Main schema\ntype: sequence\nchildren:\n  - ref: validate\n  - ref: resilient-external-call  # Pre-composed\n  - ref: finalize // Register composed processor\nresilientCall := pipz.NewCircuitBreaker(\"resilient\",\n    pipz.NewTimeout(\"timeout\", apiCall, 5*time.Second),\n    3, 30*time.Second,\n)\nfactory.Add(resilientCall)",{"id":3359,"title":3360,"titles":3361,"content":3362,"level":150},"/v1.0.1/guides/schema-design#group-related-operations","Group Related Operations",[1331,3351],"Use sequence to group related steps: type: sequence\nname: payment-processing\nchildren:\n  - ref: validate-payment\n  - ref: authorize-payment\n  - ref: capture-payment\n  - ref: record-transaction",{"id":3364,"title":3365,"titles":3366,"content":3367,"level":150},"/v1.0.1/guides/schema-design#name-complex-nodes","Name Complex Nodes",[1331,3351],"Add names to non-trivial nodes for debugging: type: concurrent\nname: parallel-enrichment\nchildren:\n  - ref: fetch-customer\n  - ref: fetch-inventory\n\ntype: filter\nname: premium-check\npredicate: is-premium\nthen:\n  ref: premium-handler",{"id":3369,"title":3370,"titles":3371,"content":104,"level":119},"/v1.0.1/guides/schema-design#version-management","Version Management",[1331],{"id":3373,"title":3374,"titles":3375,"content":3376,"level":150},"/v1.0.1/guides/schema-design#semantic-versioning","Semantic Versioning",[1331,3370],"Use semantic versioning for schemas: version: \"1.0.0\"  # Initial\nversion: \"1.1.0\"  # Added new route\nversion: \"2.0.0\"  # Breaking change to structure",{"id":3378,"title":3379,"titles":3380,"content":3381,"level":150},"/v1.0.1/guides/schema-design#version-in-schema-name","Version in Schema Name",[1331,3370],"For A/B testing or gradual rollouts: factory.SetSchema(\"checkout-v1\", schemaV1)\nfactory.SetSchema(\"checkout-v2\", schemaV2)\n\n// Create bindings for each variant\nbindingV1, _ := factory.Bind(v1ID, \"checkout-v1\", flume.WithAutoSync())\nbindingV2, _ := factory.Bind(v2ID, \"checkout-v2\", flume.WithAutoSync())\n\n// Route traffic\nbinding := getBindingForUser(user, bindingV1, bindingV2)\nresult, _ := binding.Process(ctx, order)",{"id":3383,"title":3384,"titles":3385,"content":104,"level":119},"/v1.0.1/guides/schema-design#error-handling-placement","Error Handling Placement",[1331],{"id":3387,"title":3388,"titles":3389,"content":3390,"level":150},"/v1.0.1/guides/schema-design#wrap-at-boundaries","Wrap at Boundaries",[1331,3384],"Apply error handling at service boundaries: type: sequence\nchildren:\n  - ref: validate  # Internal - no wrap needed\n  - type: circuit-breaker\n    failure_threshold: 5\n    child:\n      type: retry\n        attempts: 3\n        child:\n          ref: external-api  # External - wrap\n  - ref: transform  # Internal - no wrap",{"id":3392,"title":3393,"titles":3394,"content":3395,"level":150},"/v1.0.1/guides/schema-design#dont-over-protect","Don't Over-Protect",[1331,3384],"Avoid redundant error handling: # Overkill\ntype: retry\nchild:\n  type: retry\n    child:\n      type: fallback\n        children:\n          - type: retry\n              child:\n                ref: processor\n          - ref: fallback",{"id":3397,"title":3398,"titles":3399,"content":3400,"level":150},"/v1.0.1/guides/schema-design#match-retry-to-operation","Match Retry to Operation",[1331,3384],"# Quick operation - few retries, no backoff\ntype: retry\nattempts: 2\nchild:\n  ref: cache-lookup\n\n# Slow external service - more retries with backoff\ntype: retry\nattempts: 5\nbackoff: \"500ms\"\nchild:\n  ref: payment-gateway",{"id":3402,"title":3403,"titles":3404,"content":104,"level":119},"/v1.0.1/guides/schema-design#performance-considerations","Performance Considerations",[1331],{"id":3406,"title":3407,"titles":3408,"content":3409,"level":150},"/v1.0.1/guides/schema-design#minimize-cloning","Minimize Cloning",[1331,3403],"concurrent and race nodes clone data. Avoid unnecessary parallelism: # Unnecessary clone\ntype: concurrent\nchildren:\n  - ref: quick-transform  # Could be sequential\n\n# Justified parallelism\ntype: concurrent\nchildren:\n  - ref: slow-api-call\n  - ref: another-slow-call",{"id":3411,"title":3412,"titles":3413,"content":3414,"level":150},"/v1.0.1/guides/schema-design#rate-limit-at-entry-points","Rate Limit at Entry Points",[1331,3403],"Place rate limiters early: type: sequence\nchildren:\n  - type: rate-limit\n    requests_per_second: 100.0\n    child:\n      ref: validate  # Everything after is protected\n  - ref: process\n  - ref: external-call",{"id":3416,"title":3417,"titles":3418,"content":3419,"level":150},"/v1.0.1/guides/schema-design#use-timeouts-wisely","Use Timeouts Wisely",[1331,3403],"Set realistic timeouts: type: timeout\nduration: \"30s\"  # Based on actual SLA\nchild:\n  ref: external-service",{"id":3421,"title":3422,"titles":3423,"content":104,"level":119},"/v1.0.1/guides/schema-design#schema-organization","Schema Organization",[1331],{"id":3425,"title":3426,"titles":3427,"content":3428,"level":150},"/v1.0.1/guides/schema-design#single-responsibility","Single Responsibility",[1331,3422],"Each schema should do one thing well: // Separate concerns\nfactory.SetSchema(\"order-validation\", validationSchema)\nfactory.SetSchema(\"order-payment\", paymentSchema)\nfactory.SetSchema(\"order-fulfillment\", fulfillmentSchema)",{"id":3430,"title":3431,"titles":3432,"content":3433,"level":150},"/v1.0.1/guides/schema-design#compose-larger-flows","Compose Larger Flows",[1331,3422],"Build complex flows from simple schemas: // High-level orchestration\nfactory.SetSchema(\"order-complete\", Schema{\n    Node: Node{\n        Type: \"sequence\",\n        Children: []Node{\n            {Ref: \"order-validation\"},   // References another pipeline\n            {Ref: \"order-payment\"},\n            {Ref: \"order-fulfillment\"},\n        },\n    },\n})",{"id":3435,"title":3436,"titles":3437,"content":104,"level":119},"/v1.0.1/guides/schema-design#documentation-practices","Documentation Practices",[1331],{"id":3439,"title":3440,"titles":3441,"content":3442,"level":150},"/v1.0.1/guides/schema-design#use-descriptions","Use Descriptions",[1331,3436],"Add descriptions when registering: factory.AddPredicate(flume.Predicate[Order]{\n    Name:        \"high-value\",\n    Description: \"Orders exceeding $1000 threshold for premium handling\",\n    Predicate:   isHighValue,\n})\n\nfactory.AddCondition(flume.Condition[Order]{\n    Name:        \"fulfillment-type\",\n    Description: \"Determines shipping vs. digital delivery\",\n    Values:      []string{\"ship\", \"digital\", \"pickup\"},\n    Condition:   getFulfillmentType,\n})",{"id":3444,"title":3445,"titles":3446,"content":3447,"level":150},"/v1.0.1/guides/schema-design#companion-documentation","Companion Documentation",[1331,3436],"Maintain schema documentation alongside files: schemas/\n  order-processing.yaml\n  order-processing.md    # Documents the schema",{"id":3449,"title":3450,"titles":3451,"content":3452,"level":150},"/v1.0.1/guides/schema-design#schema-diagrams","Schema Diagrams",[1331,3436],"For complex pipelines, create visual diagrams: validate → [concurrent: enrich] → [filter: premium?] → [switch: payment] → complete\n                                        ↓                    ↓\n                                  premium-handler     credit|paypal|crypto",{"id":3454,"title":3031,"titles":3455,"content":3456,"level":119},"/v1.0.1/guides/schema-design#next-steps",[1331],"Hot Reloading - Dynamic schema updatesTesting - Testing schema-driven pipelinesSchema Format Reference - Complete specification html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}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 .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}",{"id":3458,"title":1295,"titles":3459,"content":3460,"level":112},"/v1.0.1/guides/hot-reloading",[],"Update pipeline behaviour at runtime without restarts",{"id":3462,"title":1295,"titles":3463,"content":3464,"level":112},"/v1.0.1/guides/hot-reloading#hot-reloading",[],"Update pipeline definitions at runtime without service restarts.",{"id":3466,"title":2900,"titles":3467,"content":3468,"level":119},"/v1.0.1/guides/hot-reloading#overview",[1295],"Flume's hot reloading enables: Zero-downtime updates - Swap pipelines while requests continueA/B testing - Switch between pipeline variantsFeature flags - Enable/disable pipeline stages dynamicallyConfiguration-driven behaviour - Operators modify pipelines without deploys",{"id":3470,"title":3471,"titles":3472,"content":104,"level":119},"/v1.0.1/guides/hot-reloading#basic-usage","Basic Usage",[1295],{"id":3474,"title":3475,"titles":3476,"content":3477,"level":150},"/v1.0.1/guides/hot-reloading#register-named-schemas","Register Named Schemas",[1295,3471],"factory := flume.New[Order]()\n\n// Register components\nfactory.Add(processors...)\nfactory.AddPredicate(predicates...)\n\n// Register named schema\nschema := flume.Schema{\n    Version: \"1.0.0\",\n    Node: flume.Node{\n        Type: \"sequence\",\n        Children: []flume.Node{\n            {Ref: \"validate\"},\n            {Ref: \"process\"},\n        },\n    },\n}\n\nerr := factory.SetSchema(\"order-pipeline\", schema)",{"id":3479,"title":3480,"titles":3481,"content":3482,"level":150},"/v1.0.1/guides/hot-reloading#create-a-binding","Create a Binding",[1295,3471],"// Create a binding with auto-sync enabled\npipelineID := factory.Identity(\"order-processor\", \"Processes incoming orders\")\nbinding, err := factory.Bind(pipelineID, \"order-pipeline\", flume.WithAutoSync())\nif err != nil {\n    return fmt.Errorf(\"failed to bind: %w\", err)\n}\n\n// Process requests (lock-free)\nresult, err := binding.Process(ctx, order)",{"id":3484,"title":3485,"titles":3486,"content":3487,"level":150},"/v1.0.1/guides/hot-reloading#update-at-runtime","Update at Runtime",[1295,3471],"newSchema := flume.Schema{\n    Version: \"1.1.0\",\n    Node: flume.Node{\n        Type: \"sequence\",\n        Children: []flume.Node{\n            {Ref: \"validate\"},\n            {Ref: \"enrich\"},  // Added step\n            {Ref: \"process\"},\n        },\n    },\n}\n\nerr := factory.SetSchema(\"order-pipeline\", newSchema)\n// New requests immediately use updated pipeline",{"id":3489,"title":3490,"titles":3491,"content":104,"level":119},"/v1.0.1/guides/hot-reloading#how-it-works","How It Works",[1295],{"id":3493,"title":3494,"titles":3495,"content":3496,"level":150},"/v1.0.1/guides/hot-reloading#atomic-pointer-swap","Atomic Pointer Swap",[1295,3490],"// Internally, pipelines are stored as atomic pointers\npipelines map[string]*atomic.Pointer[pipz.Chainable[T]]\n\n// Update atomically swaps the pointer\nptr.Store(&newPipeline)\n\n// Retrieval loads atomically\nreturn *ptr.Load(), true",{"id":3498,"title":3499,"titles":3500,"content":3501,"level":150},"/v1.0.1/guides/hot-reloading#request-continuity","Request Continuity",[1295,3490],"Request A starts with pipeline v1Schema updates to v2Request A completes with v1 (unaffected)Request B starts with v2 No locks are held during processing - updates don't block requests.",{"id":3503,"title":3504,"titles":3505,"content":104,"level":119},"/v1.0.1/guides/hot-reloading#file-based-reloading","File-Based Reloading",[1295],{"id":3507,"title":3508,"titles":3509,"content":3510,"level":150},"/v1.0.1/guides/hot-reloading#watch-for-changes","Watch for Changes",[1295,3504],"func watchSchemaFile(ctx context.Context, factory *flume.Factory[Order], path string) {\n    watcher, _ := fsnotify.NewWatcher()\n    defer watcher.Close()\n\n    watcher.Add(path)\n\n    for {\n        select {\n        case \u003C-ctx.Done():\n            return\n        case event := \u003C-watcher.Events:\n            if event.Op&fsnotify.Write == fsnotify.Write {\n                reloadSchema(factory, path)\n            }\n        }\n    }\n}\n\nfunc reloadSchema(factory *flume.Factory[Order], path string) {\n    pipeline, err := factory.BuildFromFile(path)\n    if err != nil {\n        log.Printf(\"failed to reload schema: %v\", err)\n        return\n    }\n\n    // Read file to get schema for SetSchema\n    data, _ := os.ReadFile(path)\n    var schema flume.Schema\n    yaml.Unmarshal(data, &schema)\n\n    if err := factory.SetSchema(\"main\", schema); err != nil {\n        log.Printf(\"failed to set schema: %v\", err)\n    }\n}",{"id":3512,"title":3513,"titles":3514,"content":3515,"level":150},"/v1.0.1/guides/hot-reloading#multi-schema-directory","Multi-Schema Directory",[1295,3504],"func watchSchemaDir(ctx context.Context, factory *flume.Factory[Order], dir string) {\n    watcher, _ := fsnotify.NewWatcher()\n    watcher.Add(dir)\n\n    for event := range watcher.Events {\n        if event.Op&fsnotify.Write == 0 {\n            continue\n        }\n\n        name := strings.TrimSuffix(filepath.Base(event.Name), filepath.Ext(event.Name))\n\n        data, _ := os.ReadFile(event.Name)\n        var schema flume.Schema\n        if err := yaml.Unmarshal(data, &schema); err != nil {\n            log.Printf(\"invalid schema %s: %v\", name, err)\n            continue\n        }\n\n        if err := factory.SetSchema(name, schema); err != nil {\n            log.Printf(\"failed to update %s: %v\", name, err)\n        }\n    }\n}",{"id":3517,"title":3518,"titles":3519,"content":104,"level":119},"/v1.0.1/guides/hot-reloading#remote-configuration","Remote Configuration",[1295],{"id":3521,"title":3522,"titles":3523,"content":3524,"level":150},"/v1.0.1/guides/hot-reloading#http-endpoint","HTTP Endpoint",[1295,3518],"http.HandleFunc(\"/schemas/{name}\", func(w http.ResponseWriter, r *http.Request) {\n    name := r.PathValue(\"name\")\n\n    switch r.Method {\n    case \"GET\":\n        schema, ok := factory.GetSchema(name)\n        if !ok {\n            http.NotFound(w, r)\n            return\n        }\n        json.NewEncoder(w).Encode(schema)\n\n    case \"PUT\":\n        var schema flume.Schema\n        json.NewDecoder(r.Body).Decode(&schema)\n\n        if err := factory.SetSchema(name, schema); err != nil {\n            http.Error(w, err.Error(), 400)\n            return\n        }\n        w.WriteHeader(204)\n\n    case \"DELETE\":\n        if !factory.RemoveSchema(name) {\n            http.NotFound(w, r)\n            return\n        }\n        w.WriteHeader(204)\n    }\n})",{"id":3526,"title":3527,"titles":3528,"content":3529,"level":150},"/v1.0.1/guides/hot-reloading#polling","Polling",[1295,3518],"func pollSchemas(ctx context.Context, factory *flume.Factory[Order], url string) {\n    ticker := time.NewTicker(30 * time.Second)\n    defer ticker.Stop()\n\n    for {\n        select {\n        case \u003C-ctx.Done():\n            return\n        case \u003C-ticker.C:\n            resp, err := http.Get(url)\n            if err != nil {\n                continue\n            }\n\n            var schemas map[string]flume.Schema\n            json.NewDecoder(resp.Body).Decode(&schemas)\n            resp.Body.Close()\n\n            for name, schema := range schemas {\n                existing, ok := factory.GetSchema(name)\n                if ok && existing.Version == schema.Version {\n                    continue // No change\n                }\n                factory.SetSchema(name, schema)\n            }\n        }\n    }\n}",{"id":3531,"title":3532,"titles":3533,"content":104,"level":119},"/v1.0.1/guides/hot-reloading#version-tracking","Version Tracking",[1295],{"id":3535,"title":3536,"titles":3537,"content":3538,"level":150},"/v1.0.1/guides/hot-reloading#compare-versions","Compare Versions",[1295,3532],"existing, ok := factory.GetSchema(\"pipeline\")\nif ok && existing.Version == newSchema.Version {\n    return // Already up to date\n}\n\nerr := factory.SetSchema(\"pipeline\", newSchema)",{"id":3540,"title":1359,"titles":3541,"content":3542,"level":150},"/v1.0.1/guides/hot-reloading#observability",[1295,3532],"Flume emits events on schema changes: import \"github.com/zoobz-io/capitan\"\n\ncapitan.Handle(flume.SchemaUpdated, func(ctx context.Context, fields []capitan.Field) {\n    var name, oldVersion, newVersion string\n    for _, f := range fields {\n        switch f.Key {\n        case \"name\":\n            name = f.String()\n        case \"old_version\":\n            oldVersion = f.String()\n        case \"new_version\":\n            newVersion = f.String()\n        }\n    }\n    log.Printf(\"schema %s updated: %s -> %s\", name, oldVersion, newVersion)\n})",{"id":3544,"title":3545,"titles":3546,"content":104,"level":119},"/v1.0.1/guides/hot-reloading#graceful-updates","Graceful Updates",[1295],{"id":3548,"title":3549,"titles":3550,"content":3551,"level":150},"/v1.0.1/guides/hot-reloading#validation-first","Validation First",[1295,3545],"Always validate before applying: if err := factory.ValidateSchema(newSchema); err != nil {\n    return fmt.Errorf(\"invalid schema: %w\", err)\n}\n\n// Schema is valid, safe to apply\nfactory.SetSchema(name, newSchema)",{"id":3553,"title":3554,"titles":3555,"content":3556,"level":150},"/v1.0.1/guides/hot-reloading#rollback-pattern","Rollback Pattern",[1295,3545],"func updateWithRollback(factory *flume.Factory[Order], name string, newSchema flume.Schema, binding *flume.Binding[Order]) error {\n    // Save current\n    oldSchema, hadOld := factory.GetSchema(name)\n\n    // Apply new (auto-sync bindings rebuild automatically)\n    if err := factory.SetSchema(name, newSchema); err != nil {\n        return err\n    }\n\n    // Test with canary request\n    _, err := binding.Process(context.Background(), canaryOrder)\n\n    if err != nil && hadOld {\n        // Rollback to previous schema\n        factory.SetSchema(name, oldSchema)\n        return fmt.Errorf(\"canary failed, rolled back: %w\", err)\n    }\n\n    return nil\n}",{"id":3558,"title":3559,"titles":3560,"content":104,"level":119},"/v1.0.1/guides/hot-reloading#best-practices","Best Practices",[1295],{"id":3562,"title":3563,"titles":3564,"content":3565,"level":150},"/v1.0.1/guides/hot-reloading#_1-use-semantic-versioning","1. Use Semantic Versioning",[1295,3559],"version: \"1.2.3\"  # MAJOR.MINOR.PATCH",{"id":3567,"title":3568,"titles":3569,"content":3570,"level":150},"/v1.0.1/guides/hot-reloading#_2-log-all-changes","2. Log All Changes",[1295,3559],"log.Printf(\"schema %s updated to version %s\", name, schema.Version)",{"id":3572,"title":3573,"titles":3574,"content":3575,"level":150},"/v1.0.1/guides/hot-reloading#_3-validate-component-dependencies","3. Validate Component Dependencies",[1295,3559],"Before removing a processor, check if schemas reference it: for _, schemaName := range factory.ListSchemas() {\n    schema, _ := factory.GetSchema(schemaName)\n    if schemaReferencesProcessor(schema, \"old-processor\") {\n        return fmt.Errorf(\"cannot remove: schema %s uses it\", schemaName)\n    }\n}",{"id":3577,"title":3578,"titles":3579,"content":3580,"level":150},"/v1.0.1/guides/hot-reloading#_4-consider-circuit-breakers","4. Consider Circuit Breakers",[1295,3559],"Protect against bad schema updates: type GuardedFactory[T pipz.Cloner[T]] struct {\n    factory       *flume.Factory[T]\n    updateBreaker *circuitbreaker.CircuitBreaker\n}\n\nfunc (g *GuardedFactory[T]) SetSchema(name string, schema flume.Schema) error {\n    return g.updateBreaker.Execute(func() error {\n        return g.factory.SetSchema(name, schema)\n    })\n}",{"id":3582,"title":3031,"titles":3583,"content":3584,"level":119},"/v1.0.1/guides/hot-reloading#next-steps",[1295],"Testing - Test hot reload scenariosObservability - Monitor schema changesEvents Reference - All schema events html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}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 .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}",{"id":3586,"title":1760,"titles":3587,"content":3588,"level":112},"/v1.0.1/guides/error-handling",[],"Build resilient pipelines with retry, fallback, circuit breakers, and timeouts",{"id":3590,"title":1760,"titles":3591,"content":3592,"level":112},"/v1.0.1/guides/error-handling#error-handling",[],"Build resilient pipelines that gracefully handle failures.",{"id":3594,"title":3243,"titles":3595,"content":3596,"level":119},"/v1.0.1/guides/error-handling#retry",[1760],"Retry operations that may fail transiently.",{"id":3598,"title":3599,"titles":3600,"content":3601,"level":150},"/v1.0.1/guides/error-handling#basic-retry","Basic Retry",[1760,3243],"type: retry\nattempts: 3\nchild:\n  ref: flaky-operation Retries up to 3 times on any error.",{"id":3603,"title":3604,"titles":3605,"content":3606,"level":150},"/v1.0.1/guides/error-handling#retry-with-backoff","Retry with Backoff",[1760,3243],"type: retry\nattempts: 5\nbackoff: \"100ms\"\nchild:\n  ref: rate-limited-api Waits backoff duration between attempts, doubling each time (exponential backoff).",{"id":3608,"title":3609,"titles":3610,"content":3611,"level":150},"/v1.0.1/guides/error-handling#when-to-use","When to Use",[1760,3243],"Network calls that may timeoutRate-limited APIs that return temporary errorsDatabase operations during high loadMessage queue operations",{"id":3613,"title":3614,"titles":3615,"content":3616,"level":150},"/v1.0.1/guides/error-handling#configuration","Configuration",[1760,3243],"FieldDefaultDescriptionattempts3Maximum retry attemptsbackoff(none)Initial backoff duration",{"id":3618,"title":3248,"titles":3619,"content":3620,"level":119},"/v1.0.1/guides/error-handling#fallback",[1760],"Provide alternative handling when primary fails.",{"id":3622,"title":3623,"titles":3624,"content":3625,"level":150},"/v1.0.1/guides/error-handling#basic-fallback","Basic Fallback",[1760,3248],"type: fallback\nchildren:\n  - ref: primary-service\n  - ref: backup-service Tries primary first; if it errors, tries backup.",{"id":3627,"title":3628,"titles":3629,"content":3630,"level":150},"/v1.0.1/guides/error-handling#cascading-fallbacks","Cascading Fallbacks",[1760,3248],"type: fallback\nchildren:\n  - ref: primary-cache\n  - type: fallback\n    children:\n      - ref: secondary-cache\n      - ref: database",{"id":3632,"title":3609,"titles":3633,"content":3634,"level":150},"/v1.0.1/guides/error-handling#when-to-use-1",[1760,3248],"Service redundancyCache miss handlingFeature degradationDefault value provision",{"id":3636,"title":3253,"titles":3637,"content":3638,"level":119},"/v1.0.1/guides/error-handling#timeout",[1760],"Enforce time limits on operations.",{"id":3640,"title":3641,"titles":3642,"content":3643,"level":150},"/v1.0.1/guides/error-handling#basic-timeout","Basic Timeout",[1760,3253],"type: timeout\nduration: \"5s\"\nchild:\n  ref: slow-operation Cancels operation if not complete within duration.",{"id":3645,"title":3614,"titles":3646,"content":3647,"level":150},"/v1.0.1/guides/error-handling#configuration-1",[1760,3253],"FieldDefaultDescriptionduration30sMaximum execution time",{"id":3649,"title":3650,"titles":3651,"content":3652,"level":150},"/v1.0.1/guides/error-handling#duration-formats","Duration Formats",[1760,3253],"duration: \"100ms\"   # 100 milliseconds\nduration: \"5s\"      # 5 seconds\nduration: \"2m\"      # 2 minutes\nduration: \"1h30m\"   # 1.5 hours",{"id":3654,"title":3609,"titles":3655,"content":3656,"level":150},"/v1.0.1/guides/error-handling#when-to-use-2",[1760,3253],"External API callsLong-running computationsUser-facing requests requiring responsivenessPreventing resource exhaustion",{"id":3658,"title":3258,"titles":3659,"content":3660,"level":119},"/v1.0.1/guides/error-handling#circuit-breaker",[1760],"Prevent cascading failures by stopping calls to failing services.",{"id":3662,"title":3663,"titles":3664,"content":3665,"level":150},"/v1.0.1/guides/error-handling#basic-circuit-breaker","Basic Circuit Breaker",[1760,3258],"type: circuit-breaker\nfailure_threshold: 5\nrecovery_timeout: \"60s\"\nchild:\n  ref: external-service",{"id":3667,"title":3490,"titles":3668,"content":3669,"level":150},"/v1.0.1/guides/error-handling#how-it-works",[1760,3258],"Closed - Normal operation, failures countedOpen - After failure_threshold failures, requests fail immediatelyHalf-Open - After recovery_timeout, one test request allowedClosed - If test succeeds, resume normal operation",{"id":3671,"title":3614,"titles":3672,"content":3673,"level":150},"/v1.0.1/guides/error-handling#configuration-2",[1760,3258],"FieldDefaultDescriptionfailure_threshold5Failures before openingrecovery_timeout60sTime before testing recovery",{"id":3675,"title":3609,"titles":3676,"content":3677,"level":150},"/v1.0.1/guides/error-handling#when-to-use-3",[1760,3258],"Calling external servicesProtecting against cascade failuresAllowing degraded operationPreventing resource exhaustion from retrying failing calls",{"id":3679,"title":3263,"titles":3680,"content":3681,"level":119},"/v1.0.1/guides/error-handling#rate-limiting",[1760],"Control request throughput.",{"id":3683,"title":3684,"titles":3685,"content":3686,"level":150},"/v1.0.1/guides/error-handling#basic-rate-limit","Basic Rate Limit",[1760,3263],"type: rate-limit\nrequests_per_second: 100.0\nburst_size: 10\nchild:\n  ref: rate-sensitive-api",{"id":3688,"title":3614,"titles":3689,"content":3690,"level":150},"/v1.0.1/guides/error-handling#configuration-3",[1760,3263],"FieldDefaultDescriptionrequests_per_second10.0Sustained rate limitburst_size1Allowed burst above limit",{"id":3692,"title":3609,"titles":3693,"content":3694,"level":150},"/v1.0.1/guides/error-handling#when-to-use-4",[1760,3263],"Calling APIs with rate limitsProtecting downstream servicesEnsuring fair resource usagePreventing thundering herd",{"id":3696,"title":3697,"titles":3698,"content":104,"level":119},"/v1.0.1/guides/error-handling#combining-patterns","Combining Patterns",[1760],{"id":3700,"title":3701,"titles":3702,"content":3703,"level":150},"/v1.0.1/guides/error-handling#resilient-external-call","Resilient External Call",[1760,3697],"type: circuit-breaker\nfailure_threshold: 3\nrecovery_timeout: \"30s\"\nchild:\n  type: timeout\n  duration: \"10s\"\n  child:\n    type: retry\n    attempts: 3\n    backoff: \"200ms\"\n    child:\n      ref: external-api Order matters: Circuit breaker - Fails fast if service is downTimeout - Limits total wait timeRetry - Handles transient failures",{"id":3705,"title":3706,"titles":3707,"content":3708,"level":150},"/v1.0.1/guides/error-handling#fallback-with-resilience","Fallback with Resilience",[1760,3697],"type: fallback\nchildren:\n  - type: circuit-breaker\n    failure_threshold: 5\n    child:\n      type: retry\n      attempts: 2\n      child:\n        ref: primary-service\n  - ref: backup-service Primary has full resilience; backup is simpler.",{"id":3710,"title":3711,"titles":3712,"content":3713,"level":150},"/v1.0.1/guides/error-handling#rate-limited-with-timeout","Rate Limited with Timeout",[1760,3697],"type: timeout\nduration: \"30s\"\nchild:\n  type: rate-limit\n  requests_per_second: 50.0\n  burst_size: 5\n  child:\n    type: retry\n    attempts: 3\n    child:\n      ref: rate-limited-api Total request time bounded even if queued for rate limiting.",{"id":3715,"title":3716,"titles":3717,"content":3718,"level":119},"/v1.0.1/guides/error-handling#error-types","Error Types",[1760],"Understand which errors trigger which behaviour: ConnectorTriggers OnRetryAny error returnedFallbackAny error from primaryTimeoutContext deadline exceededCircuit BreakerAny error (tracks count)",{"id":3720,"title":3559,"titles":3721,"content":104,"level":119},"/v1.0.1/guides/error-handling#best-practices",[1760],{"id":3723,"title":3724,"titles":3725,"content":3726,"level":150},"/v1.0.1/guides/error-handling#_1-set-realistic-timeouts","1. Set Realistic Timeouts",[1760,3559],"# Too short - may fail healthy requests\nduration: \"100ms\"\n\n# Too long - poor user experience\nduration: \"5m\"\n\n# Right - based on actual service SLA\nduration: \"5s\"",{"id":3728,"title":3729,"titles":3730,"content":3731,"level":150},"/v1.0.1/guides/error-handling#_2-tune-circuit-breaker-thresholds","2. Tune Circuit Breaker Thresholds",[1760,3559],"# Too sensitive - opens on minor issues\nfailure_threshold: 1\n\n# Too lenient - doesn't protect\nfailure_threshold: 100\n\n# Balanced - opens after pattern emerges\nfailure_threshold: 5\nrecovery_timeout: \"30s\"",{"id":3733,"title":3734,"titles":3735,"content":3736,"level":150},"/v1.0.1/guides/error-handling#_3-use-backoff-for-rate-limits","3. Use Backoff for Rate Limits",[1760,3559],"type: retry\nattempts: 5\nbackoff: \"1s\"  # Gives rate limit time to reset\nchild:\n  ref: rate-limited-api",{"id":3738,"title":3739,"titles":3740,"content":3741,"level":150},"/v1.0.1/guides/error-handling#_4-dont-retry-non-retryable-errors","4. Don't Retry Non-Retryable Errors",[1760,3559],"Some errors shouldn't be retried. Design processors to return wrapped errors: type nonRetryableError struct {\n    error\n}\n\nfunc (e nonRetryableError) Unwrap() error { return e.error }\n\n// In processor\nif isInvalidInput(err) {\n    return data, nonRetryableError{err}\n}",{"id":3743,"title":3744,"titles":3745,"content":3746,"level":150},"/v1.0.1/guides/error-handling#_5-monitor-error-rates","5. Monitor Error Rates",[1760,3559],"Use Capitan events to track failures: capitan.Handle(flume.SchemaBuildFailed, logFailure)\n// Also monitor your processor errors",{"id":3748,"title":3031,"titles":3749,"content":3750,"level":119},"/v1.0.1/guides/error-handling#next-steps",[1760],"Testing - Test error scenariosConnector Types Reference - All options html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}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 .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}",{"id":3752,"title":1767,"titles":3753,"content":3754,"level":112},"/v1.0.1/guides/testing",[],"Testing strategies for schema-driven pipelines",{"id":3756,"title":1767,"titles":3757,"content":3758,"level":112},"/v1.0.1/guides/testing#testing",[],"Strategies for testing Flume pipelines at multiple levels.",{"id":3760,"title":3761,"titles":3762,"content":3763,"level":119},"/v1.0.1/guides/testing#testing-levels","Testing Levels",[1767],"Unit Tests - Test individual processorsSchema Tests - Test schema validationIntegration Tests - Test complete pipelinesProperty Tests - Test invariants across schemas",{"id":3765,"title":3766,"titles":3767,"content":3768,"level":119},"/v1.0.1/guides/testing#unit-testing-processors","Unit Testing Processors",[1767],"Test processors independently before registering: func TestValidateOrder(t *testing.T) {\n    processor := pipz.Apply(\"validate\", validateOrder)\n\n    tests := []struct {\n        name    string\n        input   Order\n        wantErr bool\n    }{\n        {\n            name:    \"valid order\",\n            input:   Order{Total: 100},\n            wantErr: false,\n        },\n        {\n            name:    \"zero total\",\n            input:   Order{Total: 0},\n            wantErr: true,\n        },\n        {\n            name:    \"negative total\",\n            input:   Order{Total: -50},\n            wantErr: true,\n        },\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            _, err := processor.Process(context.Background(), tt.input)\n            if (err != nil) != tt.wantErr {\n                t.Errorf(\"error = %v, wantErr %v\", err, tt.wantErr)\n            }\n        })\n    }\n}",{"id":3770,"title":3771,"titles":3772,"content":3773,"level":119},"/v1.0.1/guides/testing#testing-predicates","Testing Predicates",[1767],"func TestIsPremium(t *testing.T) {\n    pred := func(ctx context.Context, o Order) bool {\n        return o.CustomerTier == \"premium\"\n    }\n\n    tests := []struct {\n        tier string\n        want bool\n    }{\n        {\"premium\", true},\n        {\"standard\", false},\n        {\"\", false},\n    }\n\n    for _, tt := range tests {\n        got := pred(context.Background(), Order{CustomerTier: tt.tier})\n        if got != tt.want {\n            t.Errorf(\"isPremium(%q) = %v, want %v\", tt.tier, got, tt.want)\n        }\n    }\n}",{"id":3775,"title":3776,"titles":3777,"content":3778,"level":119},"/v1.0.1/guides/testing#schema-validation-tests","Schema Validation Tests",[1767],"Test that schemas are valid before deployment: func TestSchemaValidation(t *testing.T) {\n    factory := setupFactory()\n\n    tests := []struct {\n        name      string\n        schema    string\n        wantError bool\n    }{\n        {\n            name: \"valid sequence\",\n            schema: `\ntype: sequence\nchildren:\n  - ref: validate\n  - ref: process`,\n            wantError: false,\n        },\n        {\n            name: \"missing processor\",\n            schema: `\ntype: sequence\nchildren:\n  - ref: nonexistent`,\n            wantError: true,\n        },\n        {\n            name: \"missing predicate\",\n            schema: `\ntype: filter\npredicate: missing\nthen:\n  ref: validate`,\n            wantError: true,\n        },\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            _, err := factory.BuildFromYAML(tt.schema)\n            if (err != nil) != tt.wantError {\n                t.Errorf(\"BuildFromYAML() error = %v, wantError %v\", err, tt.wantError)\n            }\n        })\n    }\n}\n\nfunc setupFactory() *flume.Factory[Order] {\n    factory := flume.New[Order]()\n    factory.Add(\n        pipz.Transform(\"validate\", func(_ context.Context, o Order) Order { return o }),\n        pipz.Transform(\"process\", func(_ context.Context, o Order) Order { return o }),\n    )\n    factory.AddPredicate(flume.Predicate[Order]{\n        Name:      \"is-valid\",\n        Predicate: func(_ context.Context, o Order) bool { return o.Total > 0 },\n    })\n    return factory\n}",{"id":3780,"title":3781,"titles":3782,"content":3783,"level":119},"/v1.0.1/guides/testing#cicd-schema-linting","CI/CD Schema Linting",[1767],"Use ValidateSchemaStructure for CI/CD pipelines where a configured factory is not available. This validates schema syntax without checking if processors, predicates, or other references exist.",{"id":3785,"title":3786,"titles":3787,"content":3788,"level":150},"/v1.0.1/guides/testing#lint-schema-files","Lint Schema Files",[1767,3781],"func TestSchemaFilesStructure(t *testing.T) {\n    files, _ := filepath.Glob(\"schemas/*.yaml\")\n\n    for _, file := range files {\n        t.Run(filepath.Base(file), func(t *testing.T) {\n            data, err := os.ReadFile(file)\n            if err != nil {\n                t.Fatalf(\"failed to read file: %v\", err)\n            }\n\n            var schema flume.Schema\n            if err := yaml.Unmarshal(data, &schema); err != nil {\n                t.Fatalf(\"failed to parse YAML: %v\", err)\n            }\n\n            // Structural validation - no factory needed\n            if err := flume.ValidateSchemaStructure(schema); err != nil {\n                t.Errorf(\"invalid schema structure: %v\", err)\n            }\n        })\n    }\n}",{"id":3790,"title":3791,"titles":3792,"content":3793,"level":150},"/v1.0.1/guides/testing#ci-pipeline-example","CI Pipeline Example",[1767,3781],"# .github/workflows/lint-schemas.yml\nname: Lint Schemas\non: [push, pull_request]\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-go@v5\n        with:\n          go-version: '1.23'\n      - run: go test -v -run TestSchemaFilesStructure ./...",{"id":3795,"title":3796,"titles":3797,"content":3798,"level":150},"/v1.0.1/guides/testing#what-each-validation-checks","What Each Validation Checks",[1767,3781],"CheckValidateSchemaStructureValidateSchemaValid node typesYesYesRequired children/childYesYesValid durationsYesYesPositive numbersYesYesProcessor refs existNoYesPredicate refs existNoYesCondition refs existNoYesChannel refs existNoYesCircular referencesNoYes Use ValidateSchemaStructure in CI to catch syntax errors early, then ValidateSchema at runtime with a configured factory to catch reference errors.",{"id":3800,"title":3801,"titles":3802,"content":3803,"level":119},"/v1.0.1/guides/testing#integration-testing","Integration Testing",[1767],"Test complete pipelines with realistic scenarios: func TestOrderPipeline(t *testing.T) {\n    factory := setupProductionFactory()\n\n    schema := `\ntype: sequence\nchildren:\n  - ref: validate\n  - type: filter\n    predicate: high-value\n    then:\n      ref: premium-handler\n  - ref: finalize`\n\n    pipeline, err := factory.BuildFromYAML(schema)\n    if err != nil {\n        t.Fatalf(\"failed to build: %v\", err)\n    }\n\n    tests := []struct {\n        name  string\n        order Order\n        want  Order\n    }{\n        {\n            name:  \"standard order unchanged\",\n            order: Order{Total: 50},\n            want:  Order{Total: 50, Status: \"finalized\"},\n        },\n        {\n            name:  \"high value gets premium treatment\",\n            order: Order{Total: 1000},\n            want:  Order{Total: 1000, Discount: 0.1, Status: \"finalized\"},\n        },\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            result, err := pipeline.Process(context.Background(), tt.order)\n            if err != nil {\n                t.Fatalf(\"unexpected error: %v\", err)\n            }\n            if result != tt.want {\n                t.Errorf(\"got %+v, want %+v\", result, tt.want)\n            }\n        })\n    }\n}",{"id":3805,"title":3806,"titles":3807,"content":104,"level":119},"/v1.0.1/guides/testing#testing-error-handling","Testing Error Handling",[1767],{"id":3809,"title":3810,"titles":3811,"content":3812,"level":150},"/v1.0.1/guides/testing#retry-behaviour","Retry Behaviour",[1767,3806],"func TestRetryBehaviour(t *testing.T) {\n    attempts := 0\n    processor := pipz.Apply(\"flaky\", func(_ context.Context, o Order) (Order, error) {\n        attempts++\n        if attempts \u003C 3 {\n            return o, errors.New(\"transient failure\")\n        }\n        return o, nil\n    })\n\n    factory := flume.New[Order]()\n    factory.Add(processor)\n\n    schema := `\ntype: retry\nattempts: 5\nchild:\n  ref: flaky`\n\n    pipeline, _ := factory.BuildFromYAML(schema)\n    _, err := pipeline.Process(context.Background(), Order{})\n\n    if err != nil {\n        t.Errorf(\"expected success after retries, got: %v\", err)\n    }\n    if attempts != 3 {\n        t.Errorf(\"expected 3 attempts, got %d\", attempts)\n    }\n}",{"id":3814,"title":3815,"titles":3816,"content":3817,"level":150},"/v1.0.1/guides/testing#fallback-behaviour","Fallback Behaviour",[1767,3806],"func TestFallbackBehaviour(t *testing.T) {\n    factory := flume.New[Order]()\n\n    factory.Add(\n        pipz.Apply(\"failing\", func(_ context.Context, o Order) (Order, error) {\n            return o, errors.New(\"primary failed\")\n        }),\n        pipz.Transform(\"backup\", func(_ context.Context, o Order) Order {\n            o.Source = \"backup\"\n            return o\n        }),\n    )\n\n    schema := `\ntype: fallback\nchildren:\n  - ref: failing\n  - ref: backup`\n\n    pipeline, _ := factory.BuildFromYAML(schema)\n    result, err := pipeline.Process(context.Background(), Order{})\n\n    if err != nil {\n        t.Errorf(\"expected success from fallback: %v\", err)\n    }\n    if result.Source != \"backup\" {\n        t.Error(\"expected fallback to be used\")\n    }\n}",{"id":3819,"title":3820,"titles":3821,"content":3822,"level":150},"/v1.0.1/guides/testing#timeout-behaviour","Timeout Behaviour",[1767,3806],"func TestTimeoutBehaviour(t *testing.T) {\n    factory := flume.New[Order]()\n\n    factory.Add(pipz.Apply(\"slow\", func(ctx context.Context, o Order) (Order, error) {\n        select {\n        case \u003C-time.After(5 * time.Second):\n            return o, nil\n        case \u003C-ctx.Done():\n            return o, ctx.Err()\n        }\n    }))\n\n    schema := `\ntype: timeout\nduration: \"100ms\"\nchild:\n  ref: slow`\n\n    pipeline, _ := factory.BuildFromYAML(schema)\n    _, err := pipeline.Process(context.Background(), Order{})\n\n    if !errors.Is(err, context.DeadlineExceeded) {\n        t.Errorf(\"expected deadline exceeded, got: %v\", err)\n    }\n}",{"id":3824,"title":3825,"titles":3826,"content":3827,"level":119},"/v1.0.1/guides/testing#testing-hot-reload","Testing Hot Reload",[1767],"func TestHotReload(t *testing.T) {\n    factory := flume.New[Order]()\n    factory.Add(\n        pipz.Transform(\"v1\", func(_ context.Context, o Order) Order {\n            o.Version = \"v1\"\n            return o\n        }),\n        pipz.Transform(\"v2\", func(_ context.Context, o Order) Order {\n            o.Version = \"v2\"\n            return o\n        }),\n    )\n\n    // Set initial schema\n    factory.SetSchema(\"test\", flume.Schema{\n        Version: \"1.0.0\",\n        Node:    flume.Node{Ref: \"v1\"},\n    })\n\n    // Create binding with auto-sync\n    pipelineID := factory.Identity(\"test-pipeline\", \"Test pipeline\")\n    binding, _ := factory.Bind(pipelineID, \"test\", flume.WithAutoSync())\n\n    // Process with v1\n    result, _ := binding.Process(context.Background(), Order{})\n    if result.Version != \"v1\" {\n        t.Error(\"expected v1\")\n    }\n\n    // Update schema - binding auto-syncs\n    factory.SetSchema(\"test\", flume.Schema{\n        Version: \"2.0.0\",\n        Node:    flume.Node{Ref: \"v2\"},\n    })\n\n    // Process with v2\n    result, _ = binding.Process(context.Background(), Order{})\n    if result.Version != \"v2\" {\n        t.Error(\"expected v2\")\n    }\n}",{"id":3829,"title":3830,"titles":3831,"content":3832,"level":119},"/v1.0.1/guides/testing#concurrent-testing","Concurrent Testing",[1767],"func TestConcurrentPipelineAccess(t *testing.T) {\n    factory := setupFactory()\n    factory.SetSchema(\"test\", testSchema)\n\n    // Create binding with auto-sync\n    pipelineID := factory.Identity(\"concurrent-pipeline\", \"Concurrent test\")\n    binding, _ := factory.Bind(pipelineID, \"test\", flume.WithAutoSync())\n\n    var wg sync.WaitGroup\n    errors := make(chan error, 100)\n\n    for i := 0; i \u003C 100; i++ {\n        wg.Add(1)\n        go func(id int) {\n            defer wg.Done()\n            _, err := binding.Process(context.Background(), Order{ID: fmt.Sprint(id)})\n            if err != nil {\n                errors \u003C- err\n            }\n        }(i)\n    }\n\n    wg.Wait()\n    close(errors)\n\n    for err := range errors {\n        t.Error(err)\n    }\n}",{"id":3834,"title":3835,"titles":3836,"content":3837,"level":119},"/v1.0.1/guides/testing#test-helpers","Test Helpers",[1767],"The flume/testing package provides utilities: import flumetesting \"github.com/zoobz-io/flume/testing\"\n\nfunc TestWithHelpers(t *testing.T) {\n    tf := flumetesting.NewTestFactory(t)\n\n    // Register test processors\n    tf.RegisterNoOpProcessors(\"validate\", \"process\", \"finalize\")\n\n    // Build and test\n    pipeline, err := tf.Factory.BuildFromYAML(schema)\n    tf.AssertNoError(err)\n\n    result, err := pipeline.Process(context.Background(), flumetesting.TestData{ID: 1})\n    tf.AssertNoError(err)\n}",{"id":3839,"title":3559,"titles":3840,"content":3841,"level":119},"/v1.0.1/guides/testing#best-practices",[1767],"Test processors in isolation before integrationUse table-driven tests for schema variationsTest error paths explicitly - don't just test happy pathsTest concurrent access if using hot reloadKeep test factories minimal - only register what's needed",{"id":3843,"title":3031,"titles":3844,"content":3845,"level":119},"/v1.0.1/guides/testing#next-steps",[1767],"Observability - Monitor in productionTesting Package Reference - Test utilities html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}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 .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .skxcq, html code.shiki .skxcq{--shiki-default:var(--shiki-builtin)}",{"id":3847,"title":1359,"titles":3848,"content":3849,"level":112},"/v1.0.1/guides/observability",[],"Monitor Flume pipelines with Capitan events",{"id":3851,"title":1359,"titles":3852,"content":3853,"level":112},"/v1.0.1/guides/observability#observability",[],"Flume integrates with Capitan for comprehensive observability.",{"id":3855,"title":2900,"titles":3856,"content":3857,"level":119},"/v1.0.1/guides/observability#overview",[1359],"Flume emits structured events throughout its lifecycle: Factory creation and component registrationSchema validation, building, and updatesPipeline retrieval and executionFile loading and parsing",{"id":3859,"title":3860,"titles":3861,"content":104,"level":119},"/v1.0.1/guides/observability#event-categories","Event Categories",[1359],{"id":3863,"title":3864,"titles":3865,"content":3866,"level":150},"/v1.0.1/guides/observability#factory-events","Factory Events",[1359,3860],"flume.FactoryCreated      // Factory instantiated\nflume.ProcessorRegistered // Processor added\nflume.PredicateRegistered // Predicate added\nflume.ConditionRegistered // Condition added\nflume.ProcessorRemoved    // Processor removed\nflume.PredicateRemoved    // Predicate removed\nflume.ConditionRemoved    // Condition removed",{"id":3868,"title":3869,"titles":3870,"content":3871,"level":150},"/v1.0.1/guides/observability#schema-events","Schema Events",[1359,3860],"flume.SchemaValidationStarted   // Validation began\nflume.SchemaValidationCompleted // Validation successful\nflume.SchemaValidationFailed    // Validation failed\nflume.SchemaBuildStarted        // Build began\nflume.SchemaBuildCompleted      // Build successful\nflume.SchemaBuildFailed         // Build failed",{"id":3873,"title":3874,"titles":3875,"content":3876,"level":150},"/v1.0.1/guides/observability#dynamic-schema-events","Dynamic Schema Events",[1359,3860],"flume.SchemaRegistered   // New schema added\nflume.SchemaUpdated      // Existing schema replaced\nflume.SchemaRemoved      // Schema deleted\nflume.PipelineRetrieved  // Pipeline accessed",{"id":3878,"title":3879,"titles":3880,"content":3881,"level":150},"/v1.0.1/guides/observability#file-events","File Events",[1359,3860],"flume.SchemaFileLoaded  // File read successfully\nflume.SchemaFileFailed  // File read error\nflume.SchemaYAMLParsed  // YAML parsed\nflume.SchemaJSONParsed  // JSON parsed\nflume.SchemaParseFailed // Parse error",{"id":3883,"title":3884,"titles":3885,"content":3886,"level":119},"/v1.0.1/guides/observability#event-fields","Event Fields",[1359],"Events include typed fields for structured data: flume.KeyName       // string: component/schema name\nflume.KeyType       // string: data type\nflume.KeyVersion    // string: schema version\nflume.KeyOldVersion // string: previous version (updates)\nflume.KeyNewVersion // string: new version (updates)\nflume.KeyPath       // string: file path\nflume.KeyError      // string: error message\nflume.KeyDuration   // time.Duration: operation duration\nflume.KeyErrorCount // int: number of errors\nflume.KeySizeBytes  // int: file size\nflume.KeyFound      // bool: retrieval success",{"id":3888,"title":3889,"titles":3890,"content":104,"level":119},"/v1.0.1/guides/observability#setting-up-handlers","Setting Up Handlers",[1359],{"id":3892,"title":3893,"titles":3894,"content":3895,"level":150},"/v1.0.1/guides/observability#basic-logging","Basic Logging",[1359,3889],"import \"github.com/zoobz-io/capitan\"\n\nfunc setupLogging() {\n    // Log all schema events\n    capitan.Handle(flume.SchemaRegistered, func(ctx context.Context, fields []capitan.Field) {\n        log.Printf(\"Schema registered: %s\", extractString(fields, \"name\"))\n    })\n\n    capitan.Handle(flume.SchemaUpdated, func(ctx context.Context, fields []capitan.Field) {\n        log.Printf(\"Schema updated: %s (%s -> %s)\",\n            extractString(fields, \"name\"),\n            extractString(fields, \"old_version\"),\n            extractString(fields, \"new_version\"))\n    })\n\n    capitan.Handle(flume.SchemaBuildFailed, func(ctx context.Context, fields []capitan.Field) {\n        log.Printf(\"Build failed: %s\", extractString(fields, \"error\"))\n    })\n}\n\nfunc extractString(fields []capitan.Field, key string) string {\n    for _, f := range fields {\n        if f.Key == key {\n            return f.String()\n        }\n    }\n    return \"\"\n}",{"id":3897,"title":3898,"titles":3899,"content":3900,"level":150},"/v1.0.1/guides/observability#metrics-collection","Metrics Collection",[1359,3889],"import (\n    \"github.com/prometheus/client_golang/prometheus\"\n    \"github.com/zoobz-io/capitan\"\n)\n\nvar (\n    schemaUpdates = prometheus.NewCounterVec(\n        prometheus.CounterOpts{\n            Name: \"flume_schema_updates_total\",\n            Help: \"Total schema updates\",\n        },\n        []string{\"name\"},\n    )\n\n    buildDuration = prometheus.NewHistogramVec(\n        prometheus.HistogramOpts{\n            Name:    \"flume_build_duration_seconds\",\n            Help:    \"Schema build duration\",\n            Buckets: prometheus.DefBuckets,\n        },\n        []string{\"version\"},\n    )\n\n    buildFailures = prometheus.NewCounter(\n        prometheus.CounterOpts{\n            Name: \"flume_build_failures_total\",\n            Help: \"Total build failures\",\n        },\n    )\n)\n\nfunc setupMetrics() {\n    prometheus.MustRegister(schemaUpdates, buildDuration, buildFailures)\n\n    capitan.Handle(flume.SchemaUpdated, func(ctx context.Context, fields []capitan.Field) {\n        name := extractString(fields, \"name\")\n        schemaUpdates.WithLabelValues(name).Inc()\n    })\n\n    capitan.Handle(flume.SchemaBuildCompleted, func(ctx context.Context, fields []capitan.Field) {\n        version := extractString(fields, \"version\")\n        duration := extractDuration(fields, \"duration\")\n        buildDuration.WithLabelValues(version).Observe(duration.Seconds())\n    })\n\n    capitan.Handle(flume.SchemaBuildFailed, func(ctx context.Context, fields []capitan.Field) {\n        buildFailures.Inc()\n    })\n}",{"id":3902,"title":3903,"titles":3904,"content":3905,"level":150},"/v1.0.1/guides/observability#distributed-tracing","Distributed Tracing",[1359,3889],"import \"go.opentelemetry.io/otel/trace\"\n\nfunc setupTracing(tracer trace.Tracer) {\n    capitan.Handle(flume.SchemaBuildStarted, func(ctx context.Context, fields []capitan.Field) {\n        _, span := tracer.Start(ctx, \"flume.build\")\n        version := extractString(fields, \"version\")\n        span.SetAttributes(attribute.String(\"schema.version\", version))\n        // Store span for completion handler\n    })\n\n    capitan.Handle(flume.SchemaBuildCompleted, func(ctx context.Context, fields []capitan.Field) {\n        // End span\n    })\n}",{"id":3907,"title":3908,"titles":3909,"content":104,"level":119},"/v1.0.1/guides/observability#common-monitoring-patterns","Common Monitoring Patterns",[1359],{"id":3911,"title":3912,"titles":3913,"content":3914,"level":150},"/v1.0.1/guides/observability#schema-change-alerting","Schema Change Alerting",[1359,3908],"capitan.Handle(flume.SchemaUpdated, func(ctx context.Context, fields []capitan.Field) {\n    name := extractString(fields, \"name\")\n    oldVersion := extractString(fields, \"old_version\")\n    newVersion := extractString(fields, \"new_version\")\n\n    if isMajorVersionChange(oldVersion, newVersion) {\n        alerting.SendAlert(alerting.Warning, fmt.Sprintf(\n            \"Major schema version change: %s from %s to %s\",\n            name, oldVersion, newVersion))\n    }\n})",{"id":3916,"title":3917,"titles":3918,"content":3919,"level":150},"/v1.0.1/guides/observability#build-performance-tracking","Build Performance Tracking",[1359,3908],"capitan.Handle(flume.SchemaBuildCompleted, func(ctx context.Context, fields []capitan.Field) {\n    duration := extractDuration(fields, \"duration\")\n\n    if duration > 100*time.Millisecond {\n        log.Printf(\"Slow schema build: %v\", duration)\n    }\n})",{"id":3921,"title":3922,"titles":3923,"content":3924,"level":150},"/v1.0.1/guides/observability#validation-error-analysis","Validation Error Analysis",[1359,3908],"capitan.Handle(flume.SchemaValidationFailed, func(ctx context.Context, fields []capitan.Field) {\n    errorCount := extractInt(fields, \"error_count\")\n    duration := extractDuration(fields, \"duration\")\n\n    metrics.RecordValidationFailure(errorCount, duration)\n})",{"id":3926,"title":3927,"titles":3928,"content":104,"level":119},"/v1.0.1/guides/observability#debugging-with-events","Debugging with Events",[1359],{"id":3930,"title":3931,"titles":3932,"content":3933,"level":150},"/v1.0.1/guides/observability#development-logging","Development Logging",[1359,3927],"func setupDevLogging() {\n    // Log everything in development\n    signals := []capitan.Signal{\n        flume.FactoryCreated,\n        flume.ProcessorRegistered,\n        flume.SchemaValidationStarted,\n        flume.SchemaBuildStarted,\n        flume.SchemaBuildCompleted,\n        // ... all signals\n    }\n\n    for _, signal := range signals {\n        s := signal\n        capitan.Handle(s, func(ctx context.Context, fields []capitan.Field) {\n            log.Printf(\"[%s] %v\", s.Name, formatFields(fields))\n        })\n    }\n}",{"id":3935,"title":3936,"titles":3937,"content":3938,"level":150},"/v1.0.1/guides/observability#pipeline-access-tracking","Pipeline Access Tracking",[1359,3927],"capitan.Handle(flume.PipelineRetrieved, func(ctx context.Context, fields []capitan.Field) {\n    name := extractString(fields, \"name\")\n    found := extractBool(fields, \"found\")\n\n    if !found {\n        log.Printf(\"Pipeline not found: %s\", name)\n        metrics.PipelineMiss(name)\n    } else {\n        metrics.PipelineHit(name)\n    }\n})",{"id":3940,"title":3941,"titles":3942,"content":104,"level":119},"/v1.0.1/guides/observability#production-recommendations","Production Recommendations",[1359],{"id":3944,"title":3945,"titles":3946,"content":3947,"level":150},"/v1.0.1/guides/observability#_1-monitor-build-failures","1. Monitor Build Failures",[1359,3941],"Build failures indicate configuration issues: capitan.Handle(flume.SchemaBuildFailed, func(ctx context.Context, fields []capitan.Field) {\n    error := extractString(fields, \"error\")\n    alerting.Page(fmt.Sprintf(\"Flume build failed: %s\", error))\n})",{"id":3949,"title":3950,"titles":3951,"content":3952,"level":150},"/v1.0.1/guides/observability#_2-track-schema-versions","2. Track Schema Versions",[1359,3941],"Maintain audit trail: capitan.Handle(flume.SchemaUpdated, func(ctx context.Context, fields []capitan.Field) {\n    audit.Log(audit.Entry{\n        Action:     \"schema_update\",\n        Name:       extractString(fields, \"name\"),\n        OldVersion: extractString(fields, \"old_version\"),\n        NewVersion: extractString(fields, \"new_version\"),\n        Timestamp:  time.Now(),\n    })\n})",{"id":3954,"title":3955,"titles":3956,"content":3957,"level":150},"/v1.0.1/guides/observability#_3-set-up-dashboards","3. Set Up Dashboards",[1359,3941],"Key metrics to display: Schema update frequencyBuild success/failure rateBuild duration percentilesPipeline retrieval hit rateValidation error trends",{"id":3959,"title":3960,"titles":3961,"content":3962,"level":150},"/v1.0.1/guides/observability#_4-alert-on-anomalies","4. Alert on Anomalies",[1359,3941],"Sudden increase in build failuresUnusually long build timesHigh pipeline miss rateValidation errors after deployment",{"id":3964,"title":3031,"titles":3965,"content":3966,"level":119},"/v1.0.1/guides/observability#next-steps",[1359],"Events Reference - Complete event listCapitan Documentation - Event system details html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}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 .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}",{"id":3968,"title":1785,"titles":3969,"content":3970,"level":112},"/v1.0.1/cookbook/common-patterns",[],"Recipes and patterns for building pipelines with flume",{"id":3972,"title":1785,"titles":3973,"content":3974,"level":112},"/v1.0.1/cookbook/common-patterns#common-patterns",[],"Practical recipes for building pipelines with flume.",{"id":3976,"title":3977,"titles":3978,"content":3979,"level":119},"/v1.0.1/cookbook/common-patterns#validation-pipeline","Validation Pipeline",[1785],"A common pattern for validating input before processing: factory := flume.New[Order]()\n\nvalidateID := factory.Identity(\"validate\", \"Validates order data\")\nprocessID := factory.Identity(\"process\", \"Processes valid orders\")\nrejectID := factory.Identity(\"reject\", \"Handles invalid orders\")\nisValidID := factory.Identity(\"is-valid\", \"Checks order validity\")\n\nfactory.Add(\n    pipz.Apply(validateID, validateOrder),\n    pipz.Apply(processID, processOrder),\n    pipz.Apply(rejectID, rejectOrder),\n)\nfactory.AddPredicate(flume.Predicate[Order]{\n    Identity:  isValidID,\n    Predicate: func(ctx context.Context, o Order) bool { return o.Total > 0 },\n})\n\npipeline, _ := factory.BuildFromYAML(`\ntype: filter\npredicate: is-valid\nthen:\n  ref: process\nelse:\n  ref: reject\n`)",{"id":3981,"title":3982,"titles":3983,"content":3984,"level":119},"/v1.0.1/cookbook/common-patterns#retry-with-fallback","Retry with Fallback",[1785],"Retry an operation with a fallback on exhaustion: type: fallback\nchildren:\n  - type: retry\n    attempts: 3\n    backoff: \"100ms\"\n    child:\n      ref: primary-service\n  - ref: fallback-service",{"id":3986,"title":3987,"titles":3988,"content":3989,"level":119},"/v1.0.1/cookbook/common-patterns#fan-out-processing","Fan-Out Processing",[1785],"Process data through multiple paths concurrently: type: concurrent\nchildren:\n  - ref: save-to-database\n  - ref: send-notification\n  - ref: update-cache",{"id":3991,"title":3992,"titles":3993,"content":3994,"level":119},"/v1.0.1/cookbook/common-patterns#conditional-routing","Conditional Routing",[1785],"Route data based on type or category: type: switch\ncondition: order-type\nroutes:\n  standard:\n    ref: process-standard\n  express:\n    ref: process-express\n  priority:\n    ref: process-priority\ndefault:\n  ref: process-unknown",{"id":3996,"title":3997,"titles":3998,"content":3999,"level":119},"/v1.0.1/cookbook/common-patterns#stream-output","Stream Output",[1785],"Send processed data to a channel for async consumption: output := make(chan Order, 100)\nfactory.AddChannel(\"processed-orders\", output)\n\npipeline, _ := factory.BuildFromYAML(`\ntype: sequence\nchildren:\n  - ref: validate\n  - ref: enrich\n  - stream: processed-orders\n`)\n\n// Consume from channel\ngo func() {\n    for order := range output {\n        // Handle processed order\n    }\n}()",{"id":4001,"title":4002,"titles":4003,"content":4004,"level":119},"/v1.0.1/cookbook/common-patterns#circuit-breaker-protection","Circuit Breaker Protection",[1785],"Protect against cascading failures: type: circuit-breaker\nfailure_threshold: 5\nrecovery_timeout: \"30s\"\nchild:\n  ref: external-api-call",{"id":4006,"title":4007,"titles":4008,"content":4009,"level":119},"/v1.0.1/cookbook/common-patterns#rate-limited-processing","Rate-Limited Processing",[1785],"Throttle requests to downstream services: type: rate-limit\nrequests_per_second: 100\nburst_size: 10\nchild:\n  type: sequence\n  children:\n    - ref: transform\n    - ref: send-to-api html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}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 .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .skxcq, html code.shiki .skxcq{--shiki-default:var(--shiki-builtin)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}",{"id":4011,"title":1317,"titles":4012,"content":4013,"level":112},"/v1.0.1/reference/api",[],"Complete reference for Flume's public API",{"id":4015,"title":1317,"titles":4016,"content":4017,"level":112},"/v1.0.1/reference/api#api-reference",[],"Complete reference for Flume's public API.",{"id":4019,"title":4020,"titles":4021,"content":104,"level":119},"/v1.0.1/reference/api#factory","Factory",[1317],{"id":4023,"title":137,"titles":4024,"content":4025,"level":150},"/v1.0.1/reference/api#new",[1317,4020],"Creates a new factory for type T. func New[T pipz.Cloner[T]]() *Factory[T] Type Constraint: T must implement pipz.Cloner[T]. Example: factory := flume.New[Order]()",{"id":4027,"title":4028,"titles":4029,"content":104,"level":119},"/v1.0.1/reference/api#processor-registration","Processor Registration",[1317],{"id":4031,"title":157,"titles":4032,"content":4033,"level":150},"/v1.0.1/reference/api#add",[1317,4028],"Registers one or more processors using their intrinsic names. func (f *Factory[T]) Add(processors ...pipz.Chainable[T]) Parameters: processors - Variadic list of pipz chainables Example: factory.Add(\n    pipz.Apply(\"validate\", validateOrder),\n    pipz.Transform(\"enrich\", enrichOrder),\n)",{"id":4035,"title":4036,"titles":4037,"content":4038,"level":150},"/v1.0.1/reference/api#addwithmeta","AddWithMeta",[1317,4028],"Registers processors with metadata for introspection. func (f *Factory[T]) AddWithMeta(processors ...ProcessorMeta[T]) Parameters: processors - Variadic list of ProcessorMeta structs Example: factory.AddWithMeta(flume.ProcessorMeta[Order]{\n    Processor:   pipz.Apply(\"validate\", validateOrder),\n    Description: \"Validates order fields\",\n    Tags:        []string{\"validation\", \"required\"},\n})",{"id":4040,"title":4041,"titles":4042,"content":4043,"level":150},"/v1.0.1/reference/api#remove","Remove",[1317,4028],"Removes processors by name. func (f *Factory[T]) Remove(names ...pipz.Name) int Parameters: names - Variadic list of processor names Returns: Number of processors removed Example: removed := factory.Remove(\"old-processor\", \"deprecated\")",{"id":4045,"title":4046,"titles":4047,"content":4048,"level":150},"/v1.0.1/reference/api#hasprocessor","HasProcessor",[1317,4028],"Checks if a processor is registered. func (f *Factory[T]) HasProcessor(name pipz.Name) bool",{"id":4050,"title":4051,"titles":4052,"content":4053,"level":150},"/v1.0.1/reference/api#listprocessors","ListProcessors",[1317,4028],"Returns all registered processor names. func (f *Factory[T]) ListProcessors() []pipz.Name",{"id":4055,"title":4056,"titles":4057,"content":104,"level":119},"/v1.0.1/reference/api#predicate-registration","Predicate Registration",[1317],{"id":4059,"title":397,"titles":4060,"content":4061,"level":150},"/v1.0.1/reference/api#addpredicate",[1317,4056],"Registers predicates for filter conditions. func (f *Factory[T]) AddPredicate(predicates ...Predicate[T]) Example: factory.AddPredicate(flume.Predicate[Order]{\n    Name:        \"is-premium\",\n    Description: \"Customer has premium tier\",\n    Predicate: func(ctx context.Context, o Order) bool {\n        return o.CustomerTier == \"premium\"\n    },\n})",{"id":4063,"title":4064,"titles":4065,"content":4066,"level":150},"/v1.0.1/reference/api#removepredicate","RemovePredicate",[1317,4056],"Removes predicates by name. func (f *Factory[T]) RemovePredicate(names ...pipz.Name) int",{"id":4068,"title":4069,"titles":4070,"content":4071,"level":150},"/v1.0.1/reference/api#haspredicate","HasPredicate",[1317,4056],"Checks if a predicate is registered. func (f *Factory[T]) HasPredicate(name pipz.Name) bool",{"id":4073,"title":4074,"titles":4075,"content":4076,"level":150},"/v1.0.1/reference/api#listpredicates","ListPredicates",[1317,4056],"Returns all registered predicate names. func (f *Factory[T]) ListPredicates() []pipz.Name",{"id":4078,"title":4079,"titles":4080,"content":104,"level":119},"/v1.0.1/reference/api#condition-registration","Condition Registration",[1317],{"id":4082,"title":4083,"titles":4084,"content":4085,"level":150},"/v1.0.1/reference/api#addcondition","AddCondition",[1317,4079],"Registers conditions for switch routing. func (f *Factory[T]) AddCondition(conditions ...Condition[T]) Example: factory.AddCondition(flume.Condition[Order]{\n    Name:        \"order-status\",\n    Description: \"Returns the order status\",\n    Values:      []string{\"pending\", \"approved\", \"rejected\"},\n    Condition: func(ctx context.Context, o Order) string {\n        return o.Status\n    },\n})",{"id":4087,"title":4088,"titles":4089,"content":4090,"level":150},"/v1.0.1/reference/api#removecondition","RemoveCondition",[1317,4079],"Removes conditions by name. func (f *Factory[T]) RemoveCondition(names ...pipz.Name) int",{"id":4092,"title":4093,"titles":4094,"content":4095,"level":150},"/v1.0.1/reference/api#hascondition","HasCondition",[1317,4079],"Checks if a condition is registered. func (f *Factory[T]) HasCondition(name pipz.Name) bool",{"id":4097,"title":4098,"titles":4099,"content":4100,"level":150},"/v1.0.1/reference/api#listconditions","ListConditions",[1317,4079],"Returns all registered condition names. func (f *Factory[T]) ListConditions() []pipz.Name",{"id":4102,"title":4103,"titles":4104,"content":104,"level":119},"/v1.0.1/reference/api#channel-registration","Channel Registration",[1317],{"id":4106,"title":4107,"titles":4108,"content":4109,"level":150},"/v1.0.1/reference/api#addchannel","AddChannel",[1317,4103],"Registers a channel for stream nodes. func (f *Factory[T]) AddChannel(name string, channel chan\u003C- T) Example: ch := make(chan Order, 100)\nfactory.AddChannel(\"orders\", ch)",{"id":4111,"title":4112,"titles":4113,"content":4114,"level":150},"/v1.0.1/reference/api#getchannel","GetChannel",[1317,4103],"Retrieves a registered channel. func (f *Factory[T]) GetChannel(name string) (chan\u003C- T, bool)",{"id":4116,"title":4117,"titles":4118,"content":4119,"level":150},"/v1.0.1/reference/api#haschannel","HasChannel",[1317,4103],"Checks if a channel is registered. func (f *Factory[T]) HasChannel(name string) bool",{"id":4121,"title":4122,"titles":4123,"content":4124,"level":150},"/v1.0.1/reference/api#listchannels","ListChannels",[1317,4103],"Returns all registered channel names. func (f *Factory[T]) ListChannels() []string",{"id":4126,"title":4127,"titles":4128,"content":4129,"level":150},"/v1.0.1/reference/api#removechannel","RemoveChannel",[1317,4103],"Removes a channel from the factory. func (f *Factory[T]) RemoveChannel(name string) bool",{"id":4131,"title":1737,"titles":4132,"content":104,"level":119},"/v1.0.1/reference/api#building-pipelines",[1317],{"id":4134,"title":4135,"titles":4136,"content":4137,"level":150},"/v1.0.1/reference/api#build","Build",[1317,1737],"Builds a pipeline from a Schema struct. func (f *Factory[T]) Build(schema Schema) (pipz.Chainable[T], error) Example: schema := flume.Schema{\n    Version: \"1.0.0\",\n    Node: flume.Node{\n        Type: \"sequence\",\n        Children: []flume.Node{\n            {Ref: \"validate\"},\n            {Ref: \"process\"},\n        },\n    },\n}\npipeline, err := factory.Build(schema)",{"id":4139,"title":522,"titles":4140,"content":4141,"level":150},"/v1.0.1/reference/api#buildfromyaml",[1317,1737],"Builds a pipeline from a YAML string. func (f *Factory[T]) BuildFromYAML(yamlStr string) (pipz.Chainable[T], error) Example: schema := `\ntype: sequence\nchildren:\n  - ref: validate\n  - ref: process\n`\npipeline, err := factory.BuildFromYAML(schema)",{"id":4143,"title":4144,"titles":4145,"content":4146,"level":150},"/v1.0.1/reference/api#buildfromjson","BuildFromJSON",[1317,1737],"Builds a pipeline from a JSON string. func (f *Factory[T]) BuildFromJSON(jsonStr string) (pipz.Chainable[T], error)",{"id":4148,"title":4149,"titles":4150,"content":4151,"level":150},"/v1.0.1/reference/api#buildfromfile","BuildFromFile",[1317,1737],"Builds a pipeline from a file (YAML or JSON). func (f *Factory[T]) BuildFromFile(path string) (pipz.Chainable[T], error) Supported Extensions: .yaml, .yml, .json",{"id":4153,"title":4154,"titles":4155,"content":104,"level":119},"/v1.0.1/reference/api#schema-management","Schema Management",[1317],{"id":4157,"title":1481,"titles":4158,"content":4159,"level":150},"/v1.0.1/reference/api#setschema",[1317,4154],"Adds or updates a named schema. func (f *Factory[T]) SetSchema(name string, schema Schema) error Validates the schema, builds the pipeline, and stores both. If the schema exists, atomically updates it. Example: err := factory.SetSchema(\"order-pipeline\", schema)",{"id":4161,"title":4162,"titles":4163,"content":4164,"level":150},"/v1.0.1/reference/api#getschema","GetSchema",[1317,4154],"Retrieves a schema by name. func (f *Factory[T]) GetSchema(name string) (Schema, bool)",{"id":4166,"title":4167,"titles":4168,"content":4169,"level":150},"/v1.0.1/reference/api#removeschema","RemoveSchema",[1317,4154],"Removes a named schema. func (f *Factory[T]) RemoveSchema(name string) bool Returns: true if removed, false if not found",{"id":4171,"title":4172,"titles":4173,"content":4174,"level":150},"/v1.0.1/reference/api#listschemas","ListSchemas",[1317,4154],"Returns all registered schema names. func (f *Factory[T]) ListSchemas() []string",{"id":4176,"title":1606,"titles":4177,"content":4178,"level":150},"/v1.0.1/reference/api#bind",[1317,4154],"Creates or retrieves a binding for a schema. func (f *Factory[T]) Bind(identity pipz.Identity, schemaID string, opts ...BindingOption[T]) (*Binding[T], error) Parameters: identity - Unique identifier for this bindingschemaID - ID of schema in registry (must exist)opts - Optional configuration (e.g., WithAutoSync()) Returns: *Binding[T] on success, error if schema not found Example: pipelineID := factory.Identity(\"order-processor\", \"Processes orders\")\nbinding, err := factory.Bind(pipelineID, \"order-pipeline\", flume.WithAutoSync())\nif err != nil {\n    return err\n}\nresult, err := binding.Process(ctx, order)",{"id":4180,"title":4181,"titles":4182,"content":4183,"level":150},"/v1.0.1/reference/api#get","Get",[1317,4154],"Retrieves an existing binding by identity. func (f *Factory[T]) Get(identity pipz.Identity) *Binding[T] Returns: *Binding[T] if found, nil otherwise",{"id":4185,"title":4186,"titles":4187,"content":4188,"level":119},"/v1.0.1/reference/api#binding","Binding",[1317],"A Binding[T] represents a live pipeline bound to a schema. It provides lock-free execution via atomic.Pointer.",{"id":4190,"title":609,"titles":4191,"content":4192,"level":150},"/v1.0.1/reference/api#process",[1317,4186],"Executes the pipeline with the given data. func (b *Binding[T]) Process(ctx context.Context, data T) (T, error) Lock-free operation using atomic pointer access.",{"id":4194,"title":1625,"titles":4195,"content":4196,"level":150},"/v1.0.1/reference/api#withautosync",[1317,4186],"Option to enable automatic rebuilding when the source schema changes. flume.WithAutoSync[T]() When enabled, calls to factory.SetSchema() automatically rebuild this binding.",{"id":4198,"title":4199,"titles":4200,"content":4201,"level":150},"/v1.0.1/reference/api#binding-accessors","Binding Accessors",[1317,4186],"binding.Identity()  // Returns pipz.Identity\nbinding.SchemaID()  // Returns string (schema ID)\nbinding.AutoSync()  // Returns bool\nbinding.Pipeline()  // Returns *pipz.Pipeline[T]",{"id":4203,"title":2939,"titles":4204,"content":104,"level":119},"/v1.0.1/reference/api#validation",[1317],{"id":4206,"title":2118,"titles":4207,"content":4208,"level":150},"/v1.0.1/reference/api#validateschema",[1317,2939],"Validates a schema against registered components without building it. func (f *Factory[T]) ValidateSchema(schema Schema) error Returns: nil if valid, ValidationErrors otherwise Checks: Schema structure (node types, required fields)All processor references existAll predicate references existAll condition references existAll reducer references existAll error handler references existAll channel references existCircular reference detection Example: if err := factory.ValidateSchema(schema); err != nil {\n    fmt.Println(err)\n    // 3 validation errors:\n    //   1. root.children[0]: processor 'missing' not found\n    //   ...\n}",{"id":4210,"title":2112,"titles":4211,"content":4212,"level":150},"/v1.0.1/reference/api#validateschemastructure",[1317,2939],"Validates schema syntax without requiring registered components. Use this for CI/CD schema linting where a configured factory is not available. func ValidateSchemaStructure(schema Schema) error Returns: nil if valid, ValidationErrors otherwise This validates: Node structure (ref vs type exclusivity, non-empty nodes)Connector constraints (required children, child counts)Configuration values (valid durations, positive numbers)Unknown node types This does NOT validate: Processor references existPredicate references existCondition references existReducer references existError handler references existChannel references exist Example: // CI/CD pipeline - validate schema files without a configured factory\nschema, _ := yaml.Unmarshal(data, &flume.Schema{})\nif err := flume.ValidateSchemaStructure(schema); err != nil {\n    log.Fatalf(\"Invalid schema: %v\", err)\n}",{"id":4214,"title":4215,"titles":4216,"content":104,"level":119},"/v1.0.1/reference/api#types","Types",[1317],{"id":4218,"title":4219,"titles":4220,"content":4221,"level":150},"/v1.0.1/reference/api#schema","Schema",[1317,4215],"type Schema struct {\n    Version string `json:\"version,omitempty\" yaml:\"version,omitempty\"`\n    Node    `yaml:\",inline\"`\n}",{"id":4223,"title":2515,"titles":4224,"content":4225,"level":150},"/v1.0.1/reference/api#node",[1317,4215],"type Node struct {\n    Ref               string          // Processor reference\n    Type              string          // Connector type\n    Name              string          // Optional name override\n    Children          []Node          // For sequence, concurrent, etc.\n    Child             *Node           // For retry, timeout, etc.\n    Predicate         string          // For filter\n    Then              *Node           // For filter\n    Else              *Node           // For filter\n    Condition         string          // For switch\n    Routes            map[string]Node // For switch\n    Default           *Node           // For switch\n    Attempts          int             // For retry\n    Backoff           string          // For retry\n    Duration          string          // For timeout\n    FailureThreshold  int             // For circuit-breaker\n    RecoveryTimeout   string          // For circuit-breaker\n    RequestsPerSecond float64         // For rate-limit\n    BurstSize         int             // For rate-limit\n    Stream            string          // For stream nodes\n}",{"id":4227,"title":406,"titles":4228,"content":4229,"level":150},"/v1.0.1/reference/api#predicate",[1317,4215],"type Predicate[T any] struct {\n    Name        pipz.Name\n    Description string\n    Predicate   func(context.Context, T) bool\n}",{"id":4231,"title":4232,"titles":4233,"content":4234,"level":150},"/v1.0.1/reference/api#condition","Condition",[1317,4215],"type Condition[T any] struct {\n    Name        pipz.Name\n    Description string\n    Values      []string  // Possible return values\n    Condition   func(context.Context, T) string\n}",{"id":4236,"title":4237,"titles":4238,"content":4239,"level":150},"/v1.0.1/reference/api#processormeta","ProcessorMeta",[1317,4215],"type ProcessorMeta[T any] struct {\n    Processor   pipz.Chainable[T]\n    Description string\n    Tags        []string\n}",{"id":4241,"title":4242,"titles":4243,"content":4244,"level":150},"/v1.0.1/reference/api#reducer","Reducer",[1317,4215],"type Reducer[T any] struct {\n    Name        pipz.Name\n    Description string\n    Reducer     func(original T, results map[pipz.Name]T, errors map[pipz.Name]error) T\n} Used with concurrent connector to merge results from parallel execution. Example: factory.AddReducer(flume.Reducer[Order]{\n    Name:        \"merge-enrichments\",\n    Description: \"Combines data from parallel enrichment sources\",\n    Reducer: func(original Order, results map[pipz.Name]Order, errors map[pipz.Name]error) Order {\n        for _, result := range results {\n            original.Metadata = append(original.Metadata, result.Metadata...)\n        }\n        return original\n    },\n})",{"id":4246,"title":4247,"titles":4248,"content":4249,"level":150},"/v1.0.1/reference/api#errorhandler","ErrorHandler",[1317,4215],"type ErrorHandler[T any] struct {\n    Name        pipz.Name\n    Description string\n    Handler     pipz.Chainable[*pipz.Error[T]]\n} Used with handle connector to process errors from child execution. The handler receives a *pipz.Error[T] containing both the original data and the error. Error Recovery Pattern: Clear the error to indicate successful recovery: factory.AddErrorHandler(flume.ErrorHandler[Order]{\n    Name:        \"order-recovery\",\n    Description: \"Recovers failed orders by marking them for retry\",\n    Handler: pipz.Apply(\"recover\", func(ctx context.Context, e *pipz.Error[Order]) (*pipz.Error[Order], error) {\n        e.Data.Status = \"pending-retry\"\n        e.Err = nil  // Clear error - pipeline continues normally\n        return e, nil\n    }),\n}) Error Transformation Pattern: Transform the error while preserving failure state: factory.AddErrorHandler(flume.ErrorHandler[Order]{\n    Name:        \"error-enricher\",\n    Description: \"Enriches errors with context before propagating\",\n    Handler: pipz.Apply(\"enrich-error\", func(ctx context.Context, e *pipz.Error[Order]) (*pipz.Error[Order], error) {\n        e.Err = fmt.Errorf(\"order %s: %w\", e.Data.ID, e.Err)\n        return e, nil  // Error still propagates\n    }),\n}) Conditional Recovery Pattern: Recover from specific errors only: factory.AddErrorHandler(flume.ErrorHandler[Order]{\n    Name:        \"transient-recovery\",\n    Description: \"Recovers from transient errors, propagates others\",\n    Handler: pipz.Apply(\"conditional-recover\", func(ctx context.Context, e *pipz.Error[Order]) (*pipz.Error[Order], error) {\n        if errors.Is(e.Err, ErrTemporaryFailure) {\n            e.Data.Status = \"retrying\"\n            e.Err = nil  // Recover\n        }\n        // Non-transient errors propagate unchanged\n        return e, nil\n    }),\n}) Schema Usage: type: handle\nerror_handler: order-recovery\nchild:\n  ref: risky-operation",{"id":4251,"title":4252,"titles":4253,"content":4254,"level":150},"/v1.0.1/reference/api#validationerror","ValidationError",[1317,4215],"type ValidationError struct {\n    Path    []string  // Path to error in schema\n    Message string\n}\n\nfunc (e ValidationError) Error() string",{"id":4256,"title":4257,"titles":4258,"content":4259,"level":150},"/v1.0.1/reference/api#validationerrors","ValidationErrors",[1317,4215],"type ValidationErrors []ValidationError\n\nfunc (e ValidationErrors) Error() string",{"id":4261,"title":4262,"titles":4263,"content":104,"level":119},"/v1.0.1/reference/api#constants","Constants",[1317],{"id":4265,"title":4266,"titles":4267,"content":4268,"level":150},"/v1.0.1/reference/api#default-values","Default Values",[1317,4262],"const (\n    DefaultRetryAttempts           = 3\n    DefaultTimeoutDuration         = 30 * time.Second\n    DefaultCircuitBreakerThreshold = 5\n    DefaultRecoveryTimeout         = 60 * time.Second\n    DefaultRequestsPerSecond       = 10.0\n    DefaultBurstSize               = 1\n)",{"id":4270,"title":3031,"titles":4271,"content":4272,"level":119},"/v1.0.1/reference/api#next-steps",[1317],"Schema Format - YAML/JSON specificationConnector Types - All connector optionsEvents - Observability signals html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}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 .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .skxcq, html code.shiki .skxcq{--shiki-default:var(--shiki-builtin)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .sfm-E, html code.shiki .sfm-E{--shiki-default:var(--shiki-variable)}",{"id":4274,"title":1290,"titles":4275,"content":4276,"level":112},"/v1.0.1/reference/schema-format",[],"Complete YAML/JSON schema specification",{"id":4278,"title":1290,"titles":4279,"content":4280,"level":112},"/v1.0.1/reference/schema-format#schema-format",[],"Complete specification for Flume schema documents.",{"id":4282,"title":2900,"titles":4283,"content":4284,"level":119},"/v1.0.1/reference/schema-format#overview",[1290],"Schemas can be written in YAML or JSON. This reference uses YAML examples; JSON equivalents use standard JSON syntax.",{"id":4286,"title":3079,"titles":4287,"content":4288,"level":119},"/v1.0.1/reference/schema-format#schema-structure",[1290],"version: \"1.0.0\"    # Optional: schema version\ntype: sequence      # Required: connector type OR ref\nname: my-pipeline   # Optional: override connector name\nchildren:           # Depends on type\n  - ref: step1\n  - ref: step2",{"id":4290,"title":4291,"titles":4292,"content":4293,"level":119},"/v1.0.1/reference/schema-format#top-level-fields","Top-Level Fields",[1290],"FieldTypeRequiredDescriptionversionstringNoSchema version for tracking changesrefstringConditionalReference to registered processortypestringConditionalConnector typenamestringNoOverride default connector name Either ref or type is required, but not both.",{"id":4295,"title":4296,"titles":4297,"content":4298,"level":119},"/v1.0.1/reference/schema-format#processor-reference","Processor Reference",[1290],"Reference a registered processor by name: ref: validate Equivalent to calling the processor directly.",{"id":4300,"title":1345,"titles":4301,"content":104,"level":119},"/v1.0.1/reference/schema-format#connector-types",[1290],{"id":4303,"title":4304,"titles":4305,"content":4306,"level":150},"/v1.0.1/reference/schema-format#sequence","sequence",[1290,1345],"Sequential processing through multiple steps. type: sequence\nname: my-sequence      # Optional\nchildren:              # Required: 1+ children\n  - ref: step1\n  - ref: step2\n  - ref: step3 FieldTypeRequiredDefaultchildrenNodeYes-namestringNo\"sequence\"",{"id":4308,"title":4309,"titles":4310,"content":4311,"level":150},"/v1.0.1/reference/schema-format#concurrent","concurrent",[1290,1345],"Parallel execution with data cloning. type: concurrent\nname: parallel-steps   # Optional\nchildren:              # Required: 1+ children\n  - ref: task1\n  - ref: task2 FieldTypeRequiredDefaultchildrenNodeYes-namestringNo\"concurrent\" Note: Requires T to implement pipz.Cloner[T].",{"id":4313,"title":4314,"titles":4315,"content":4316,"level":150},"/v1.0.1/reference/schema-format#race","race",[1290,1345],"First successful result wins. type: race\nchildren:\n  - ref: fast-path\n  - ref: slow-path FieldTypeRequiredDefaultchildrenNodeYes-namestringNo\"race\" Note: Requires T to implement pipz.Cloner[T].",{"id":4318,"title":4319,"titles":4320,"content":4321,"level":150},"/v1.0.1/reference/schema-format#fallback","fallback",[1290,1345],"Try primary, use fallback on error. type: fallback\nchildren:\n  - ref: primary       # First child is primary\n  - ref: backup        # Second child is fallback FieldTypeRequiredDefaultchildrenNode (exactly 2)Yes-namestringNo\"fallback\"",{"id":4323,"title":4324,"titles":4325,"content":4326,"level":150},"/v1.0.1/reference/schema-format#retry","retry",[1290,1345],"Retry operation on failure. type: retry\nattempts: 5            # Optional\nbackoff: \"100ms\"       # Optional: enables exponential backoff\nchild:                 # Required\n  ref: flaky-operation FieldTypeRequiredDefaultchildNodeYes-attemptsintNo3backoffdurationNo(none)namestringNo\"retry\" or \"backoff\"",{"id":4328,"title":4329,"titles":4330,"content":4331,"level":150},"/v1.0.1/reference/schema-format#timeout","timeout",[1290,1345],"Enforce time limit. type: timeout\nduration: \"5s\"         # Optional\nchild:                 # Required\n  ref: slow-operation FieldTypeRequiredDefaultchildNodeYes-durationdurationNo\"30s\"namestringNo\"timeout\"",{"id":4333,"title":4334,"titles":4335,"content":4336,"level":150},"/v1.0.1/reference/schema-format#filter","filter",[1290,1345],"Conditional execution based on predicate. type: filter\npredicate: is-valid    # Required: registered predicate name\nthen:                  # Required\n  ref: process-valid\nelse:                  # Optional\n  ref: handle-invalid FieldTypeRequiredDefaultpredicatestringYes-thenNodeYes-elseNodeNo(passthrough)namestringNo\"filter-{predicate}\"",{"id":4338,"title":4339,"titles":4340,"content":4341,"level":150},"/v1.0.1/reference/schema-format#switch","switch",[1290,1345],"Multi-way routing based on condition. type: switch\ncondition: order-type  # Required: registered condition name\nroutes:                # Required: 1+ routes\n  subscription:\n    ref: handle-subscription\n  one-time:\n    ref: handle-single\ndefault:               # Optional\n  ref: handle-unknown FieldTypeRequiredDefaultconditionstringYes-routesmapstringNodeYes-defaultNodeNo(none)namestringNo\"switch-{condition}\" Default Routing: The default node is registered as a route with key \"default\". For default routing to work, your condition function must return the string \"default\" when no other route matches: factory.AddCondition(flume.Condition[Order]{\n    Name: \"order-type\",\n    Condition: func(ctx context.Context, o Order) string {\n        switch o.Type {\n        case \"subscription\":\n            return \"subscription\"\n        case \"one-time\":\n            return \"one-time\"\n        default:\n            return \"default\"  // Triggers the default route\n        }\n    },\n})",{"id":4343,"title":4344,"titles":4345,"content":4346,"level":150},"/v1.0.1/reference/schema-format#circuit-breaker","circuit-breaker",[1290,1345],"Circuit breaker pattern. type: circuit-breaker\nfailure_threshold: 5   # Optional\nrecovery_timeout: \"60s\"  # Optional\nchild:                 # Required\n  ref: external-service FieldTypeRequiredDefaultchildNodeYes-failure_thresholdintNo5recovery_timeoutdurationNo\"60s\"namestringNo\"circuit-breaker\"",{"id":4348,"title":4349,"titles":4350,"content":4351,"level":150},"/v1.0.1/reference/schema-format#rate-limit","rate-limit",[1290,1345],"Rate limiting with token bucket. type: rate-limit\nrequests_per_second: 100.0  # Optional\nburst_size: 10              # Optional\nchild:                      # Required\n  ref: rate-sensitive-api FieldTypeRequiredDefaultchildNodeYes-requests_per_secondfloatNo10.0burst_sizeintNo1namestringNo\"rate-limit\"",{"id":4353,"title":4354,"titles":4355,"content":4356,"level":150},"/v1.0.1/reference/schema-format#stream","stream",[1290,1345],"Send to registered channel. stream: output-channel  # Required: channel name\nstream_timeout: \"5s\"    # Optional: timeout for channel write\nchild:                  # Optional: continue processing\n  ref: next-step FieldTypeRequiredDefaultstreamstringYes-stream_timeoutdurationNo(blocks indefinitely)childNodeNo(none)childrenNodeNo(none)namestringNo\"stream:{name}\" Timeout Behaviour: Without stream_timeout, the stream blocks until the channel accepts the item or the context is cancelled. With stream_timeout, returns an error if the channel doesn't accept within the duration.",{"id":4358,"title":4359,"titles":4360,"content":4361,"level":150},"/v1.0.1/reference/schema-format#contest","contest",[1290,1345],"First result satisfying a predicate. type: contest\npredicate: is-valid      # Required: registered predicate name\nchildren:                # Required: 1+ children\n  - ref: source1\n  - ref: source2 FieldTypeRequiredDefaultpredicatestringYes-childrenNodeYes-namestringNo\"contest-{predicate}\" Note: Requires T to implement pipz.Cloner[T].",{"id":4363,"title":4364,"titles":4365,"content":4366,"level":150},"/v1.0.1/reference/schema-format#handle","handle",[1290,1345],"Wrap child with error handling. type: handle\nerror_handler: recovery  # Required: registered error handler name\nchild:                   # Required\n  ref: risky-operation FieldTypeRequiredDefaulterror_handlerstringYes-childNodeYes-namestringNo\"handle-{handler}\"",{"id":4368,"title":4369,"titles":4370,"content":4371,"level":150},"/v1.0.1/reference/schema-format#scaffold","scaffold",[1290,1345],"Structural grouping of children. type: scaffold\nname: validation-stage   # Optional\nchildren:                # Required: 1+ children\n  - ref: step1\n  - ref: step2 FieldTypeRequiredDefaultchildrenNodeYes-namestringNo\"scaffold\"",{"id":4373,"title":4374,"titles":4375,"content":4376,"level":150},"/v1.0.1/reference/schema-format#worker-pool","worker-pool",[1290,1345],"Bounded parallel execution. type: worker-pool\nworkers: 8               # Optional\nchildren:                # Required: 1+ children\n  - ref: task1\n  - ref: task2 FieldTypeRequiredDefaultchildrenNodeYes-workersintNo4namestringNo\"worker-pool\" Note: Requires T to implement pipz.Cloner[T].",{"id":4378,"title":4379,"titles":4380,"content":4381,"level":119},"/v1.0.1/reference/schema-format#duration-format","Duration Format",[1290],"Durations use Go's duration format: FormatExampleNanoseconds100nsMicroseconds50µs or 50usMilliseconds100msSeconds5sMinutes2mHours1hCombined1h30m, 2m30s",{"id":4383,"title":4384,"titles":4385,"content":4386,"level":119},"/v1.0.1/reference/schema-format#nesting","Nesting",[1290],"Nodes can be nested arbitrarily: type: sequence\nchildren:\n  - ref: validate\n  - type: filter\n    predicate: is-premium\n    then:\n      type: retry\n      attempts: 3\n      child:\n        type: timeout\n        duration: \"5s\"\n        child:\n          ref: premium-process\n  - ref: finalize",{"id":4388,"title":4389,"titles":4390,"content":4391,"level":119},"/v1.0.1/reference/schema-format#json-format","JSON Format",[1290],"Equivalent JSON for the nested example: {\n  \"type\": \"sequence\",\n  \"children\": [\n    {\"ref\": \"validate\"},\n    {\n      \"type\": \"filter\",\n      \"predicate\": \"is-premium\",\n      \"then\": {\n        \"type\": \"retry\",\n        \"attempts\": 3,\n        \"child\": {\n          \"type\": \"timeout\",\n          \"duration\": \"5s\",\n          \"child\": {\"ref\": \"premium-process\"}\n        }\n      }\n    },\n    {\"ref\": \"finalize\"}\n  ]\n}",{"id":4393,"title":4394,"titles":4395,"content":4396,"level":119},"/v1.0.1/reference/schema-format#validation-rules","Validation Rules",[1290],"Either ref or type - Node must have exactly oneRequired fields - Each type has required fieldsRegistered components - All refs, predicates, conditions must existCorrect counts - fallback needs exactly 2 childrenValid durations - Duration strings must parsePositive values - attempts, threshold must be positiveNo cycles - Reference chains cannot loop",{"id":4398,"title":3031,"titles":4399,"content":4400,"level":119},"/v1.0.1/reference/schema-format#next-steps",[1290],"Connector Types - Detailed connector behaviourAPI Reference - Factory methods html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}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 .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}",{"id":4402,"title":1345,"titles":4403,"content":4404,"level":112},"/v1.0.1/reference/connector-types",[],"Detailed reference for all Flume connector types",{"id":4406,"title":1345,"titles":4407,"content":4408,"level":112},"/v1.0.1/reference/connector-types#connector-types",[],"Detailed reference for all Flume connector types and their behaviour.",{"id":4410,"title":4411,"titles":4412,"content":104,"level":119},"/v1.0.1/reference/connector-types#flow-control","Flow Control",[1345],{"id":4414,"title":4304,"titles":4415,"content":4416,"level":150},"/v1.0.1/reference/connector-types#sequence",[1345,4411],"Processes data through multiple steps in order. Schema: type: sequence\nchildren:\n  - ref: step1\n  - ref: step2\n  - ref: step3 Behaviour: Process step1 with input dataPass step1 output to step2Pass step2 output to step3Return step3 output Error Handling: Stops on first error, returns that error. Use Cases: Multi-stage processingPipeline compositionSequential transformations",{"id":4418,"title":4309,"titles":4419,"content":4420,"level":150},"/v1.0.1/reference/connector-types#concurrent",[1345,4411],"Executes multiple steps in parallel. Schema: type: concurrent\nchildren:\n  - ref: task1\n  - ref: task2\n  - ref: task3 Behaviour: Clone input data for each childExecute all children concurrentlyWait for all to completeMerge results Error Handling: Collects all errors, returns first error encountered. Requirements: Type T must implement pipz.Cloner[T]. Use Cases: Parallel enrichment from multiple sourcesIndependent validationsConcurrent API calls",{"id":4422,"title":4314,"titles":4423,"content":4424,"level":150},"/v1.0.1/reference/connector-types#race",[1345,4411],"Returns first successful result. Schema: type: race\nchildren:\n  - ref: fast-path\n  - ref: slow-path Behaviour: Clone input data for each childExecute all children concurrentlyReturn first successful resultCancel other executions Error Handling: Returns error only if all children fail. Requirements: Type T must implement pipz.Cloner[T]. Use Cases: Redundant data sourcesFastest-wins scenariosSpeculative execution",{"id":4426,"title":1760,"titles":4427,"content":104,"level":119},"/v1.0.1/reference/connector-types#error-handling",[1345],{"id":4429,"title":4319,"titles":4430,"content":4431,"level":150},"/v1.0.1/reference/connector-types#fallback",[1345,1760],"Provides backup processing on failure. Schema: type: fallback\nchildren:\n  - ref: primary\n  - ref: backup Behaviour: Execute primary with inputIf primary succeeds, return resultIf primary fails, execute backupReturn backup result or error Requirements: Exactly 2 children. Use Cases: Service redundancyGraceful degradationDefault value provision",{"id":4433,"title":4324,"titles":4434,"content":4435,"level":150},"/v1.0.1/reference/connector-types#retry",[1345,1760],"Retries on transient failures. Schema: type: retry\nattempts: 3\nchild:\n  ref: operation With backoff: type: retry\nattempts: 5\nbackoff: \"100ms\"\nchild:\n  ref: operation Behaviour without backoff: Execute childIf error, retry up to attempts timesReturn success or final error Behaviour with backoff: Execute childIf error, wait backoff durationRetry with doubled wait time (exponential)Continue until success or attempts exhausted Defaults: attempts: 3backoff: none (immediate retry) Use Cases: Network timeoutsRate limit handlingTransient service failures",{"id":4437,"title":4329,"titles":4438,"content":4439,"level":150},"/v1.0.1/reference/connector-types#timeout",[1345,1760],"Enforces execution time limit. Schema: type: timeout\nduration: \"5s\"\nchild:\n  ref: operation Behaviour: Start child execution with deadline contextIf completes before deadline, return resultIf deadline exceeded, cancel and return error Default: 30 seconds Error: Returns context.DeadlineExceeded Use Cases: External API callsLong-running computationsUser-facing requests",{"id":4441,"title":4344,"titles":4442,"content":4443,"level":150},"/v1.0.1/reference/connector-types#circuit-breaker",[1345,1760],"Prevents repeated calls to failing services. Schema: type: circuit-breaker\nfailure_threshold: 5\nrecovery_timeout: \"30s\"\nchild:\n  ref: service States: StateBehaviourClosedNormal operation, count failuresOpenFail immediately, don't call childHalf-OpenAllow one test request Behaviour: Closed: Execute child, count failuresAfter failure_threshold failures, open circuitOpen: Return error immediatelyAfter recovery_timeout, enter half-openHalf-Open: Execute one test requestIf test succeeds, close circuitIf test fails, reopen circuit Defaults: failure_threshold: 5recovery_timeout: 60s Use Cases: External service protectionCascade failure preventionAllowing service recovery",{"id":4445,"title":4349,"titles":4446,"content":4447,"level":150},"/v1.0.1/reference/connector-types#rate-limit",[1345,1760],"Controls request throughput. Schema: type: rate-limit\nrequests_per_second: 100.0\nburst_size: 10\nchild:\n  ref: operation Behaviour: Wait for token from bucketExecute childReturn result Uses token bucket algorithm: Tokens added at requests_per_second rateUp to burst_size tokens can accumulateRequest waits if no tokens available Defaults: requests_per_second: 10.0burst_size: 1 Use Cases: API rate limit complianceResource protectionFair usage enforcement",{"id":4449,"title":4450,"titles":4451,"content":104,"level":119},"/v1.0.1/reference/connector-types#routing","Routing",[1345],{"id":4453,"title":4334,"titles":4454,"content":4455,"level":150},"/v1.0.1/reference/connector-types#filter",[1345,4450],"Conditional execution based on boolean predicate. Schema: type: filter\npredicate: is-valid\nthen:\n  ref: process\nelse:\n  ref: handle-invalid  # Optional Behaviour with else: Evaluate predicateIf true, execute then branchIf false, execute else branchReturn result Behaviour without else: Evaluate predicateIf true, execute then branchIf false, pass data through unchanged Requirements: Predicate must be registered with factory. Use Cases: Conditional processingFeature flagsValidation gates",{"id":4457,"title":4339,"titles":4458,"content":4459,"level":150},"/v1.0.1/reference/connector-types#switch",[1345,4450],"Multi-way routing based on condition value. Schema: type: switch\ncondition: category\nroutes:\n  electronics:\n    ref: handle-electronics\n  clothing:\n    ref: handle-clothing\n  food:\n    ref: handle-food\ndefault:\n  ref: handle-other Behaviour: Evaluate condition functionMatch return value to route keyExecute matched routeIf no match and default exists, execute defaultIf no match and no default, pass through unchanged Default Route: The condition function should return \"default\" for default routing. Requirements: Condition must be registered with factory. Use Cases: Multi-tenant routingCategory handlingStatus-based processing",{"id":4461,"title":4462,"titles":4463,"content":104,"level":119},"/v1.0.1/reference/connector-types#streaming","Streaming",[1345],{"id":4465,"title":4354,"titles":4466,"content":4467,"level":150},"/v1.0.1/reference/connector-types#stream",[1345,4462],"Sends data to a registered channel. Schema (terminal): stream: output-channel Schema (with timeout): stream: output-channel\nstream_timeout: \"5s\" Schema (with continuation): stream: audit-channel\nchild:\n  ref: continue-processing Behaviour (terminal): Send data to channelReturn data (unchanged) Behaviour (with child): Send data to channelExecute childReturn child result Timeout Behaviour: Without stream_timeout: Blocks until channel accepts or context cancelledWith stream_timeout: Returns error if write doesn't complete within duration Requirements: Channel must be registered with factory. Use Cases: Stream processing integrationAsync event publishingAudit loggingFan-out patterns",{"id":4469,"title":4470,"titles":4471,"content":104,"level":119},"/v1.0.1/reference/connector-types#advanced","Advanced",[1345],{"id":4473,"title":4359,"titles":4474,"content":4475,"level":150},"/v1.0.1/reference/connector-types#contest",[1345,4470],"Runs children concurrently and returns the first result satisfying a predicate. Schema: type: contest\npredicate: is-valid\nchildren:\n  - ref: source1\n  - ref: source2\n  - ref: source3 Behaviour: Clone input data for each childExecute all children concurrentlyEvaluate predicate against each result as it completesReturn first result where predicate returns trueCancel remaining executions Error Handling: Returns error if no child produces a result satisfying the predicate. Requirements: Type T must implement pipz.Cloner[T]Predicate must be registered with factory Use Cases: Find first valid response from multiple sourcesSpeculative execution with validationBest-effort data retrieval",{"id":4477,"title":4364,"titles":4478,"content":4479,"level":150},"/v1.0.1/reference/connector-types#handle",[1345,4470],"Wraps a child with custom error handling logic. Schema: type: handle\nerror_handler: recovery-handler\nchild:\n  ref: risky-operation Behaviour: Execute childIf child succeeds, return resultIf child fails, pass error to handlerHandler receives *pipz.Error[T] with original data and errorReturn handler result Error Handling: Handler can recover, transform, or propagate the error. Requirements: Error handler must be registered with factory. Use Cases: Custom error recoveryError transformationContextual error handlingCompensating transactions",{"id":4481,"title":4369,"titles":4482,"content":4483,"level":150},"/v1.0.1/reference/connector-types#scaffold",[1345,4470],"Structural wrapper that groups children for organisational purposes. Schema: type: scaffold\nname: validation-stage\nchildren:\n  - ref: validate-format\n  - ref: validate-business-rules\n  - ref: validate-permissions Behaviour: Execute children in sequencePass output of each child to the nextReturn final child's output Error Handling: Stops on first error, returns that error. Use Cases: Logical grouping of related processorsPipeline organisationNamed stages for observability",{"id":4485,"title":4374,"titles":4486,"content":4487,"level":150},"/v1.0.1/reference/connector-types#worker-pool",[1345,4470],"Distributes work across a pool of workers. Schema: type: worker-pool\nworkers: 8\nchildren:\n  - ref: task1\n  - ref: task2\n  - ref: task3 Behaviour: Create pool of workers goroutinesDistribute children across workersExecute concurrently within worker limitCollect and merge results Defaults: workers: 4 Requirements: Type T must implement pipz.Cloner[T]. Use Cases: Bounded concurrencyResource-constrained parallel processingBatch processing with limits",{"id":4489,"title":4490,"titles":4491,"content":4492,"level":119},"/v1.0.1/reference/connector-types#comparison-table","Comparison Table",[1345],"TypePurposeError BehaviourCloningsequenceChain stepsStop on errorNoconcurrentParallel executionReturn first errorYesraceFirst successError if all failYesfallbackBackup processingTry backupNoretryTransient failuresRetry n timesNotimeoutTime limitCancel on timeoutNocircuit-breakerFailure protectionFail fast when openNorate-limitThroughput controlWait for tokenNofilterConditional routingFrom branchNoswitchMulti-way routingFrom routeNostreamChannel outputFrom sendNocontestFirst valid resultError if none validYeshandleError handlingFrom handlerNoscaffoldLogical groupingStop on errorNoworker-poolBounded parallelismReturn first errorYes",{"id":4494,"title":3031,"titles":4495,"content":4496,"level":119},"/v1.0.1/reference/connector-types#next-steps",[1345],"Schema Format - YAML/JSON syntaxEvents - Observability signals html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}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 .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}",{"id":4498,"title":1813,"titles":4499,"content":4500,"level":112},"/v1.0.1/reference/events",[],"Complete reference for Flume observability events",{"id":4502,"title":1813,"titles":4503,"content":4504,"level":112},"/v1.0.1/reference/events#events",[],"Complete reference for Flume's observability events using Capitan.",{"id":4506,"title":4507,"titles":4508,"content":104,"level":119},"/v1.0.1/reference/events#signal-categories","Signal Categories",[1813],{"id":4510,"title":4511,"titles":4512,"content":4513,"level":150},"/v1.0.1/reference/events#factory-lifecycle","Factory Lifecycle",[1813,4507],"SignalDescriptionFactoryCreatedFactory instantiatedProcessorRegisteredProcessor added to factoryPredicateRegisteredPredicate added to factoryConditionRegisteredCondition added to factoryProcessorRemovedProcessor removed from factoryPredicateRemovedPredicate removed from factoryConditionRemovedCondition removed from factory",{"id":4515,"title":2104,"titles":4516,"content":4517,"level":150},"/v1.0.1/reference/events#schema-validation",[1813,4507],"SignalDescriptionSchemaValidationStartedValidation beganSchemaValidationCompletedValidation successfulSchemaValidationFailedValidation found errors",{"id":4519,"title":4520,"titles":4521,"content":4522,"level":150},"/v1.0.1/reference/events#schema-building","Schema Building",[1813,4507],"SignalDescriptionSchemaBuildStartedBuild beganSchemaBuildCompletedBuild successfulSchemaBuildFailedBuild failed",{"id":4524,"title":3093,"titles":4525,"content":4526,"level":150},"/v1.0.1/reference/events#dynamic-schema-management",[1813,4507],"SignalDescriptionSchemaRegisteredNew schema added via SetSchemaSchemaUpdatedExisting schema replacedSchemaRemovedSchema removedPipelineRetrievedPipeline accessed via Pipeline()",{"id":4528,"title":4529,"titles":4530,"content":4531,"level":150},"/v1.0.1/reference/events#file-operations","File Operations",[1813,4507],"SignalDescriptionSchemaFileLoadedFile read successfullySchemaFileFailedFile read failedSchemaYAMLParsedYAML parsed successfullySchemaJSONParsedJSON parsed successfullySchemaParseFailedParse failed",{"id":4533,"title":4534,"titles":4535,"content":104,"level":119},"/v1.0.1/reference/events#field-keys","Field Keys",[1813],{"id":4537,"title":4538,"titles":4539,"content":4540,"level":150},"/v1.0.1/reference/events#string-fields","String Fields",[1813,4534],"KeyTypeDescriptionKeyNamestringComponent or schema nameKeyTypestringData type (e.g., *main.Order)KeyVersionstringSchema versionKeyOldVersionstringPrevious version (on update)KeyNewVersionstringNew version (on update)KeyPathstringFile pathKeyErrorstringError message",{"id":4542,"title":4543,"titles":4544,"content":4545,"level":150},"/v1.0.1/reference/events#duration-fields","Duration Fields",[1813,4534],"KeyTypeDescriptionKeyDurationtime.DurationOperation duration",{"id":4547,"title":4548,"titles":4549,"content":4550,"level":150},"/v1.0.1/reference/events#integer-fields","Integer Fields",[1813,4534],"KeyTypeDescriptionKeyErrorCountintNumber of validation errorsKeySizeBytesintFile size in bytes",{"id":4552,"title":4553,"titles":4554,"content":4555,"level":150},"/v1.0.1/reference/events#boolean-fields","Boolean Fields",[1813,4534],"KeyTypeDescriptionKeyFoundboolWhether pipeline was found",{"id":4557,"title":4558,"titles":4559,"content":104,"level":119},"/v1.0.1/reference/events#event-details","Event Details",[1813],{"id":4561,"title":4562,"titles":4563,"content":4564,"level":150},"/v1.0.1/reference/events#factorycreated","FactoryCreated",[1813,4558],"Emitted when flume.New[T]() is called. Fields: KeyType: The type parameter T Example: capitan.Handle(flume.FactoryCreated, func(ctx context.Context, fields []capitan.Field) {\n    dataType := extractString(fields, \"type\")\n    log.Printf(\"Factory created for type: %s\", dataType)\n})",{"id":4566,"title":4567,"titles":4568,"content":4569,"level":150},"/v1.0.1/reference/events#processorregistered","ProcessorRegistered",[1813,4558],"Emitted when a processor is added. Fields: KeyName: Processor name",{"id":4571,"title":4572,"titles":4573,"content":4574,"level":150},"/v1.0.1/reference/events#schemavalidationstarted","SchemaValidationStarted",[1813,4558],"Emitted at the start of validation. Fields: None",{"id":4576,"title":4577,"titles":4578,"content":4579,"level":150},"/v1.0.1/reference/events#schemavalidationcompleted","SchemaValidationCompleted",[1813,4558],"Emitted on successful validation. Fields: KeyDuration: Validation duration",{"id":4581,"title":4582,"titles":4583,"content":4584,"level":150},"/v1.0.1/reference/events#schemavalidationfailed","SchemaValidationFailed",[1813,4558],"Emitted when validation finds errors. Fields: KeyErrorCount: Number of errorsKeyDuration: Validation duration Example: capitan.Handle(flume.SchemaValidationFailed, func(ctx context.Context, fields []capitan.Field) {\n    count := extractInt(fields, \"error_count\")\n    duration := extractDuration(fields, \"duration\")\n    log.Printf(\"Validation failed with %d errors in %v\", count, duration)\n})",{"id":4586,"title":4587,"titles":4588,"content":4589,"level":150},"/v1.0.1/reference/events#schemabuildstarted","SchemaBuildStarted",[1813,4558],"Emitted at the start of building. Fields: KeyVersion: Schema version (if present)",{"id":4591,"title":4592,"titles":4593,"content":4594,"level":150},"/v1.0.1/reference/events#schemabuildcompleted","SchemaBuildCompleted",[1813,4558],"Emitted on successful build. Fields: KeyDuration: Build durationKeyVersion: Schema version (if present)",{"id":4596,"title":4597,"titles":4598,"content":4599,"level":150},"/v1.0.1/reference/events#schemabuildfailed","SchemaBuildFailed",[1813,4558],"Emitted when build fails. Fields: KeyError: Error messageKeyDuration: Duration until failureKeyVersion: Schema version (if present)",{"id":4601,"title":4602,"titles":4603,"content":4604,"level":150},"/v1.0.1/reference/events#schemaregistered","SchemaRegistered",[1813,4558],"Emitted when a new schema is added. Fields: KeyName: Schema nameKeyVersion: Schema version (if present)",{"id":4606,"title":4607,"titles":4608,"content":4609,"level":150},"/v1.0.1/reference/events#schemaupdated","SchemaUpdated",[1813,4558],"Emitted when an existing schema is replaced. Fields: KeyName: Schema nameKeyOldVersion: Previous version (if present)KeyNewVersion: New version (if present) Example: capitan.Handle(flume.SchemaUpdated, func(ctx context.Context, fields []capitan.Field) {\n    name := extractString(fields, \"name\")\n    oldV := extractString(fields, \"old_version\")\n    newV := extractString(fields, \"new_version\")\n    log.Printf(\"Schema %s: %s -> %s\", name, oldV, newV)\n})",{"id":4611,"title":4612,"titles":4613,"content":4614,"level":150},"/v1.0.1/reference/events#pipelineretrieved","PipelineRetrieved",[1813,4558],"Emitted when Pipeline() is called. Fields: KeyName: Schema name requestedKeyFound: Whether pipeline exists Example: capitan.Handle(flume.PipelineRetrieved, func(ctx context.Context, fields []capitan.Field) {\n    name := extractString(fields, \"name\")\n    found := extractBool(fields, \"found\")\n    if !found {\n        log.Printf(\"Pipeline not found: %s\", name)\n    }\n})",{"id":4616,"title":4617,"titles":4618,"content":4619,"level":150},"/v1.0.1/reference/events#schemafileloaded","SchemaFileLoaded",[1813,4558],"Emitted when a file is read. Fields: KeyPath: File pathKeySizeBytes: File size",{"id":4621,"title":4622,"titles":4623,"content":4624,"level":150},"/v1.0.1/reference/events#schemaparsefailed","SchemaParseFailed",[1813,4558],"Emitted when parsing fails. Fields: KeyPath: File path (if from file)KeyError: Parse error message",{"id":4626,"title":4627,"titles":4628,"content":104,"level":119},"/v1.0.1/reference/events#handler-patterns","Handler Patterns",[1813],{"id":4630,"title":4631,"titles":4632,"content":4633,"level":150},"/v1.0.1/reference/events#complete-logging-handler","Complete Logging Handler",[1813,4627],"func setupLogging() {\n    signals := map[capitan.Signal]string{\n        flume.FactoryCreated:            \"Factory created\",\n        flume.ProcessorRegistered:       \"Processor registered\",\n        flume.SchemaValidationStarted:   \"Validation started\",\n        flume.SchemaValidationCompleted: \"Validation completed\",\n        flume.SchemaValidationFailed:    \"Validation failed\",\n        flume.SchemaBuildStarted:        \"Build started\",\n        flume.SchemaBuildCompleted:      \"Build completed\",\n        flume.SchemaBuildFailed:         \"Build failed\",\n        flume.SchemaRegistered:          \"Schema registered\",\n        flume.SchemaUpdated:             \"Schema updated\",\n        flume.SchemaRemoved:             \"Schema removed\",\n        flume.PipelineRetrieved:         \"Pipeline retrieved\",\n    }\n\n    for signal, message := range signals {\n        s, m := signal, message\n        capitan.Handle(s, func(ctx context.Context, fields []capitan.Field) {\n            log.Printf(\"[FLUME] %s: %v\", m, formatFields(fields))\n        })\n    }\n}\n\nfunc formatFields(fields []capitan.Field) string {\n    parts := make([]string, 0, len(fields))\n    for _, f := range fields {\n        parts = append(parts, fmt.Sprintf(\"%s=%v\", f.Key, f.Value()))\n    }\n    return strings.Join(parts, \", \")\n}",{"id":4635,"title":4636,"titles":4637,"content":4638,"level":150},"/v1.0.1/reference/events#metrics-handler","Metrics Handler",[1813,4627],"func setupMetrics() {\n    // Build latency histogram\n    capitan.Handle(flume.SchemaBuildCompleted, func(ctx context.Context, fields []capitan.Field) {\n        for _, f := range fields {\n            if f.Key == \"duration\" {\n                metrics.RecordBuildLatency(f.Duration())\n            }\n        }\n    })\n\n    // Error counter\n    capitan.Handle(flume.SchemaBuildFailed, func(ctx context.Context, fields []capitan.Field) {\n        metrics.IncrBuildErrors()\n    })\n\n    capitan.Handle(flume.SchemaValidationFailed, func(ctx context.Context, fields []capitan.Field) {\n        metrics.IncrValidationErrors()\n    })\n}",{"id":4640,"title":4641,"titles":4642,"content":4643,"level":150},"/v1.0.1/reference/events#alerting-handler","Alerting Handler",[1813,4627],"func setupAlerting() {\n    capitan.Handle(flume.SchemaBuildFailed, func(ctx context.Context, fields []capitan.Field) {\n        errMsg := extractString(fields, \"error\")\n        alerting.Send(alerting.Error, fmt.Sprintf(\"Flume build failed: %s\", errMsg))\n    })\n\n    capitan.Handle(flume.SchemaUpdated, func(ctx context.Context, fields []capitan.Field) {\n        name := extractString(fields, \"name\")\n        oldV := extractString(fields, \"old_version\")\n        newV := extractString(fields, \"new_version\")\n\n        // Alert on major version changes\n        if isMajorChange(oldV, newV) {\n            alerting.Send(alerting.Warning,\n                fmt.Sprintf(\"Major version change: %s %s->%s\", name, oldV, newV))\n        }\n    })\n}",{"id":4645,"title":4646,"titles":4647,"content":4648,"level":119},"/v1.0.1/reference/events#helper-functions","Helper Functions",[1813],"func extractString(fields []capitan.Field, key string) string {\n    for _, f := range fields {\n        if f.Key == key {\n            return f.String()\n        }\n    }\n    return \"\"\n}\n\nfunc extractInt(fields []capitan.Field, key string) int {\n    for _, f := range fields {\n        if f.Key == key {\n            return f.Int()\n        }\n    }\n    return 0\n}\n\nfunc extractBool(fields []capitan.Field, key string) bool {\n    for _, f := range fields {\n        if f.Key == key {\n            return f.Bool()\n        }\n    }\n    return false\n}\n\nfunc extractDuration(fields []capitan.Field, key string) time.Duration {\n    for _, f := range fields {\n        if f.Key == key {\n            return f.Duration()\n        }\n    }\n    return 0\n}",{"id":4650,"title":3031,"titles":4651,"content":4652,"level":119},"/v1.0.1/reference/events#next-steps",[1813],"Observability Guide - Monitoring patternsCapitan Documentation - Event system html pre.shiki code .sh8_p, html code.shiki .sh8_p{--shiki-default:var(--shiki-text)}html pre.shiki code .sq5bi, html code.shiki .sq5bi{--shiki-default:var(--shiki-punctuation)}html pre.shiki code .s5klm, html code.shiki .s5klm{--shiki-default:var(--shiki-function)}html pre.shiki code .sUt3r, html code.shiki .sUt3r{--shiki-default:var(--shiki-keyword)}html pre.shiki code .sSYET, html code.shiki .sSYET{--shiki-default:var(--shiki-parameter)}html pre.shiki code .sYBwO, html code.shiki .sYBwO{--shiki-default:var(--shiki-type)}html pre.shiki code .sxAnc, html code.shiki .sxAnc{--shiki-default:var(--shiki-string)}html pre.shiki code .scyPU, html code.shiki .scyPU{--shiki-default:var(--shiki-placeholder)}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 .sW3Qg, html code.shiki .sW3Qg{--shiki-default:var(--shiki-operator)}html pre.shiki code .sBGCq, html code.shiki .sBGCq{--shiki-default:var(--shiki-property)}html pre.shiki code .skxcq, html code.shiki .skxcq{--shiki-default:var(--shiki-builtin)}html pre.shiki code .sMAmT, html code.shiki .sMAmT{--shiki-default:var(--shiki-number)}html pre.shiki code .sLkEo, html code.shiki .sLkEo{--shiki-default:var(--shiki-comment)}",[4654],{"title":4655,"path":4656,"stem":4657,"children":4658,"page":4673},"V101","/v1.0.1","v1.0.1",[4659,4661,4674,4688,4694],{"title":2900,"path":2899,"stem":4660,"description":2902},"v1.0.1/1.overview",{"title":1708,"path":4662,"stem":4663,"children":4664,"page":4673},"/v1.0.1/learn","v1.0.1/2.learn",[4665,4667,4669,4671],{"title":1716,"path":2963,"stem":4666,"description":2965},"v1.0.1/2.learn/1.quickstart",{"title":1723,"path":3035,"stem":4668,"description":3037},"v1.0.1/2.learn/2.core-concepts",{"title":1730,"path":3124,"stem":4670,"description":3126},"v1.0.1/2.learn/3.architecture",{"title":1737,"path":3207,"stem":4672,"description":3209},"v1.0.1/2.learn/4.building-pipelines",false,{"title":1742,"path":4675,"stem":4676,"children":4677,"page":4673},"/v1.0.1/guides","v1.0.1/3.guides",[4678,4680,4682,4684,4686],{"title":1331,"path":3318,"stem":4679,"description":3320},"v1.0.1/3.guides/1.schema-design",{"title":1295,"path":3458,"stem":4681,"description":3460},"v1.0.1/3.guides/2.hot-reloading",{"title":1760,"path":3586,"stem":4683,"description":3588},"v1.0.1/3.guides/3.error-handling",{"title":1767,"path":3752,"stem":4685,"description":3754},"v1.0.1/3.guides/4.testing",{"title":1359,"path":3847,"stem":4687,"description":3849},"v1.0.1/3.guides/5.observability",{"title":1777,"path":4689,"stem":4690,"children":4691,"page":4673},"/v1.0.1/cookbook","v1.0.1/4.cookbook",[4692],{"title":1785,"path":3968,"stem":4693,"description":3970},"v1.0.1/4.cookbook/1.common-patterns",{"title":1790,"path":4695,"stem":4696,"children":4697,"page":4673},"/v1.0.1/reference","v1.0.1/5.reference",[4698,4700,4702,4704],{"title":1317,"path":4011,"stem":4699,"description":4013},"v1.0.1/5.reference/1.api",{"title":1290,"path":4274,"stem":4701,"description":4276},"v1.0.1/5.reference/2.schema-format",{"title":1345,"path":4402,"stem":4703,"description":4404},"v1.0.1/5.reference/3.connector-types",{"title":1813,"path":4498,"stem":4705,"description":4500},"v1.0.1/5.reference/4.events",[4707],{"title":4655,"path":4656,"stem":4657,"children":4708,"page":4673},[4709,4710,4716,4723,4726],{"title":2900,"path":2899,"stem":4660},{"title":1708,"path":4662,"stem":4663,"children":4711,"page":4673},[4712,4713,4714,4715],{"title":1716,"path":2963,"stem":4666},{"title":1723,"path":3035,"stem":4668},{"title":1730,"path":3124,"stem":4670},{"title":1737,"path":3207,"stem":4672},{"title":1742,"path":4675,"stem":4676,"children":4717,"page":4673},[4718,4719,4720,4721,4722],{"title":1331,"path":3318,"stem":4679},{"title":1295,"path":3458,"stem":4681},{"title":1760,"path":3586,"stem":4683},{"title":1767,"path":3752,"stem":4685},{"title":1359,"path":3847,"stem":4687},{"title":1777,"path":4689,"stem":4690,"children":4724,"page":4673},[4725],{"title":1785,"path":3968,"stem":4693},{"title":1790,"path":4695,"stem":4696,"children":4727,"page":4673},[4728,4729,4730,4731],{"title":1317,"path":4011,"stem":4699},{"title":1290,"path":4274,"stem":4701},{"title":1345,"path":4402,"stem":4703},{"title":1813,"path":4498,"stem":4705},[4733],{"title":4655,"path":4656,"stem":4657,"children":4734,"page":4673},[4735,4736,4742,4749,4752],{"title":2900,"path":2899,"stem":4660,"description":2902},{"title":1708,"path":4662,"stem":4663,"children":4737,"page":4673},[4738,4739,4740,4741],{"title":1716,"path":2963,"stem":4666,"description":2965},{"title":1723,"path":3035,"stem":4668,"description":3037},{"title":1730,"path":3124,"stem":4670,"description":3126},{"title":1737,"path":3207,"stem":4672,"description":3209},{"title":1742,"path":4675,"stem":4676,"children":4743,"page":4673},[4744,4745,4746,4747,4748],{"title":1331,"path":3318,"stem":4679,"description":3320},{"title":1295,"path":3458,"stem":4681,"description":3460},{"title":1760,"path":3586,"stem":4683,"description":3588},{"title":1767,"path":3752,"stem":4685,"description":3754},{"title":1359,"path":3847,"stem":4687,"description":3849},{"title":1777,"path":4689,"stem":4690,"children":4750,"page":4673},[4751],{"title":1785,"path":3968,"stem":4693,"description":3970},{"title":1790,"path":4695,"stem":4696,"children":4753,"page":4673},[4754,4755,4756,4757],{"title":1317,"path":4011,"stem":4699,"description":4013},{"title":1290,"path":4274,"stem":4701,"description":4276},{"title":1345,"path":4402,"stem":4703,"description":4404},{"title":1813,"path":4498,"stem":4705,"description":4500},1776189694340]