[{"data":1,"prerenderedAt":7787},["ShallowReactive",2],{"search-sections-flume":3,"nav-flume":1798,"content-tree-flume":1852,"footer-resources":1878,"content-/v1.0.1/guides/observability":4731,"surround-/v1.0.1/guides/observability":7784},[4,10,14,20,25,31,36,41,45,50,55,60,64,69,74,79,84,88,93,98,103,108,113,118,123,128,133,138,143,148,153,158,162,167,172,177,182,187,192,197,202,207,212,217,222,226,231,236,241,245,249,253,257,262,267,271,276,281,286,291,296,301,306,310,315,320,325,329,333,337,342,347,351,356,361,365,370,375,380,385,390,394,399,404,409,413,417,422,427,432,437,441,446,450,454,459,464,469,474,478,483,488,493,497,502,507,511,516,521,526,530,535,540,545,549,554,559,563,568,573,578,582,586,590,594,598,603,608,613,617,622,627,631,636,641,645,650,655,659,664,669,673,678,683,687,692,697,702,707,711,715,719,723,728,733,738,743,747,752,757,761,765,770,774,779,783,787,792,796,800,804,808,813,817,821,825,830,835,840,845,848,853,858,863,868,873,877,882,886,891,896,901,906,911,916,921,926,931,935,940,945,950,955,960,965,969,973,977,981,985,989,994,999,1004,1009,1014,1018,1023,1028,1033,1037,1042,1047,1052,1056,1061,1066,1070,1075,1080,1085,1090,1094,1099,1103,1108,1113,1118,1123,1128,1133,1138,1143,1147,1151,1156,1160,1165,1170,1175,1180,1185,1189,1194,1199,1204,1209,1213,1218,1223,1228,1233,1237,1242,1247,1252,1257,1262,1265,1270,1275,1280,1285,1289,1294,1299,1304,1309,1314,1319,1324,1329,1334,1339,1342,1347,1352,1356,1361,1366,1371,1376,1381,1386,1391,1396,1401,1405,1410,1414,1419,1423,1427,1431,1436,1441,1445,1450,1455,1460,1465,1470,1475,1480,1485,1490,1495,1500,1505,1510,1515,1520,1525,1530,1535,1540,1544,1548,1552,1556,1560,1564,1568,1571,1575,1579,1583,1587,1591,1595,1599,1603,1607,1611,1615,1619,1623,1627,1631,1636,1640,1645,1649,1653,1658,1663,1668,1672,1677,1681,1686,1691,1696,1701,1705,1710,1715,1720,1725,1730,1735,1740,1745,1750,1755,1760,1765,1770,1774,1779,1784,1789,1794],{"id":5,"title":6,"titles":7,"content":8,"level":9},"/v1.0.1/overview","Overview",[],"Schema-driven pipeline factory for pipz with hot-reloading capabilities",1,{"id":11,"title":6,"titles":12,"content":13,"level":9},"/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":15,"title":16,"titles":17,"content":18,"level":19},"/v1.0.1/overview#architecture","Architecture",[6],"┌──────────────────────────────────────────────────────────────┐\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.",2,{"id":21,"title":22,"titles":23,"content":24,"level":19},"/v1.0.1/overview#philosophy","Philosophy",[6],"",{"id":26,"title":27,"titles":28,"content":29,"level":30},"/v1.0.1/overview#configuration-over-code","Configuration Over Code",[6,22],"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}))",3,{"id":32,"title":33,"titles":34,"content":35,"level":30},"/v1.0.1/overview#zero-magic","Zero Magic",[6,22],"Processors name themselves via pipz.NameSchemas are plain YAML/JSONValidation errors include full pathsNo reflection at runtime",{"id":37,"title":38,"titles":39,"content":40,"level":19},"/v1.0.1/overview#capabilities","Capabilities",[6],"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":42,"title":43,"titles":44,"content":24,"level":19},"/v1.0.1/overview#priorities","Priorities",[6],{"id":46,"title":47,"titles":48,"content":49,"level":30},"/v1.0.1/overview#type-safety","Type Safety",[6,43],"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":51,"title":52,"titles":53,"content":54,"level":30},"/v1.0.1/overview#validation","Validation",[6,43],"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":56,"title":57,"titles":58,"content":59,"level":30},"/v1.0.1/overview#performance","Performance",[6,43],"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":61,"title":62,"titles":63,"content":24,"level":19},"/v1.0.1/overview#documentation","Documentation",[6],{"id":65,"title":66,"titles":67,"content":68,"level":30},"/v1.0.1/overview#learn","Learn",[6,62],"Quickstart - Your first pipeline in 5 minutesCore Concepts - Factories, schemas, and componentsArchitecture - How Flume works under the hoodBuilding Pipelines - From simple to complex",{"id":70,"title":71,"titles":72,"content":73,"level":30},"/v1.0.1/overview#guides","Guides",[6,62],"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":75,"title":76,"titles":77,"content":78,"level":30},"/v1.0.1/overview#reference","Reference",[6,62],"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":80,"title":81,"titles":82,"content":83,"level":9},"/v1.0.1/learn/quickstart","Quickstart",[],"Build your first Flume pipeline in 5 minutes",{"id":85,"title":81,"titles":86,"content":87,"level":9},"/v1.0.1/learn/quickstart#quickstart",[],"Build your first schema-driven pipeline in 5 minutes.",{"id":89,"title":90,"titles":91,"content":92,"level":19},"/v1.0.1/learn/quickstart#installation","Installation",[81],"go get github.com/zoobz-io/flume",{"id":94,"title":95,"titles":96,"content":97,"level":19},"/v1.0.1/learn/quickstart#step-1-define-your-data-type","Step 1: Define Your Data Type",[81],"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":99,"title":100,"titles":101,"content":102,"level":19},"/v1.0.1/learn/quickstart#step-2-create-a-factory","Step 2: Create a Factory",[81],"func main() {\n    factory := flume.New[Order]()\n}",{"id":104,"title":105,"titles":106,"content":107,"level":19},"/v1.0.1/learn/quickstart#step-3-register-processors","Step 3: Register Processors",[81],"// 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":109,"title":110,"titles":111,"content":112,"level":19},"/v1.0.1/learn/quickstart#step-4-define-schema","Step 4: Define Schema",[81],"schema := `\ntype: sequence\nchildren:\n  - ref: validate\n  - ref: enrich\n  - ref: log\n`",{"id":114,"title":115,"titles":116,"content":117,"level":19},"/v1.0.1/learn/quickstart#step-5-build-and-use","Step 5: Build and Use",[81],"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":119,"title":120,"titles":121,"content":122,"level":19},"/v1.0.1/learn/quickstart#complete-example","Complete Example",[81],"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":124,"title":125,"titles":126,"content":127,"level":19},"/v1.0.1/learn/quickstart#adding-conditional-logic","Adding Conditional Logic",[81],"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":129,"title":130,"titles":131,"content":132,"level":19},"/v1.0.1/learn/quickstart#adding-error-handling","Adding Error Handling",[81],"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":134,"title":135,"titles":136,"content":137,"level":19},"/v1.0.1/learn/quickstart#merging-concurrent-results","Merging Concurrent Results",[81],"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":139,"title":140,"titles":141,"content":142,"level":19},"/v1.0.1/learn/quickstart#loading-from-files","Loading from Files",[81],"pipeline, err := factory.BuildFromFile(\"pipeline.yaml\")",{"id":144,"title":145,"titles":146,"content":147,"level":19},"/v1.0.1/learn/quickstart#using-named-schemas","Using Named Schemas",[81],"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":149,"title":150,"titles":151,"content":152,"level":19},"/v1.0.1/learn/quickstart#next-steps","Next Steps",[81],"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":154,"title":155,"titles":156,"content":157,"level":9},"/v1.0.1/learn/core-concepts","Core Concepts",[],"Understanding Flume's fundamental building blocks - factories, schemas, and components",{"id":159,"title":155,"titles":160,"content":161,"level":9},"/v1.0.1/learn/core-concepts#core-concepts",[],"Flume is built around three core concepts: the Factory, Schemas, and Components.",{"id":163,"title":164,"titles":165,"content":166,"level":19},"/v1.0.1/learn/core-concepts#the-factory","The Factory",[155],"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":168,"title":169,"titles":170,"content":171,"level":30},"/v1.0.1/learn/core-concepts#factory-responsibilities","Factory Responsibilities",[155,164],"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":173,"title":174,"titles":175,"content":176,"level":19},"/v1.0.1/learn/core-concepts#components","Components",[155],"Components are the building blocks registered with the factory. There are three types:",{"id":178,"title":179,"titles":180,"content":181,"level":30},"/v1.0.1/learn/core-concepts#processors","Processors",[155,174],"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":183,"title":184,"titles":185,"content":186,"level":30},"/v1.0.1/learn/core-concepts#predicates","Predicates",[155,174],"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":188,"title":189,"titles":190,"content":191,"level":30},"/v1.0.1/learn/core-concepts#conditions","Conditions",[155,174],"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":193,"title":194,"titles":195,"content":196,"level":19},"/v1.0.1/learn/core-concepts#schemas","Schemas",[155],"Schemas define pipeline structure as YAML or JSON documents.",{"id":198,"title":199,"titles":200,"content":201,"level":30},"/v1.0.1/learn/core-concepts#schema-structure","Schema Structure",[155,194],"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":203,"title":204,"titles":205,"content":206,"level":30},"/v1.0.1/learn/core-concepts#node-types","Node Types",[155,194],"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":208,"title":209,"titles":210,"content":211,"level":30},"/v1.0.1/learn/core-concepts#building-pipelines","Building Pipelines",[155,194],"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":213,"title":214,"titles":215,"content":216,"level":19},"/v1.0.1/learn/core-concepts#dynamic-schema-management","Dynamic Schema Management",[155],"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":218,"title":219,"titles":220,"content":221,"level":30},"/v1.0.1/learn/core-concepts#hot-reloading","Hot Reloading",[155,214],"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":223,"title":52,"titles":224,"content":225,"level":19},"/v1.0.1/learn/core-concepts#validation",[155],"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":227,"title":228,"titles":229,"content":230,"level":30},"/v1.0.1/learn/core-concepts#what-gets-validated","What Gets Validated",[155,52],"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":232,"title":233,"titles":234,"content":235,"level":19},"/v1.0.1/learn/core-concepts#component-introspection","Component Introspection",[155],"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":237,"title":238,"titles":239,"content":240,"level":19},"/v1.0.1/learn/core-concepts#component-removal","Component Removal",[155],"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":242,"title":150,"titles":243,"content":244,"level":19},"/v1.0.1/learn/core-concepts#next-steps",[155],"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":246,"title":16,"titles":247,"content":248,"level":9},"/v1.0.1/learn/architecture",[],"How Flume works under the hood - from schema to pipeline",{"id":250,"title":16,"titles":251,"content":252,"level":9},"/v1.0.1/learn/architecture#architecture",[],"Understanding Flume's internal architecture helps you use it effectively and debug issues.",{"id":254,"title":6,"titles":255,"content":256,"level":19},"/v1.0.1/learn/architecture#overview",[16],"┌─────────────────────────────────────────────────────────────┐\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":258,"title":259,"titles":260,"content":261,"level":19},"/v1.0.1/learn/architecture#factory-structure","Factory Structure",[16],"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":263,"title":264,"titles":265,"content":266,"level":30},"/v1.0.1/learn/architecture#thread-safety","Thread Safety",[16,259],"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":268,"title":269,"titles":270,"content":24,"level":19},"/v1.0.1/learn/architecture#schema-processing-pipeline","Schema Processing Pipeline",[16],{"id":272,"title":273,"titles":274,"content":275,"level":30},"/v1.0.1/learn/architecture#_1-parsing","1. Parsing",[16,269],"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":277,"title":278,"titles":279,"content":280,"level":30},"/v1.0.1/learn/architecture#_2-validation","2. Validation",[16,269],"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":282,"title":283,"titles":284,"content":285,"level":30},"/v1.0.1/learn/architecture#_3-building","3. Building",[16,269],"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":287,"title":288,"titles":289,"content":290,"level":19},"/v1.0.1/learn/architecture#connector-mapping","Connector Mapping",[16],"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":292,"title":293,"titles":294,"content":295,"level":19},"/v1.0.1/learn/architecture#hot-reload-mechanism","Hot Reload Mechanism",[16],"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":297,"title":298,"titles":299,"content":300,"level":19},"/v1.0.1/learn/architecture#observability-integration","Observability Integration",[16],"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":302,"title":303,"titles":304,"content":305,"level":19},"/v1.0.1/learn/architecture#channel-integration","Channel Integration",[16],"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":307,"title":308,"titles":309,"content":24,"level":19},"/v1.0.1/learn/architecture#memory-model","Memory Model",[16],{"id":311,"title":312,"titles":313,"content":314,"level":30},"/v1.0.1/learn/architecture#component-storage","Component Storage",[16,308],"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":316,"title":317,"titles":318,"content":319,"level":30},"/v1.0.1/learn/architecture#pipeline-lifecycle","Pipeline Lifecycle",[16,308],"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":321,"title":322,"titles":323,"content":324,"level":30},"/v1.0.1/learn/architecture#concurrency","Concurrency",[16,308],"Multiple goroutines can safely call Pipeline() concurrentlyBuild operations are serialized through the write lockBuilt pipelines are independent of the factory",{"id":326,"title":150,"titles":327,"content":328,"level":19},"/v1.0.1/learn/architecture#next-steps",[16],"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":330,"title":209,"titles":331,"content":332,"level":9},"/v1.0.1/learn/building-pipelines",[],"From simple sequences to complex nested pipelines",{"id":334,"title":209,"titles":335,"content":336,"level":9},"/v1.0.1/learn/building-pipelines#building-pipelines",[],"Learn to construct increasingly sophisticated pipelines with Flume schemas.",{"id":338,"title":339,"titles":340,"content":341,"level":19},"/v1.0.1/learn/building-pipelines#simple-sequences","Simple Sequences",[209],"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":343,"title":344,"titles":345,"content":346,"level":19},"/v1.0.1/learn/building-pipelines#parallel-execution","Parallel Execution",[209],"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":348,"title":349,"titles":350,"content":24,"level":19},"/v1.0.1/learn/building-pipelines#conditional-processing","Conditional Processing",[209],{"id":352,"title":353,"titles":354,"content":355,"level":30},"/v1.0.1/learn/building-pipelines#filter","Filter",[209,349],"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":357,"title":358,"titles":359,"content":360,"level":30},"/v1.0.1/learn/building-pipelines#switch","Switch",[209,349],"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":362,"title":363,"titles":364,"content":24,"level":19},"/v1.0.1/learn/building-pipelines#error-handling","Error Handling",[209],{"id":366,"title":367,"titles":368,"content":369,"level":30},"/v1.0.1/learn/building-pipelines#retry","Retry",[209,363],"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":371,"title":372,"titles":373,"content":374,"level":30},"/v1.0.1/learn/building-pipelines#fallback","Fallback",[209,363],"Use a backup handler on failure: type: fallback\nchildren:\n  - ref: primary-service\n  - ref: backup-service",{"id":376,"title":377,"titles":378,"content":379,"level":30},"/v1.0.1/learn/building-pipelines#timeout","Timeout",[209,363],"Enforce time limits: type: timeout\nduration: \"5s\"\nchild:\n  ref: slow-operation",{"id":381,"title":382,"titles":383,"content":384,"level":30},"/v1.0.1/learn/building-pipelines#circuit-breaker","Circuit Breaker",[209,363],"Prevent cascading failures: type: circuit-breaker\nfailure_threshold: 5\nrecovery_timeout: \"30s\"\nchild:\n  ref: unreliable-service",{"id":386,"title":387,"titles":388,"content":389,"level":30},"/v1.0.1/learn/building-pipelines#rate-limiting","Rate Limiting",[209,363],"Control throughput: type: rate-limit\nrequests_per_second: 100.0\nburst_size: 10\nchild:\n  ref: rate-sensitive-api",{"id":391,"title":392,"titles":393,"content":24,"level":19},"/v1.0.1/learn/building-pipelines#nesting-patterns","Nesting Patterns",[209],{"id":395,"title":396,"titles":397,"content":398,"level":30},"/v1.0.1/learn/building-pipelines#resilient-external-calls","Resilient External Calls",[209,392],"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":400,"title":401,"titles":402,"content":403,"level":30},"/v1.0.1/learn/building-pipelines#conditional-with-fallback","Conditional with Fallback",[209,392],"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":405,"title":406,"titles":407,"content":408,"level":30},"/v1.0.1/learn/building-pipelines#parallel-with-error-handling","Parallel with Error Handling",[209,392],"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":410,"title":120,"titles":411,"content":412,"level":19},"/v1.0.1/learn/building-pipelines#complete-example",[209],"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":414,"title":415,"titles":416,"content":24,"level":19},"/v1.0.1/learn/building-pipelines#schema-design-tips","Schema Design Tips",[209],{"id":418,"title":419,"titles":420,"content":421,"level":30},"/v1.0.1/learn/building-pipelines#_1-name-complex-nodes","1. Name Complex Nodes",[209,415],"type: sequence\nname: payment-handling  # Helps with debugging\nchildren:\n  - ref: charge\n  - ref: confirm",{"id":423,"title":424,"titles":425,"content":426,"level":30},"/v1.0.1/learn/building-pipelines#_2-keep-depth-manageable","2. Keep Depth Manageable",[209,415],"Break deeply nested schemas into named sub-pipelines: // Register sub-pipeline\nfactory.SetSchema(\"payment-flow\", paymentSchema)",{"id":428,"title":429,"titles":430,"content":431,"level":30},"/v1.0.1/learn/building-pipelines#_3-version-your-schemas","3. Version Your Schemas",[209,415],"version: \"1.2.0\"\ntype: sequence\n# ...",{"id":433,"title":434,"titles":435,"content":436,"level":30},"/v1.0.1/learn/building-pipelines#_4-document-with-comments","4. Document with Comments",[209,415],"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":438,"title":150,"titles":439,"content":440,"level":19},"/v1.0.1/learn/building-pipelines#next-steps",[209],"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":442,"title":443,"titles":444,"content":445,"level":9},"/v1.0.1/guides/schema-design","Schema Design",[],"Best practices for designing maintainable Flume schemas",{"id":447,"title":443,"titles":448,"content":449,"level":9},"/v1.0.1/guides/schema-design#schema-design",[],"Best practices for designing clear, maintainable Flume schemas.",{"id":451,"title":452,"titles":453,"content":24,"level":19},"/v1.0.1/guides/schema-design#naming-conventions","Naming Conventions",[443],{"id":455,"title":456,"titles":457,"content":458,"level":30},"/v1.0.1/guides/schema-design#processor-names","Processor Names",[443,452],"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":460,"title":461,"titles":462,"content":463,"level":30},"/v1.0.1/guides/schema-design#predicate-names","Predicate Names",[443,452],"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":465,"title":466,"titles":467,"content":468,"level":30},"/v1.0.1/guides/schema-design#condition-names","Condition Names",[443,452],"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":470,"title":471,"titles":472,"content":473,"level":30},"/v1.0.1/guides/schema-design#schema-names","Schema Names",[443,452],"Use descriptive kebab-case: factory.SetSchema(\"order-processing\", ...)\nfactory.SetSchema(\"user-onboarding\", ...)\nfactory.SetSchema(\"payment-v2\", ...)",{"id":475,"title":476,"titles":477,"content":24,"level":19},"/v1.0.1/guides/schema-design#structure-guidelines","Structure Guidelines",[443],{"id":479,"title":480,"titles":481,"content":482,"level":30},"/v1.0.1/guides/schema-design#keep-depth-shallow","Keep Depth Shallow",[443,476],"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":484,"title":485,"titles":486,"content":487,"level":30},"/v1.0.1/guides/schema-design#group-related-operations","Group Related Operations",[443,476],"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":489,"title":490,"titles":491,"content":492,"level":30},"/v1.0.1/guides/schema-design#name-complex-nodes","Name Complex Nodes",[443,476],"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":494,"title":495,"titles":496,"content":24,"level":19},"/v1.0.1/guides/schema-design#version-management","Version Management",[443],{"id":498,"title":499,"titles":500,"content":501,"level":30},"/v1.0.1/guides/schema-design#semantic-versioning","Semantic Versioning",[443,495],"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":503,"title":504,"titles":505,"content":506,"level":30},"/v1.0.1/guides/schema-design#version-in-schema-name","Version in Schema Name",[443,495],"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":508,"title":509,"titles":510,"content":24,"level":19},"/v1.0.1/guides/schema-design#error-handling-placement","Error Handling Placement",[443],{"id":512,"title":513,"titles":514,"content":515,"level":30},"/v1.0.1/guides/schema-design#wrap-at-boundaries","Wrap at Boundaries",[443,509],"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":517,"title":518,"titles":519,"content":520,"level":30},"/v1.0.1/guides/schema-design#dont-over-protect","Don't Over-Protect",[443,509],"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":522,"title":523,"titles":524,"content":525,"level":30},"/v1.0.1/guides/schema-design#match-retry-to-operation","Match Retry to Operation",[443,509],"# 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":527,"title":528,"titles":529,"content":24,"level":19},"/v1.0.1/guides/schema-design#performance-considerations","Performance Considerations",[443],{"id":531,"title":532,"titles":533,"content":534,"level":30},"/v1.0.1/guides/schema-design#minimize-cloning","Minimize Cloning",[443,528],"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":536,"title":537,"titles":538,"content":539,"level":30},"/v1.0.1/guides/schema-design#rate-limit-at-entry-points","Rate Limit at Entry Points",[443,528],"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":541,"title":542,"titles":543,"content":544,"level":30},"/v1.0.1/guides/schema-design#use-timeouts-wisely","Use Timeouts Wisely",[443,528],"Set realistic timeouts: type: timeout\nduration: \"30s\"  # Based on actual SLA\nchild:\n  ref: external-service",{"id":546,"title":547,"titles":548,"content":24,"level":19},"/v1.0.1/guides/schema-design#schema-organization","Schema Organization",[443],{"id":550,"title":551,"titles":552,"content":553,"level":30},"/v1.0.1/guides/schema-design#single-responsibility","Single Responsibility",[443,547],"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":555,"title":556,"titles":557,"content":558,"level":30},"/v1.0.1/guides/schema-design#compose-larger-flows","Compose Larger Flows",[443,547],"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":560,"title":561,"titles":562,"content":24,"level":19},"/v1.0.1/guides/schema-design#documentation-practices","Documentation Practices",[443],{"id":564,"title":565,"titles":566,"content":567,"level":30},"/v1.0.1/guides/schema-design#use-descriptions","Use Descriptions",[443,561],"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":569,"title":570,"titles":571,"content":572,"level":30},"/v1.0.1/guides/schema-design#companion-documentation","Companion Documentation",[443,561],"Maintain schema documentation alongside files: schemas/\n  order-processing.yaml\n  order-processing.md    # Documents the schema",{"id":574,"title":575,"titles":576,"content":577,"level":30},"/v1.0.1/guides/schema-design#schema-diagrams","Schema Diagrams",[443,561],"For complex pipelines, create visual diagrams: validate → [concurrent: enrich] → [filter: premium?] → [switch: payment] → complete\n                                        ↓                    ↓\n                                  premium-handler     credit|paypal|crypto",{"id":579,"title":150,"titles":580,"content":581,"level":19},"/v1.0.1/guides/schema-design#next-steps",[443],"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":583,"title":219,"titles":584,"content":585,"level":9},"/v1.0.1/guides/hot-reloading",[],"Update pipeline behaviour at runtime without restarts",{"id":587,"title":219,"titles":588,"content":589,"level":9},"/v1.0.1/guides/hot-reloading#hot-reloading",[],"Update pipeline definitions at runtime without service restarts.",{"id":591,"title":6,"titles":592,"content":593,"level":19},"/v1.0.1/guides/hot-reloading#overview",[219],"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":595,"title":596,"titles":597,"content":24,"level":19},"/v1.0.1/guides/hot-reloading#basic-usage","Basic Usage",[219],{"id":599,"title":600,"titles":601,"content":602,"level":30},"/v1.0.1/guides/hot-reloading#register-named-schemas","Register Named Schemas",[219,596],"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":604,"title":605,"titles":606,"content":607,"level":30},"/v1.0.1/guides/hot-reloading#create-a-binding","Create a Binding",[219,596],"// 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":609,"title":610,"titles":611,"content":612,"level":30},"/v1.0.1/guides/hot-reloading#update-at-runtime","Update at Runtime",[219,596],"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":614,"title":615,"titles":616,"content":24,"level":19},"/v1.0.1/guides/hot-reloading#how-it-works","How It Works",[219],{"id":618,"title":619,"titles":620,"content":621,"level":30},"/v1.0.1/guides/hot-reloading#atomic-pointer-swap","Atomic Pointer Swap",[219,615],"// 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":623,"title":624,"titles":625,"content":626,"level":30},"/v1.0.1/guides/hot-reloading#request-continuity","Request Continuity",[219,615],"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":628,"title":629,"titles":630,"content":24,"level":19},"/v1.0.1/guides/hot-reloading#file-based-reloading","File-Based Reloading",[219],{"id":632,"title":633,"titles":634,"content":635,"level":30},"/v1.0.1/guides/hot-reloading#watch-for-changes","Watch for Changes",[219,629],"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":637,"title":638,"titles":639,"content":640,"level":30},"/v1.0.1/guides/hot-reloading#multi-schema-directory","Multi-Schema Directory",[219,629],"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":642,"title":643,"titles":644,"content":24,"level":19},"/v1.0.1/guides/hot-reloading#remote-configuration","Remote Configuration",[219],{"id":646,"title":647,"titles":648,"content":649,"level":30},"/v1.0.1/guides/hot-reloading#http-endpoint","HTTP Endpoint",[219,643],"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":651,"title":652,"titles":653,"content":654,"level":30},"/v1.0.1/guides/hot-reloading#polling","Polling",[219,643],"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":656,"title":657,"titles":658,"content":24,"level":19},"/v1.0.1/guides/hot-reloading#version-tracking","Version Tracking",[219],{"id":660,"title":661,"titles":662,"content":663,"level":30},"/v1.0.1/guides/hot-reloading#compare-versions","Compare Versions",[219,657],"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":665,"title":666,"titles":667,"content":668,"level":30},"/v1.0.1/guides/hot-reloading#observability","Observability",[219,657],"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":670,"title":671,"titles":672,"content":24,"level":19},"/v1.0.1/guides/hot-reloading#graceful-updates","Graceful Updates",[219],{"id":674,"title":675,"titles":676,"content":677,"level":30},"/v1.0.1/guides/hot-reloading#validation-first","Validation First",[219,671],"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":679,"title":680,"titles":681,"content":682,"level":30},"/v1.0.1/guides/hot-reloading#rollback-pattern","Rollback Pattern",[219,671],"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":684,"title":685,"titles":686,"content":24,"level":19},"/v1.0.1/guides/hot-reloading#best-practices","Best Practices",[219],{"id":688,"title":689,"titles":690,"content":691,"level":30},"/v1.0.1/guides/hot-reloading#_1-use-semantic-versioning","1. Use Semantic Versioning",[219,685],"version: \"1.2.3\"  # MAJOR.MINOR.PATCH",{"id":693,"title":694,"titles":695,"content":696,"level":30},"/v1.0.1/guides/hot-reloading#_2-log-all-changes","2. Log All Changes",[219,685],"log.Printf(\"schema %s updated to version %s\", name, schema.Version)",{"id":698,"title":699,"titles":700,"content":701,"level":30},"/v1.0.1/guides/hot-reloading#_3-validate-component-dependencies","3. Validate Component Dependencies",[219,685],"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":703,"title":704,"titles":705,"content":706,"level":30},"/v1.0.1/guides/hot-reloading#_4-consider-circuit-breakers","4. Consider Circuit Breakers",[219,685],"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":708,"title":150,"titles":709,"content":710,"level":19},"/v1.0.1/guides/hot-reloading#next-steps",[219],"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":712,"title":363,"titles":713,"content":714,"level":9},"/v1.0.1/guides/error-handling",[],"Build resilient pipelines with retry, fallback, circuit breakers, and timeouts",{"id":716,"title":363,"titles":717,"content":718,"level":9},"/v1.0.1/guides/error-handling#error-handling",[],"Build resilient pipelines that gracefully handle failures.",{"id":720,"title":367,"titles":721,"content":722,"level":19},"/v1.0.1/guides/error-handling#retry",[363],"Retry operations that may fail transiently.",{"id":724,"title":725,"titles":726,"content":727,"level":30},"/v1.0.1/guides/error-handling#basic-retry","Basic Retry",[363,367],"type: retry\nattempts: 3\nchild:\n  ref: flaky-operation Retries up to 3 times on any error.",{"id":729,"title":730,"titles":731,"content":732,"level":30},"/v1.0.1/guides/error-handling#retry-with-backoff","Retry with Backoff",[363,367],"type: retry\nattempts: 5\nbackoff: \"100ms\"\nchild:\n  ref: rate-limited-api Waits backoff duration between attempts, doubling each time (exponential backoff).",{"id":734,"title":735,"titles":736,"content":737,"level":30},"/v1.0.1/guides/error-handling#when-to-use","When to Use",[363,367],"Network calls that may timeoutRate-limited APIs that return temporary errorsDatabase operations during high loadMessage queue operations",{"id":739,"title":740,"titles":741,"content":742,"level":30},"/v1.0.1/guides/error-handling#configuration","Configuration",[363,367],"FieldDefaultDescriptionattempts3Maximum retry attemptsbackoff(none)Initial backoff duration",{"id":744,"title":372,"titles":745,"content":746,"level":19},"/v1.0.1/guides/error-handling#fallback",[363],"Provide alternative handling when primary fails.",{"id":748,"title":749,"titles":750,"content":751,"level":30},"/v1.0.1/guides/error-handling#basic-fallback","Basic Fallback",[363,372],"type: fallback\nchildren:\n  - ref: primary-service\n  - ref: backup-service Tries primary first; if it errors, tries backup.",{"id":753,"title":754,"titles":755,"content":756,"level":30},"/v1.0.1/guides/error-handling#cascading-fallbacks","Cascading Fallbacks",[363,372],"type: fallback\nchildren:\n  - ref: primary-cache\n  - type: fallback\n    children:\n      - ref: secondary-cache\n      - ref: database",{"id":758,"title":735,"titles":759,"content":760,"level":30},"/v1.0.1/guides/error-handling#when-to-use-1",[363,372],"Service redundancyCache miss handlingFeature degradationDefault value provision",{"id":762,"title":377,"titles":763,"content":764,"level":19},"/v1.0.1/guides/error-handling#timeout",[363],"Enforce time limits on operations.",{"id":766,"title":767,"titles":768,"content":769,"level":30},"/v1.0.1/guides/error-handling#basic-timeout","Basic Timeout",[363,377],"type: timeout\nduration: \"5s\"\nchild:\n  ref: slow-operation Cancels operation if not complete within duration.",{"id":771,"title":740,"titles":772,"content":773,"level":30},"/v1.0.1/guides/error-handling#configuration-1",[363,377],"FieldDefaultDescriptionduration30sMaximum execution time",{"id":775,"title":776,"titles":777,"content":778,"level":30},"/v1.0.1/guides/error-handling#duration-formats","Duration Formats",[363,377],"duration: \"100ms\"   # 100 milliseconds\nduration: \"5s\"      # 5 seconds\nduration: \"2m\"      # 2 minutes\nduration: \"1h30m\"   # 1.5 hours",{"id":780,"title":735,"titles":781,"content":782,"level":30},"/v1.0.1/guides/error-handling#when-to-use-2",[363,377],"External API callsLong-running computationsUser-facing requests requiring responsivenessPreventing resource exhaustion",{"id":784,"title":382,"titles":785,"content":786,"level":19},"/v1.0.1/guides/error-handling#circuit-breaker",[363],"Prevent cascading failures by stopping calls to failing services.",{"id":788,"title":789,"titles":790,"content":791,"level":30},"/v1.0.1/guides/error-handling#basic-circuit-breaker","Basic Circuit Breaker",[363,382],"type: circuit-breaker\nfailure_threshold: 5\nrecovery_timeout: \"60s\"\nchild:\n  ref: external-service",{"id":793,"title":615,"titles":794,"content":795,"level":30},"/v1.0.1/guides/error-handling#how-it-works",[363,382],"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":797,"title":740,"titles":798,"content":799,"level":30},"/v1.0.1/guides/error-handling#configuration-2",[363,382],"FieldDefaultDescriptionfailure_threshold5Failures before openingrecovery_timeout60sTime before testing recovery",{"id":801,"title":735,"titles":802,"content":803,"level":30},"/v1.0.1/guides/error-handling#when-to-use-3",[363,382],"Calling external servicesProtecting against cascade failuresAllowing degraded operationPreventing resource exhaustion from retrying failing calls",{"id":805,"title":387,"titles":806,"content":807,"level":19},"/v1.0.1/guides/error-handling#rate-limiting",[363],"Control request throughput.",{"id":809,"title":810,"titles":811,"content":812,"level":30},"/v1.0.1/guides/error-handling#basic-rate-limit","Basic Rate Limit",[363,387],"type: rate-limit\nrequests_per_second: 100.0\nburst_size: 10\nchild:\n  ref: rate-sensitive-api",{"id":814,"title":740,"titles":815,"content":816,"level":30},"/v1.0.1/guides/error-handling#configuration-3",[363,387],"FieldDefaultDescriptionrequests_per_second10.0Sustained rate limitburst_size1Allowed burst above limit",{"id":818,"title":735,"titles":819,"content":820,"level":30},"/v1.0.1/guides/error-handling#when-to-use-4",[363,387],"Calling APIs with rate limitsProtecting downstream servicesEnsuring fair resource usagePreventing thundering herd",{"id":822,"title":823,"titles":824,"content":24,"level":19},"/v1.0.1/guides/error-handling#combining-patterns","Combining Patterns",[363],{"id":826,"title":827,"titles":828,"content":829,"level":30},"/v1.0.1/guides/error-handling#resilient-external-call","Resilient External Call",[363,823],"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":831,"title":832,"titles":833,"content":834,"level":30},"/v1.0.1/guides/error-handling#fallback-with-resilience","Fallback with Resilience",[363,823],"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":836,"title":837,"titles":838,"content":839,"level":30},"/v1.0.1/guides/error-handling#rate-limited-with-timeout","Rate Limited with Timeout",[363,823],"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":841,"title":842,"titles":843,"content":844,"level":19},"/v1.0.1/guides/error-handling#error-types","Error Types",[363],"Understand which errors trigger which behaviour: ConnectorTriggers OnRetryAny error returnedFallbackAny error from primaryTimeoutContext deadline exceededCircuit BreakerAny error (tracks count)",{"id":846,"title":685,"titles":847,"content":24,"level":19},"/v1.0.1/guides/error-handling#best-practices",[363],{"id":849,"title":850,"titles":851,"content":852,"level":30},"/v1.0.1/guides/error-handling#_1-set-realistic-timeouts","1. Set Realistic Timeouts",[363,685],"# 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":854,"title":855,"titles":856,"content":857,"level":30},"/v1.0.1/guides/error-handling#_2-tune-circuit-breaker-thresholds","2. Tune Circuit Breaker Thresholds",[363,685],"# 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":859,"title":860,"titles":861,"content":862,"level":30},"/v1.0.1/guides/error-handling#_3-use-backoff-for-rate-limits","3. Use Backoff for Rate Limits",[363,685],"type: retry\nattempts: 5\nbackoff: \"1s\"  # Gives rate limit time to reset\nchild:\n  ref: rate-limited-api",{"id":864,"title":865,"titles":866,"content":867,"level":30},"/v1.0.1/guides/error-handling#_4-dont-retry-non-retryable-errors","4. Don't Retry Non-Retryable Errors",[363,685],"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":869,"title":870,"titles":871,"content":872,"level":30},"/v1.0.1/guides/error-handling#_5-monitor-error-rates","5. Monitor Error Rates",[363,685],"Use Capitan events to track failures: capitan.Handle(flume.SchemaBuildFailed, logFailure)\n// Also monitor your processor errors",{"id":874,"title":150,"titles":875,"content":876,"level":19},"/v1.0.1/guides/error-handling#next-steps",[363],"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":878,"title":879,"titles":880,"content":881,"level":9},"/v1.0.1/guides/testing","Testing",[],"Testing strategies for schema-driven pipelines",{"id":883,"title":879,"titles":884,"content":885,"level":9},"/v1.0.1/guides/testing#testing",[],"Strategies for testing Flume pipelines at multiple levels.",{"id":887,"title":888,"titles":889,"content":890,"level":19},"/v1.0.1/guides/testing#testing-levels","Testing Levels",[879],"Unit Tests - Test individual processorsSchema Tests - Test schema validationIntegration Tests - Test complete pipelinesProperty Tests - Test invariants across schemas",{"id":892,"title":893,"titles":894,"content":895,"level":19},"/v1.0.1/guides/testing#unit-testing-processors","Unit Testing Processors",[879],"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":897,"title":898,"titles":899,"content":900,"level":19},"/v1.0.1/guides/testing#testing-predicates","Testing Predicates",[879],"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":902,"title":903,"titles":904,"content":905,"level":19},"/v1.0.1/guides/testing#schema-validation-tests","Schema Validation Tests",[879],"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":907,"title":908,"titles":909,"content":910,"level":19},"/v1.0.1/guides/testing#cicd-schema-linting","CI/CD Schema Linting",[879],"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":912,"title":913,"titles":914,"content":915,"level":30},"/v1.0.1/guides/testing#lint-schema-files","Lint Schema Files",[879,908],"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":917,"title":918,"titles":919,"content":920,"level":30},"/v1.0.1/guides/testing#ci-pipeline-example","CI Pipeline Example",[879,908],"# .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":922,"title":923,"titles":924,"content":925,"level":30},"/v1.0.1/guides/testing#what-each-validation-checks","What Each Validation Checks",[879,908],"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":927,"title":928,"titles":929,"content":930,"level":19},"/v1.0.1/guides/testing#integration-testing","Integration Testing",[879],"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":932,"title":933,"titles":934,"content":24,"level":19},"/v1.0.1/guides/testing#testing-error-handling","Testing Error Handling",[879],{"id":936,"title":937,"titles":938,"content":939,"level":30},"/v1.0.1/guides/testing#retry-behaviour","Retry Behaviour",[879,933],"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":941,"title":942,"titles":943,"content":944,"level":30},"/v1.0.1/guides/testing#fallback-behaviour","Fallback Behaviour",[879,933],"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":946,"title":947,"titles":948,"content":949,"level":30},"/v1.0.1/guides/testing#timeout-behaviour","Timeout Behaviour",[879,933],"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":951,"title":952,"titles":953,"content":954,"level":19},"/v1.0.1/guides/testing#testing-hot-reload","Testing Hot Reload",[879],"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":956,"title":957,"titles":958,"content":959,"level":19},"/v1.0.1/guides/testing#concurrent-testing","Concurrent Testing",[879],"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":961,"title":962,"titles":963,"content":964,"level":19},"/v1.0.1/guides/testing#test-helpers","Test Helpers",[879],"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":966,"title":685,"titles":967,"content":968,"level":19},"/v1.0.1/guides/testing#best-practices",[879],"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":970,"title":150,"titles":971,"content":972,"level":19},"/v1.0.1/guides/testing#next-steps",[879],"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":974,"title":666,"titles":975,"content":976,"level":9},"/v1.0.1/guides/observability",[],"Monitor Flume pipelines with Capitan events",{"id":978,"title":666,"titles":979,"content":980,"level":9},"/v1.0.1/guides/observability#observability",[],"Flume integrates with Capitan for comprehensive observability.",{"id":982,"title":6,"titles":983,"content":984,"level":19},"/v1.0.1/guides/observability#overview",[666],"Flume emits structured events throughout its lifecycle: Factory creation and component registrationSchema validation, building, and updatesPipeline retrieval and executionFile loading and parsing",{"id":986,"title":987,"titles":988,"content":24,"level":19},"/v1.0.1/guides/observability#event-categories","Event Categories",[666],{"id":990,"title":991,"titles":992,"content":993,"level":30},"/v1.0.1/guides/observability#factory-events","Factory Events",[666,987],"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":995,"title":996,"titles":997,"content":998,"level":30},"/v1.0.1/guides/observability#schema-events","Schema Events",[666,987],"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":1000,"title":1001,"titles":1002,"content":1003,"level":30},"/v1.0.1/guides/observability#dynamic-schema-events","Dynamic Schema Events",[666,987],"flume.SchemaRegistered   // New schema added\nflume.SchemaUpdated      // Existing schema replaced\nflume.SchemaRemoved      // Schema deleted\nflume.PipelineRetrieved  // Pipeline accessed",{"id":1005,"title":1006,"titles":1007,"content":1008,"level":30},"/v1.0.1/guides/observability#file-events","File Events",[666,987],"flume.SchemaFileLoaded  // File read successfully\nflume.SchemaFileFailed  // File read error\nflume.SchemaYAMLParsed  // YAML parsed\nflume.SchemaJSONParsed  // JSON parsed\nflume.SchemaParseFailed // Parse error",{"id":1010,"title":1011,"titles":1012,"content":1013,"level":19},"/v1.0.1/guides/observability#event-fields","Event Fields",[666],"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":1015,"title":1016,"titles":1017,"content":24,"level":19},"/v1.0.1/guides/observability#setting-up-handlers","Setting Up Handlers",[666],{"id":1019,"title":1020,"titles":1021,"content":1022,"level":30},"/v1.0.1/guides/observability#basic-logging","Basic Logging",[666,1016],"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":1024,"title":1025,"titles":1026,"content":1027,"level":30},"/v1.0.1/guides/observability#metrics-collection","Metrics Collection",[666,1016],"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":1029,"title":1030,"titles":1031,"content":1032,"level":30},"/v1.0.1/guides/observability#distributed-tracing","Distributed Tracing",[666,1016],"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":1034,"title":1035,"titles":1036,"content":24,"level":19},"/v1.0.1/guides/observability#common-monitoring-patterns","Common Monitoring Patterns",[666],{"id":1038,"title":1039,"titles":1040,"content":1041,"level":30},"/v1.0.1/guides/observability#schema-change-alerting","Schema Change Alerting",[666,1035],"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":1043,"title":1044,"titles":1045,"content":1046,"level":30},"/v1.0.1/guides/observability#build-performance-tracking","Build Performance Tracking",[666,1035],"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":1048,"title":1049,"titles":1050,"content":1051,"level":30},"/v1.0.1/guides/observability#validation-error-analysis","Validation Error Analysis",[666,1035],"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":1053,"title":1054,"titles":1055,"content":24,"level":19},"/v1.0.1/guides/observability#debugging-with-events","Debugging with Events",[666],{"id":1057,"title":1058,"titles":1059,"content":1060,"level":30},"/v1.0.1/guides/observability#development-logging","Development Logging",[666,1054],"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":1062,"title":1063,"titles":1064,"content":1065,"level":30},"/v1.0.1/guides/observability#pipeline-access-tracking","Pipeline Access Tracking",[666,1054],"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":1067,"title":1068,"titles":1069,"content":24,"level":19},"/v1.0.1/guides/observability#production-recommendations","Production Recommendations",[666],{"id":1071,"title":1072,"titles":1073,"content":1074,"level":30},"/v1.0.1/guides/observability#_1-monitor-build-failures","1. Monitor Build Failures",[666,1068],"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":1076,"title":1077,"titles":1078,"content":1079,"level":30},"/v1.0.1/guides/observability#_2-track-schema-versions","2. Track Schema Versions",[666,1068],"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":1081,"title":1082,"titles":1083,"content":1084,"level":30},"/v1.0.1/guides/observability#_3-set-up-dashboards","3. Set Up Dashboards",[666,1068],"Key metrics to display: Schema update frequencyBuild success/failure rateBuild duration percentilesPipeline retrieval hit rateValidation error trends",{"id":1086,"title":1087,"titles":1088,"content":1089,"level":30},"/v1.0.1/guides/observability#_4-alert-on-anomalies","4. Alert on Anomalies",[666,1068],"Sudden increase in build failuresUnusually long build timesHigh pipeline miss rateValidation errors after deployment",{"id":1091,"title":150,"titles":1092,"content":1093,"level":19},"/v1.0.1/guides/observability#next-steps",[666],"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":1095,"title":1096,"titles":1097,"content":1098,"level":9},"/v1.0.1/cookbook/common-patterns","Common Patterns",[],"Recipes and patterns for building pipelines with flume",{"id":1100,"title":1096,"titles":1101,"content":1102,"level":9},"/v1.0.1/cookbook/common-patterns#common-patterns",[],"Practical recipes for building pipelines with flume.",{"id":1104,"title":1105,"titles":1106,"content":1107,"level":19},"/v1.0.1/cookbook/common-patterns#validation-pipeline","Validation Pipeline",[1096],"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":1109,"title":1110,"titles":1111,"content":1112,"level":19},"/v1.0.1/cookbook/common-patterns#retry-with-fallback","Retry with Fallback",[1096],"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":1114,"title":1115,"titles":1116,"content":1117,"level":19},"/v1.0.1/cookbook/common-patterns#fan-out-processing","Fan-Out Processing",[1096],"Process data through multiple paths concurrently: type: concurrent\nchildren:\n  - ref: save-to-database\n  - ref: send-notification\n  - ref: update-cache",{"id":1119,"title":1120,"titles":1121,"content":1122,"level":19},"/v1.0.1/cookbook/common-patterns#conditional-routing","Conditional Routing",[1096],"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":1124,"title":1125,"titles":1126,"content":1127,"level":19},"/v1.0.1/cookbook/common-patterns#stream-output","Stream Output",[1096],"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":1129,"title":1130,"titles":1131,"content":1132,"level":19},"/v1.0.1/cookbook/common-patterns#circuit-breaker-protection","Circuit Breaker Protection",[1096],"Protect against cascading failures: type: circuit-breaker\nfailure_threshold: 5\nrecovery_timeout: \"30s\"\nchild:\n  ref: external-api-call",{"id":1134,"title":1135,"titles":1136,"content":1137,"level":19},"/v1.0.1/cookbook/common-patterns#rate-limited-processing","Rate-Limited Processing",[1096],"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":1139,"title":1140,"titles":1141,"content":1142,"level":9},"/v1.0.1/reference/api","API Reference",[],"Complete reference for Flume's public API",{"id":1144,"title":1140,"titles":1145,"content":1146,"level":9},"/v1.0.1/reference/api#api-reference",[],"Complete reference for Flume's public API.",{"id":1148,"title":1149,"titles":1150,"content":24,"level":19},"/v1.0.1/reference/api#factory","Factory",[1140],{"id":1152,"title":1153,"titles":1154,"content":1155,"level":30},"/v1.0.1/reference/api#new","New",[1140,1149],"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":1157,"title":1158,"titles":1159,"content":24,"level":19},"/v1.0.1/reference/api#processor-registration","Processor Registration",[1140],{"id":1161,"title":1162,"titles":1163,"content":1164,"level":30},"/v1.0.1/reference/api#add","Add",[1140,1158],"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":1166,"title":1167,"titles":1168,"content":1169,"level":30},"/v1.0.1/reference/api#addwithmeta","AddWithMeta",[1140,1158],"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":1171,"title":1172,"titles":1173,"content":1174,"level":30},"/v1.0.1/reference/api#remove","Remove",[1140,1158],"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":1176,"title":1177,"titles":1178,"content":1179,"level":30},"/v1.0.1/reference/api#hasprocessor","HasProcessor",[1140,1158],"Checks if a processor is registered. func (f *Factory[T]) HasProcessor(name pipz.Name) bool",{"id":1181,"title":1182,"titles":1183,"content":1184,"level":30},"/v1.0.1/reference/api#listprocessors","ListProcessors",[1140,1158],"Returns all registered processor names. func (f *Factory[T]) ListProcessors() []pipz.Name",{"id":1186,"title":1187,"titles":1188,"content":24,"level":19},"/v1.0.1/reference/api#predicate-registration","Predicate Registration",[1140],{"id":1190,"title":1191,"titles":1192,"content":1193,"level":30},"/v1.0.1/reference/api#addpredicate","AddPredicate",[1140,1187],"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":1195,"title":1196,"titles":1197,"content":1198,"level":30},"/v1.0.1/reference/api#removepredicate","RemovePredicate",[1140,1187],"Removes predicates by name. func (f *Factory[T]) RemovePredicate(names ...pipz.Name) int",{"id":1200,"title":1201,"titles":1202,"content":1203,"level":30},"/v1.0.1/reference/api#haspredicate","HasPredicate",[1140,1187],"Checks if a predicate is registered. func (f *Factory[T]) HasPredicate(name pipz.Name) bool",{"id":1205,"title":1206,"titles":1207,"content":1208,"level":30},"/v1.0.1/reference/api#listpredicates","ListPredicates",[1140,1187],"Returns all registered predicate names. func (f *Factory[T]) ListPredicates() []pipz.Name",{"id":1210,"title":1211,"titles":1212,"content":24,"level":19},"/v1.0.1/reference/api#condition-registration","Condition Registration",[1140],{"id":1214,"title":1215,"titles":1216,"content":1217,"level":30},"/v1.0.1/reference/api#addcondition","AddCondition",[1140,1211],"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":1219,"title":1220,"titles":1221,"content":1222,"level":30},"/v1.0.1/reference/api#removecondition","RemoveCondition",[1140,1211],"Removes conditions by name. func (f *Factory[T]) RemoveCondition(names ...pipz.Name) int",{"id":1224,"title":1225,"titles":1226,"content":1227,"level":30},"/v1.0.1/reference/api#hascondition","HasCondition",[1140,1211],"Checks if a condition is registered. func (f *Factory[T]) HasCondition(name pipz.Name) bool",{"id":1229,"title":1230,"titles":1231,"content":1232,"level":30},"/v1.0.1/reference/api#listconditions","ListConditions",[1140,1211],"Returns all registered condition names. func (f *Factory[T]) ListConditions() []pipz.Name",{"id":1234,"title":1235,"titles":1236,"content":24,"level":19},"/v1.0.1/reference/api#channel-registration","Channel Registration",[1140],{"id":1238,"title":1239,"titles":1240,"content":1241,"level":30},"/v1.0.1/reference/api#addchannel","AddChannel",[1140,1235],"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":1243,"title":1244,"titles":1245,"content":1246,"level":30},"/v1.0.1/reference/api#getchannel","GetChannel",[1140,1235],"Retrieves a registered channel. func (f *Factory[T]) GetChannel(name string) (chan\u003C- T, bool)",{"id":1248,"title":1249,"titles":1250,"content":1251,"level":30},"/v1.0.1/reference/api#haschannel","HasChannel",[1140,1235],"Checks if a channel is registered. func (f *Factory[T]) HasChannel(name string) bool",{"id":1253,"title":1254,"titles":1255,"content":1256,"level":30},"/v1.0.1/reference/api#listchannels","ListChannels",[1140,1235],"Returns all registered channel names. func (f *Factory[T]) ListChannels() []string",{"id":1258,"title":1259,"titles":1260,"content":1261,"level":30},"/v1.0.1/reference/api#removechannel","RemoveChannel",[1140,1235],"Removes a channel from the factory. func (f *Factory[T]) RemoveChannel(name string) bool",{"id":1263,"title":209,"titles":1264,"content":24,"level":19},"/v1.0.1/reference/api#building-pipelines",[1140],{"id":1266,"title":1267,"titles":1268,"content":1269,"level":30},"/v1.0.1/reference/api#build","Build",[1140,209],"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":1271,"title":1272,"titles":1273,"content":1274,"level":30},"/v1.0.1/reference/api#buildfromyaml","BuildFromYAML",[1140,209],"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":1276,"title":1277,"titles":1278,"content":1279,"level":30},"/v1.0.1/reference/api#buildfromjson","BuildFromJSON",[1140,209],"Builds a pipeline from a JSON string. func (f *Factory[T]) BuildFromJSON(jsonStr string) (pipz.Chainable[T], error)",{"id":1281,"title":1282,"titles":1283,"content":1284,"level":30},"/v1.0.1/reference/api#buildfromfile","BuildFromFile",[1140,209],"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":1286,"title":1287,"titles":1288,"content":24,"level":19},"/v1.0.1/reference/api#schema-management","Schema Management",[1140],{"id":1290,"title":1291,"titles":1292,"content":1293,"level":30},"/v1.0.1/reference/api#setschema","SetSchema",[1140,1287],"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":1295,"title":1296,"titles":1297,"content":1298,"level":30},"/v1.0.1/reference/api#getschema","GetSchema",[1140,1287],"Retrieves a schema by name. func (f *Factory[T]) GetSchema(name string) (Schema, bool)",{"id":1300,"title":1301,"titles":1302,"content":1303,"level":30},"/v1.0.1/reference/api#removeschema","RemoveSchema",[1140,1287],"Removes a named schema. func (f *Factory[T]) RemoveSchema(name string) bool Returns: true if removed, false if not found",{"id":1305,"title":1306,"titles":1307,"content":1308,"level":30},"/v1.0.1/reference/api#listschemas","ListSchemas",[1140,1287],"Returns all registered schema names. func (f *Factory[T]) ListSchemas() []string",{"id":1310,"title":1311,"titles":1312,"content":1313,"level":30},"/v1.0.1/reference/api#bind","Bind",[1140,1287],"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":1315,"title":1316,"titles":1317,"content":1318,"level":30},"/v1.0.1/reference/api#get","Get",[1140,1287],"Retrieves an existing binding by identity. func (f *Factory[T]) Get(identity pipz.Identity) *Binding[T] Returns: *Binding[T] if found, nil otherwise",{"id":1320,"title":1321,"titles":1322,"content":1323,"level":19},"/v1.0.1/reference/api#binding","Binding",[1140],"A Binding[T] represents a live pipeline bound to a schema. It provides lock-free execution via atomic.Pointer.",{"id":1325,"title":1326,"titles":1327,"content":1328,"level":30},"/v1.0.1/reference/api#process","Process",[1140,1321],"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":1330,"title":1331,"titles":1332,"content":1333,"level":30},"/v1.0.1/reference/api#withautosync","WithAutoSync",[1140,1321],"Option to enable automatic rebuilding when the source schema changes. flume.WithAutoSync[T]() When enabled, calls to factory.SetSchema() automatically rebuild this binding.",{"id":1335,"title":1336,"titles":1337,"content":1338,"level":30},"/v1.0.1/reference/api#binding-accessors","Binding Accessors",[1140,1321],"binding.Identity()  // Returns pipz.Identity\nbinding.SchemaID()  // Returns string (schema ID)\nbinding.AutoSync()  // Returns bool\nbinding.Pipeline()  // Returns *pipz.Pipeline[T]",{"id":1340,"title":52,"titles":1341,"content":24,"level":19},"/v1.0.1/reference/api#validation",[1140],{"id":1343,"title":1344,"titles":1345,"content":1346,"level":30},"/v1.0.1/reference/api#validateschema","ValidateSchema",[1140,52],"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":1348,"title":1349,"titles":1350,"content":1351,"level":30},"/v1.0.1/reference/api#validateschemastructure","ValidateSchemaStructure",[1140,52],"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":1353,"title":1354,"titles":1355,"content":24,"level":19},"/v1.0.1/reference/api#types","Types",[1140],{"id":1357,"title":1358,"titles":1359,"content":1360,"level":30},"/v1.0.1/reference/api#schema","Schema",[1140,1354],"type Schema struct {\n    Version string `json:\"version,omitempty\" yaml:\"version,omitempty\"`\n    Node    `yaml:\",inline\"`\n}",{"id":1362,"title":1363,"titles":1364,"content":1365,"level":30},"/v1.0.1/reference/api#node","Node",[1140,1354],"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":1367,"title":1368,"titles":1369,"content":1370,"level":30},"/v1.0.1/reference/api#predicate","Predicate",[1140,1354],"type Predicate[T any] struct {\n    Name        pipz.Name\n    Description string\n    Predicate   func(context.Context, T) bool\n}",{"id":1372,"title":1373,"titles":1374,"content":1375,"level":30},"/v1.0.1/reference/api#condition","Condition",[1140,1354],"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":1377,"title":1378,"titles":1379,"content":1380,"level":30},"/v1.0.1/reference/api#processormeta","ProcessorMeta",[1140,1354],"type ProcessorMeta[T any] struct {\n    Processor   pipz.Chainable[T]\n    Description string\n    Tags        []string\n}",{"id":1382,"title":1383,"titles":1384,"content":1385,"level":30},"/v1.0.1/reference/api#reducer","Reducer",[1140,1354],"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":1387,"title":1388,"titles":1389,"content":1390,"level":30},"/v1.0.1/reference/api#errorhandler","ErrorHandler",[1140,1354],"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":1392,"title":1393,"titles":1394,"content":1395,"level":30},"/v1.0.1/reference/api#validationerror","ValidationError",[1140,1354],"type ValidationError struct {\n    Path    []string  // Path to error in schema\n    Message string\n}\n\nfunc (e ValidationError) Error() string",{"id":1397,"title":1398,"titles":1399,"content":1400,"level":30},"/v1.0.1/reference/api#validationerrors","ValidationErrors",[1140,1354],"type ValidationErrors []ValidationError\n\nfunc (e ValidationErrors) Error() string",{"id":1402,"title":1403,"titles":1404,"content":24,"level":19},"/v1.0.1/reference/api#constants","Constants",[1140],{"id":1406,"title":1407,"titles":1408,"content":1409,"level":30},"/v1.0.1/reference/api#default-values","Default Values",[1140,1403],"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":1411,"title":150,"titles":1412,"content":1413,"level":19},"/v1.0.1/reference/api#next-steps",[1140],"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":1415,"title":1416,"titles":1417,"content":1418,"level":9},"/v1.0.1/reference/schema-format","Schema Format",[],"Complete YAML/JSON schema specification",{"id":1420,"title":1416,"titles":1421,"content":1422,"level":9},"/v1.0.1/reference/schema-format#schema-format",[],"Complete specification for Flume schema documents.",{"id":1424,"title":6,"titles":1425,"content":1426,"level":19},"/v1.0.1/reference/schema-format#overview",[1416],"Schemas can be written in YAML or JSON. This reference uses YAML examples; JSON equivalents use standard JSON syntax.",{"id":1428,"title":199,"titles":1429,"content":1430,"level":19},"/v1.0.1/reference/schema-format#schema-structure",[1416],"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":1432,"title":1433,"titles":1434,"content":1435,"level":19},"/v1.0.1/reference/schema-format#top-level-fields","Top-Level Fields",[1416],"FieldTypeRequiredDescriptionversionstringNoSchema version for tracking changesrefstringConditionalReference to registered processortypestringConditionalConnector typenamestringNoOverride default connector name Either ref or type is required, but not both.",{"id":1437,"title":1438,"titles":1439,"content":1440,"level":19},"/v1.0.1/reference/schema-format#processor-reference","Processor Reference",[1416],"Reference a registered processor by name: ref: validate Equivalent to calling the processor directly.",{"id":1442,"title":1443,"titles":1444,"content":24,"level":19},"/v1.0.1/reference/schema-format#connector-types","Connector Types",[1416],{"id":1446,"title":1447,"titles":1448,"content":1449,"level":30},"/v1.0.1/reference/schema-format#sequence","sequence",[1416,1443],"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":1451,"title":1452,"titles":1453,"content":1454,"level":30},"/v1.0.1/reference/schema-format#concurrent","concurrent",[1416,1443],"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":1456,"title":1457,"titles":1458,"content":1459,"level":30},"/v1.0.1/reference/schema-format#race","race",[1416,1443],"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":1461,"title":1462,"titles":1463,"content":1464,"level":30},"/v1.0.1/reference/schema-format#fallback","fallback",[1416,1443],"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":1466,"title":1467,"titles":1468,"content":1469,"level":30},"/v1.0.1/reference/schema-format#retry","retry",[1416,1443],"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":1471,"title":1472,"titles":1473,"content":1474,"level":30},"/v1.0.1/reference/schema-format#timeout","timeout",[1416,1443],"Enforce time limit. type: timeout\nduration: \"5s\"         # Optional\nchild:                 # Required\n  ref: slow-operation FieldTypeRequiredDefaultchildNodeYes-durationdurationNo\"30s\"namestringNo\"timeout\"",{"id":1476,"title":1477,"titles":1478,"content":1479,"level":30},"/v1.0.1/reference/schema-format#filter","filter",[1416,1443],"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":1481,"title":1482,"titles":1483,"content":1484,"level":30},"/v1.0.1/reference/schema-format#switch","switch",[1416,1443],"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":1486,"title":1487,"titles":1488,"content":1489,"level":30},"/v1.0.1/reference/schema-format#circuit-breaker","circuit-breaker",[1416,1443],"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":1491,"title":1492,"titles":1493,"content":1494,"level":30},"/v1.0.1/reference/schema-format#rate-limit","rate-limit",[1416,1443],"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":1496,"title":1497,"titles":1498,"content":1499,"level":30},"/v1.0.1/reference/schema-format#stream","stream",[1416,1443],"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":1501,"title":1502,"titles":1503,"content":1504,"level":30},"/v1.0.1/reference/schema-format#contest","contest",[1416,1443],"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":1506,"title":1507,"titles":1508,"content":1509,"level":30},"/v1.0.1/reference/schema-format#handle","handle",[1416,1443],"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":1511,"title":1512,"titles":1513,"content":1514,"level":30},"/v1.0.1/reference/schema-format#scaffold","scaffold",[1416,1443],"Structural grouping of children. type: scaffold\nname: validation-stage   # Optional\nchildren:                # Required: 1+ children\n  - ref: step1\n  - ref: step2 FieldTypeRequiredDefaultchildrenNodeYes-namestringNo\"scaffold\"",{"id":1516,"title":1517,"titles":1518,"content":1519,"level":30},"/v1.0.1/reference/schema-format#worker-pool","worker-pool",[1416,1443],"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":1521,"title":1522,"titles":1523,"content":1524,"level":19},"/v1.0.1/reference/schema-format#duration-format","Duration Format",[1416],"Durations use Go's duration format: FormatExampleNanoseconds100nsMicroseconds50µs or 50usMilliseconds100msSeconds5sMinutes2mHours1hCombined1h30m, 2m30s",{"id":1526,"title":1527,"titles":1528,"content":1529,"level":19},"/v1.0.1/reference/schema-format#nesting","Nesting",[1416],"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":1531,"title":1532,"titles":1533,"content":1534,"level":19},"/v1.0.1/reference/schema-format#json-format","JSON Format",[1416],"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":1536,"title":1537,"titles":1538,"content":1539,"level":19},"/v1.0.1/reference/schema-format#validation-rules","Validation Rules",[1416],"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":1541,"title":150,"titles":1542,"content":1543,"level":19},"/v1.0.1/reference/schema-format#next-steps",[1416],"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":1545,"title":1443,"titles":1546,"content":1547,"level":9},"/v1.0.1/reference/connector-types",[],"Detailed reference for all Flume connector types",{"id":1549,"title":1443,"titles":1550,"content":1551,"level":9},"/v1.0.1/reference/connector-types#connector-types",[],"Detailed reference for all Flume connector types and their behaviour.",{"id":1553,"title":1554,"titles":1555,"content":24,"level":19},"/v1.0.1/reference/connector-types#flow-control","Flow Control",[1443],{"id":1557,"title":1447,"titles":1558,"content":1559,"level":30},"/v1.0.1/reference/connector-types#sequence",[1443,1554],"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":1561,"title":1452,"titles":1562,"content":1563,"level":30},"/v1.0.1/reference/connector-types#concurrent",[1443,1554],"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":1565,"title":1457,"titles":1566,"content":1567,"level":30},"/v1.0.1/reference/connector-types#race",[1443,1554],"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":1569,"title":363,"titles":1570,"content":24,"level":19},"/v1.0.1/reference/connector-types#error-handling",[1443],{"id":1572,"title":1462,"titles":1573,"content":1574,"level":30},"/v1.0.1/reference/connector-types#fallback",[1443,363],"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":1576,"title":1467,"titles":1577,"content":1578,"level":30},"/v1.0.1/reference/connector-types#retry",[1443,363],"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":1580,"title":1472,"titles":1581,"content":1582,"level":30},"/v1.0.1/reference/connector-types#timeout",[1443,363],"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":1584,"title":1487,"titles":1585,"content":1586,"level":30},"/v1.0.1/reference/connector-types#circuit-breaker",[1443,363],"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":1588,"title":1492,"titles":1589,"content":1590,"level":30},"/v1.0.1/reference/connector-types#rate-limit",[1443,363],"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":1592,"title":1593,"titles":1594,"content":24,"level":19},"/v1.0.1/reference/connector-types#routing","Routing",[1443],{"id":1596,"title":1477,"titles":1597,"content":1598,"level":30},"/v1.0.1/reference/connector-types#filter",[1443,1593],"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":1600,"title":1482,"titles":1601,"content":1602,"level":30},"/v1.0.1/reference/connector-types#switch",[1443,1593],"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":1604,"title":1605,"titles":1606,"content":24,"level":19},"/v1.0.1/reference/connector-types#streaming","Streaming",[1443],{"id":1608,"title":1497,"titles":1609,"content":1610,"level":30},"/v1.0.1/reference/connector-types#stream",[1443,1605],"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":1612,"title":1613,"titles":1614,"content":24,"level":19},"/v1.0.1/reference/connector-types#advanced","Advanced",[1443],{"id":1616,"title":1502,"titles":1617,"content":1618,"level":30},"/v1.0.1/reference/connector-types#contest",[1443,1613],"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":1620,"title":1507,"titles":1621,"content":1622,"level":30},"/v1.0.1/reference/connector-types#handle",[1443,1613],"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":1624,"title":1512,"titles":1625,"content":1626,"level":30},"/v1.0.1/reference/connector-types#scaffold",[1443,1613],"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":1628,"title":1517,"titles":1629,"content":1630,"level":30},"/v1.0.1/reference/connector-types#worker-pool",[1443,1613],"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":1632,"title":1633,"titles":1634,"content":1635,"level":19},"/v1.0.1/reference/connector-types#comparison-table","Comparison Table",[1443],"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":1637,"title":150,"titles":1638,"content":1639,"level":19},"/v1.0.1/reference/connector-types#next-steps",[1443],"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":1641,"title":1642,"titles":1643,"content":1644,"level":9},"/v1.0.1/reference/events","Events",[],"Complete reference for Flume observability events",{"id":1646,"title":1642,"titles":1647,"content":1648,"level":9},"/v1.0.1/reference/events#events",[],"Complete reference for Flume's observability events using Capitan.",{"id":1650,"title":1651,"titles":1652,"content":24,"level":19},"/v1.0.1/reference/events#signal-categories","Signal Categories",[1642],{"id":1654,"title":1655,"titles":1656,"content":1657,"level":30},"/v1.0.1/reference/events#factory-lifecycle","Factory Lifecycle",[1642,1651],"SignalDescriptionFactoryCreatedFactory instantiatedProcessorRegisteredProcessor added to factoryPredicateRegisteredPredicate added to factoryConditionRegisteredCondition added to factoryProcessorRemovedProcessor removed from factoryPredicateRemovedPredicate removed from factoryConditionRemovedCondition removed from factory",{"id":1659,"title":1660,"titles":1661,"content":1662,"level":30},"/v1.0.1/reference/events#schema-validation","Schema Validation",[1642,1651],"SignalDescriptionSchemaValidationStartedValidation beganSchemaValidationCompletedValidation successfulSchemaValidationFailedValidation found errors",{"id":1664,"title":1665,"titles":1666,"content":1667,"level":30},"/v1.0.1/reference/events#schema-building","Schema Building",[1642,1651],"SignalDescriptionSchemaBuildStartedBuild beganSchemaBuildCompletedBuild successfulSchemaBuildFailedBuild failed",{"id":1669,"title":214,"titles":1670,"content":1671,"level":30},"/v1.0.1/reference/events#dynamic-schema-management",[1642,1651],"SignalDescriptionSchemaRegisteredNew schema added via SetSchemaSchemaUpdatedExisting schema replacedSchemaRemovedSchema removedPipelineRetrievedPipeline accessed via Pipeline()",{"id":1673,"title":1674,"titles":1675,"content":1676,"level":30},"/v1.0.1/reference/events#file-operations","File Operations",[1642,1651],"SignalDescriptionSchemaFileLoadedFile read successfullySchemaFileFailedFile read failedSchemaYAMLParsedYAML parsed successfullySchemaJSONParsedJSON parsed successfullySchemaParseFailedParse failed",{"id":1678,"title":1679,"titles":1680,"content":24,"level":19},"/v1.0.1/reference/events#field-keys","Field Keys",[1642],{"id":1682,"title":1683,"titles":1684,"content":1685,"level":30},"/v1.0.1/reference/events#string-fields","String Fields",[1642,1679],"KeyTypeDescriptionKeyNamestringComponent or schema nameKeyTypestringData type (e.g., *main.Order)KeyVersionstringSchema versionKeyOldVersionstringPrevious version (on update)KeyNewVersionstringNew version (on update)KeyPathstringFile pathKeyErrorstringError message",{"id":1687,"title":1688,"titles":1689,"content":1690,"level":30},"/v1.0.1/reference/events#duration-fields","Duration Fields",[1642,1679],"KeyTypeDescriptionKeyDurationtime.DurationOperation duration",{"id":1692,"title":1693,"titles":1694,"content":1695,"level":30},"/v1.0.1/reference/events#integer-fields","Integer Fields",[1642,1679],"KeyTypeDescriptionKeyErrorCountintNumber of validation errorsKeySizeBytesintFile size in bytes",{"id":1697,"title":1698,"titles":1699,"content":1700,"level":30},"/v1.0.1/reference/events#boolean-fields","Boolean Fields",[1642,1679],"KeyTypeDescriptionKeyFoundboolWhether pipeline was found",{"id":1702,"title":1703,"titles":1704,"content":24,"level":19},"/v1.0.1/reference/events#event-details","Event Details",[1642],{"id":1706,"title":1707,"titles":1708,"content":1709,"level":30},"/v1.0.1/reference/events#factorycreated","FactoryCreated",[1642,1703],"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":1711,"title":1712,"titles":1713,"content":1714,"level":30},"/v1.0.1/reference/events#processorregistered","ProcessorRegistered",[1642,1703],"Emitted when a processor is added. Fields: KeyName: Processor name",{"id":1716,"title":1717,"titles":1718,"content":1719,"level":30},"/v1.0.1/reference/events#schemavalidationstarted","SchemaValidationStarted",[1642,1703],"Emitted at the start of validation. Fields: None",{"id":1721,"title":1722,"titles":1723,"content":1724,"level":30},"/v1.0.1/reference/events#schemavalidationcompleted","SchemaValidationCompleted",[1642,1703],"Emitted on successful validation. Fields: KeyDuration: Validation duration",{"id":1726,"title":1727,"titles":1728,"content":1729,"level":30},"/v1.0.1/reference/events#schemavalidationfailed","SchemaValidationFailed",[1642,1703],"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":1731,"title":1732,"titles":1733,"content":1734,"level":30},"/v1.0.1/reference/events#schemabuildstarted","SchemaBuildStarted",[1642,1703],"Emitted at the start of building. Fields: KeyVersion: Schema version (if present)",{"id":1736,"title":1737,"titles":1738,"content":1739,"level":30},"/v1.0.1/reference/events#schemabuildcompleted","SchemaBuildCompleted",[1642,1703],"Emitted on successful build. Fields: KeyDuration: Build durationKeyVersion: Schema version (if present)",{"id":1741,"title":1742,"titles":1743,"content":1744,"level":30},"/v1.0.1/reference/events#schemabuildfailed","SchemaBuildFailed",[1642,1703],"Emitted when build fails. Fields: KeyError: Error messageKeyDuration: Duration until failureKeyVersion: Schema version (if present)",{"id":1746,"title":1747,"titles":1748,"content":1749,"level":30},"/v1.0.1/reference/events#schemaregistered","SchemaRegistered",[1642,1703],"Emitted when a new schema is added. Fields: KeyName: Schema nameKeyVersion: Schema version (if present)",{"id":1751,"title":1752,"titles":1753,"content":1754,"level":30},"/v1.0.1/reference/events#schemaupdated","SchemaUpdated",[1642,1703],"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":1756,"title":1757,"titles":1758,"content":1759,"level":30},"/v1.0.1/reference/events#pipelineretrieved","PipelineRetrieved",[1642,1703],"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":1761,"title":1762,"titles":1763,"content":1764,"level":30},"/v1.0.1/reference/events#schemafileloaded","SchemaFileLoaded",[1642,1703],"Emitted when a file is read. Fields: KeyPath: File pathKeySizeBytes: File size",{"id":1766,"title":1767,"titles":1768,"content":1769,"level":30},"/v1.0.1/reference/events#schemaparsefailed","SchemaParseFailed",[1642,1703],"Emitted when parsing fails. Fields: KeyPath: File path (if from file)KeyError: Parse error message",{"id":1771,"title":1772,"titles":1773,"content":24,"level":19},"/v1.0.1/reference/events#handler-patterns","Handler Patterns",[1642],{"id":1775,"title":1776,"titles":1777,"content":1778,"level":30},"/v1.0.1/reference/events#complete-logging-handler","Complete Logging Handler",[1642,1772],"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":1780,"title":1781,"titles":1782,"content":1783,"level":30},"/v1.0.1/reference/events#metrics-handler","Metrics Handler",[1642,1772],"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":1785,"title":1786,"titles":1787,"content":1788,"level":30},"/v1.0.1/reference/events#alerting-handler","Alerting Handler",[1642,1772],"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":1790,"title":1791,"titles":1792,"content":1793,"level":19},"/v1.0.1/reference/events#helper-functions","Helper Functions",[1642],"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":1795,"title":150,"titles":1796,"content":1797,"level":19},"/v1.0.1/reference/events#next-steps",[1642],"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)}",[1799],{"title":1800,"path":1801,"stem":1802,"children":1803,"page":1818},"V101","/v1.0.1","v1.0.1",[1804,1806,1819,1833,1840],{"title":6,"path":5,"stem":1805,"description":8},"v1.0.1/1.overview",{"title":66,"path":1807,"stem":1808,"children":1809,"page":1818},"/v1.0.1/learn","v1.0.1/2.learn",[1810,1812,1814,1816],{"title":81,"path":80,"stem":1811,"description":83},"v1.0.1/2.learn/1.quickstart",{"title":155,"path":154,"stem":1813,"description":157},"v1.0.1/2.learn/2.core-concepts",{"title":16,"path":246,"stem":1815,"description":248},"v1.0.1/2.learn/3.architecture",{"title":209,"path":330,"stem":1817,"description":332},"v1.0.1/2.learn/4.building-pipelines",false,{"title":71,"path":1820,"stem":1821,"children":1822,"page":1818},"/v1.0.1/guides","v1.0.1/3.guides",[1823,1825,1827,1829,1831],{"title":443,"path":442,"stem":1824,"description":445},"v1.0.1/3.guides/1.schema-design",{"title":219,"path":583,"stem":1826,"description":585},"v1.0.1/3.guides/2.hot-reloading",{"title":363,"path":712,"stem":1828,"description":714},"v1.0.1/3.guides/3.error-handling",{"title":879,"path":878,"stem":1830,"description":881},"v1.0.1/3.guides/4.testing",{"title":666,"path":974,"stem":1832,"description":976},"v1.0.1/3.guides/5.observability",{"title":1834,"path":1835,"stem":1836,"children":1837,"page":1818},"Cookbook","/v1.0.1/cookbook","v1.0.1/4.cookbook",[1838],{"title":1096,"path":1095,"stem":1839,"description":1098},"v1.0.1/4.cookbook/1.common-patterns",{"title":76,"path":1841,"stem":1842,"children":1843,"page":1818},"/v1.0.1/reference","v1.0.1/5.reference",[1844,1846,1848,1850],{"title":1140,"path":1139,"stem":1845,"description":1142},"v1.0.1/5.reference/1.api",{"title":1416,"path":1415,"stem":1847,"description":1418},"v1.0.1/5.reference/2.schema-format",{"title":1443,"path":1545,"stem":1849,"description":1547},"v1.0.1/5.reference/3.connector-types",{"title":1642,"path":1641,"stem":1851,"description":1644},"v1.0.1/5.reference/4.events",[1853],{"title":1800,"path":1801,"stem":1802,"children":1854,"page":1818},[1855,1856,1862,1869,1872],{"title":6,"path":5,"stem":1805},{"title":66,"path":1807,"stem":1808,"children":1857,"page":1818},[1858,1859,1860,1861],{"title":81,"path":80,"stem":1811},{"title":155,"path":154,"stem":1813},{"title":16,"path":246,"stem":1815},{"title":209,"path":330,"stem":1817},{"title":71,"path":1820,"stem":1821,"children":1863,"page":1818},[1864,1865,1866,1867,1868],{"title":443,"path":442,"stem":1824},{"title":219,"path":583,"stem":1826},{"title":363,"path":712,"stem":1828},{"title":879,"path":878,"stem":1830},{"title":666,"path":974,"stem":1832},{"title":1834,"path":1835,"stem":1836,"children":1870,"page":1818},[1871],{"title":1096,"path":1095,"stem":1839},{"title":76,"path":1841,"stem":1842,"children":1873,"page":1818},[1874,1875,1876,1877],{"title":1140,"path":1139,"stem":1845},{"title":1416,"path":1415,"stem":1847},{"title":1443,"path":1545,"stem":1849},{"title":1642,"path":1641,"stem":1851},[1879,3704,4152],{"id":1880,"title":1881,"body":1882,"description":24,"extension":3697,"icon":3698,"meta":3699,"navigation":2360,"path":3700,"seo":3701,"stem":3702,"__hash__":3703},"resources/readme.md","README",{"type":1883,"value":1884,"toc":3680},"minimark",[1885,1890,1958,1967,1972,2485,2488,2491,2508,2512,3113,3116,3216,3220,3267,3271,3277,3280,3387,3399,3402,3405,3546,3549,3556,3560,3586,3589,3618,3621,3629,3632,3655,3659,3667,3670,3676],[1886,1887,1889],"h1",{"id":1888},"flume","Flume",[1891,1892,1893,1904,1912,1920,1928,1936,1943,1950],"p",{},[1894,1895,1899],"a",{"href":1896,"rel":1897},"https://github.com/zoobz-io/flume/actions/workflows/ci.yml",[1898],"nofollow",[1900,1901],"img",{"alt":1902,"src":1903},"CI Status","https://github.com/zoobz-io/flume/workflows/CI/badge.svg",[1894,1905,1908],{"href":1906,"rel":1907},"https://codecov.io/gh/zoobz-io/flume",[1898],[1900,1909],{"alt":1910,"src":1911},"codecov","https://codecov.io/gh/zoobz-io/flume/graph/badge.svg?branch=main",[1894,1913,1916],{"href":1914,"rel":1915},"https://goreportcard.com/report/github.com/zoobz-io/flume",[1898],[1900,1917],{"alt":1918,"src":1919},"Go Report Card","https://goreportcard.com/badge/github.com/zoobz-io/flume",[1894,1921,1924],{"href":1922,"rel":1923},"https://github.com/zoobz-io/flume/security/code-scanning",[1898],[1900,1925],{"alt":1926,"src":1927},"CodeQL","https://github.com/zoobz-io/flume/workflows/CodeQL/badge.svg",[1894,1929,1932],{"href":1930,"rel":1931},"https://pkg.go.dev/github.com/zoobz-io/flume",[1898],[1900,1933],{"alt":1934,"src":1935},"Go Reference","https://pkg.go.dev/badge/github.com/zoobz-io/flume.svg",[1894,1937,1939],{"href":1938},"LICENSE",[1900,1940],{"alt":1941,"src":1942},"License","https://img.shields.io/github/license/zoobz-io/flume",[1894,1944,1946],{"href":1945},"go.mod",[1900,1947],{"alt":1948,"src":1949},"Go Version","https://img.shields.io/github/go-mod/go-version/zoobz-io/flume",[1894,1951,1954],{"href":1952,"rel":1953},"https://github.com/zoobz-io/flume/releases",[1898],[1900,1955],{"alt":1956,"src":1957},"Release","https://img.shields.io/github/v/release/zoobz-io/flume",[1891,1959,1960,1961,1966],{},"A dynamic pipeline factory for ",[1894,1962,1965],{"href":1963,"rel":1964},"https://github.com/zoobz-io/pipz",[1898],"pipz"," that enables schema-driven pipeline construction with hot-reloading capabilities.",[1968,1969,1971],"h2",{"id":1970},"logic-in-code-structure-in-schema","Logic in Code, Structure in Schema",[1973,1974,1978],"pre",{"className":1975,"code":1976,"language":1977,"meta":24,"style":24},"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",[1979,1980,1981,1989,2018,2029,2094,2117,2143,2149,2162,2168,2216,2235,2246,2251,2256,2280,2296,2349,2355,2362,2368,2393,2399,2405,2411,2417,2423,2429,2435,2443,2448,2454],"code",{"__ignoreMap":24},[1982,1983,1985],"span",{"class":1984,"line":9},"line",[1982,1986,1988],{"class":1987},"sLkEo","// 1. Register components\n",[1982,1990,1991,1995,1998,2001,2005,2008,2011,2015],{"class":1984,"line":19},[1982,1992,1994],{"class":1993},"sh8_p","factory",[1982,1996,1997],{"class":1993}," :=",[1982,1999,2000],{"class":1993}," flume",[1982,2002,2004],{"class":2003},"sq5bi",".",[1982,2006,1153],{"class":2007},"s5klm",[1982,2009,2010],{"class":2003},"[",[1982,2012,2014],{"class":2013},"sYBwO","Order",[1982,2016,2017],{"class":2003},"]()\n",[1982,2019,2020,2022,2024,2026],{"class":1984,"line":30},[1982,2021,1994],{"class":1993},[1982,2023,2004],{"class":2003},[1982,2025,1162],{"class":2007},[1982,2027,2028],{"class":2003},"(\n",[1982,2030,2032,2035,2037,2040,2043,2047,2050,2054,2056,2060,2063,2065,2068,2070,2073,2076,2079,2082,2084,2086,2089,2091],{"class":1984,"line":2031},4,[1982,2033,2034],{"class":1993},"    pipz",[1982,2036,2004],{"class":2003},[1982,2038,2039],{"class":2007},"Apply",[1982,2041,2042],{"class":2003},"(",[1982,2044,2046],{"class":2045},"sxAnc","\"validate\"",[1982,2048,2049],{"class":2003},",",[1982,2051,2053],{"class":2052},"sUt3r"," func",[1982,2055,2042],{"class":2003},[1982,2057,2059],{"class":2058},"sSYET","ctx",[1982,2061,2062],{"class":2013}," context",[1982,2064,2004],{"class":2003},[1982,2066,2067],{"class":2013},"Context",[1982,2069,2049],{"class":2003},[1982,2071,2072],{"class":2058}," o",[1982,2074,2075],{"class":2013}," Order",[1982,2077,2078],{"class":2003},")",[1982,2080,2081],{"class":2003}," (",[1982,2083,2014],{"class":2013},[1982,2085,2049],{"class":2003},[1982,2087,2088],{"class":2013}," error",[1982,2090,2078],{"class":2003},[1982,2092,2093],{"class":2003}," {\n",[1982,2095,2097,2101,2103,2105,2108,2111,2115],{"class":1984,"line":2096},5,[1982,2098,2100],{"class":2099},"sW3Qg","        if",[1982,2102,2072],{"class":1993},[1982,2104,2004],{"class":2003},[1982,2106,2107],{"class":1993},"Total",[1982,2109,2110],{"class":2099}," \u003C=",[1982,2112,2114],{"class":2113},"sMAmT"," 0",[1982,2116,2093],{"class":2003},[1982,2118,2120,2123,2125,2127,2130,2132,2135,2137,2140],{"class":1984,"line":2119},6,[1982,2121,2122],{"class":2099},"            return",[1982,2124,2072],{"class":1993},[1982,2126,2049],{"class":2003},[1982,2128,2129],{"class":1993}," fmt",[1982,2131,2004],{"class":2003},[1982,2133,2134],{"class":2007},"Errorf",[1982,2136,2042],{"class":2003},[1982,2138,2139],{"class":2045},"\"invalid total\"",[1982,2141,2142],{"class":2003},")\n",[1982,2144,2146],{"class":1984,"line":2145},7,[1982,2147,2148],{"class":2003},"        }\n",[1982,2150,2152,2155,2157,2159],{"class":1984,"line":2151},8,[1982,2153,2154],{"class":2099},"        return",[1982,2156,2072],{"class":1993},[1982,2158,2049],{"class":2003},[1982,2160,2161],{"class":2052}," nil\n",[1982,2163,2165],{"class":1984,"line":2164},9,[1982,2166,2167],{"class":2003},"    }),\n",[1982,2169,2171,2173,2175,2177,2179,2182,2184,2186,2188,2190,2192,2194,2196,2198,2200,2202,2204,2206,2208,2210,2212,2214],{"class":1984,"line":2170},10,[1982,2172,2034],{"class":1993},[1982,2174,2004],{"class":2003},[1982,2176,2039],{"class":2007},[1982,2178,2042],{"class":2003},[1982,2180,2181],{"class":2045},"\"apply-discount\"",[1982,2183,2049],{"class":2003},[1982,2185,2053],{"class":2052},[1982,2187,2042],{"class":2003},[1982,2189,2059],{"class":2058},[1982,2191,2062],{"class":2013},[1982,2193,2004],{"class":2003},[1982,2195,2067],{"class":2013},[1982,2197,2049],{"class":2003},[1982,2199,2072],{"class":2058},[1982,2201,2075],{"class":2013},[1982,2203,2078],{"class":2003},[1982,2205,2081],{"class":2003},[1982,2207,2014],{"class":2013},[1982,2209,2049],{"class":2003},[1982,2211,2088],{"class":2013},[1982,2213,2078],{"class":2003},[1982,2215,2093],{"class":2003},[1982,2217,2219,2222,2224,2226,2229,2232],{"class":1984,"line":2218},11,[1982,2220,2221],{"class":1993},"        o",[1982,2223,2004],{"class":2003},[1982,2225,2107],{"class":1993},[1982,2227,2228],{"class":1993}," *=",[1982,2230,2231],{"class":2113}," 0.9",[1982,2233,2234],{"class":1987}," // 10% discount\n",[1982,2236,2238,2240,2242,2244],{"class":1984,"line":2237},12,[1982,2239,2154],{"class":2099},[1982,2241,2072],{"class":1993},[1982,2243,2049],{"class":2003},[1982,2245,2161],{"class":2052},[1982,2247,2249],{"class":1984,"line":2248},13,[1982,2250,2167],{"class":2003},[1982,2252,2254],{"class":1984,"line":2253},14,[1982,2255,2142],{"class":2003},[1982,2257,2259,2261,2263,2265,2267,2269,2271,2273,2275,2277],{"class":1984,"line":2258},15,[1982,2260,1994],{"class":1993},[1982,2262,2004],{"class":2003},[1982,2264,1191],{"class":2007},[1982,2266,2042],{"class":2003},[1982,2268,1888],{"class":2013},[1982,2270,2004],{"class":2003},[1982,2272,1368],{"class":2013},[1982,2274,2010],{"class":2003},[1982,2276,2014],{"class":2013},[1982,2278,2279],{"class":2003},"]{\n",[1982,2281,2283,2287,2290,2293],{"class":1984,"line":2282},16,[1982,2284,2286],{"class":2285},"sBGCq","    Name",[1982,2288,2289],{"class":2003},":",[1982,2291,2292],{"class":2045},"      \"is-premium\"",[1982,2294,2295],{"class":2003},",\n",[1982,2297,2299,2302,2304,2306,2308,2310,2312,2314,2316,2318,2320,2322,2324,2327,2330,2333,2335,2337,2340,2343,2346],{"class":1984,"line":2298},17,[1982,2300,2301],{"class":2285},"    Predicate",[1982,2303,2289],{"class":2003},[1982,2305,2053],{"class":2052},[1982,2307,2042],{"class":2003},[1982,2309,2059],{"class":2058},[1982,2311,2062],{"class":2013},[1982,2313,2004],{"class":2003},[1982,2315,2067],{"class":2013},[1982,2317,2049],{"class":2003},[1982,2319,2072],{"class":2058},[1982,2321,2075],{"class":2013},[1982,2323,2078],{"class":2003},[1982,2325,2326],{"class":2013}," bool",[1982,2328,2329],{"class":2003}," {",[1982,2331,2332],{"class":2099}," return",[1982,2334,2072],{"class":1993},[1982,2336,2004],{"class":2003},[1982,2338,2339],{"class":1993},"Tier",[1982,2341,2342],{"class":2099}," ==",[1982,2344,2345],{"class":2045}," \"premium\"",[1982,2347,2348],{"class":2003}," },\n",[1982,2350,2352],{"class":1984,"line":2351},18,[1982,2353,2354],{"class":2003},"})\n",[1982,2356,2358],{"class":1984,"line":2357},19,[1982,2359,2361],{"emptyLinePlaceholder":2360},true,"\n",[1982,2363,2365],{"class":1984,"line":2364},20,[1982,2366,2367],{"class":1987},"// 2. Build from schema\n",[1982,2369,2371,2374,2376,2379,2381,2384,2386,2388,2390],{"class":1984,"line":2370},21,[1982,2372,2373],{"class":1993},"pipeline",[1982,2375,2049],{"class":2003},[1982,2377,2378],{"class":1993}," _",[1982,2380,1997],{"class":1993},[1982,2382,2383],{"class":1993}," factory",[1982,2385,2004],{"class":2003},[1982,2387,1272],{"class":2007},[1982,2389,2042],{"class":2003},[1982,2391,2392],{"class":2045},"`\n",[1982,2394,2396],{"class":1984,"line":2395},22,[1982,2397,2398],{"class":2045},"type: sequence\n",[1982,2400,2402],{"class":1984,"line":2401},23,[1982,2403,2404],{"class":2045},"children:\n",[1982,2406,2408],{"class":1984,"line":2407},24,[1982,2409,2410],{"class":2045},"  - ref: validate\n",[1982,2412,2414],{"class":1984,"line":2413},25,[1982,2415,2416],{"class":2045},"  - type: filter\n",[1982,2418,2420],{"class":1984,"line":2419},26,[1982,2421,2422],{"class":2045},"    predicate: is-premium\n",[1982,2424,2426],{"class":1984,"line":2425},27,[1982,2427,2428],{"class":2045},"    then:\n",[1982,2430,2432],{"class":1984,"line":2431},28,[1982,2433,2434],{"class":2045},"      ref: apply-discount\n",[1982,2436,2438,2441],{"class":1984,"line":2437},29,[1982,2439,2440],{"class":2045},"`",[1982,2442,2142],{"class":2003},[1982,2444,2446],{"class":1984,"line":2445},30,[1982,2447,2361],{"emptyLinePlaceholder":2360},[1982,2449,2451],{"class":1984,"line":2450},31,[1982,2452,2453],{"class":1987},"// 3. Process data\n",[1982,2455,2457,2460,2462,2465,2467,2470,2472,2474,2476,2478,2480,2483],{"class":1984,"line":2456},32,[1982,2458,2459],{"class":1993},"result",[1982,2461,2049],{"class":2003},[1982,2463,2464],{"class":1993}," err",[1982,2466,1997],{"class":1993},[1982,2468,2469],{"class":1993}," pipeline",[1982,2471,2004],{"class":2003},[1982,2473,1326],{"class":2007},[1982,2475,2042],{"class":2003},[1982,2477,2059],{"class":1993},[1982,2479,2049],{"class":2003},[1982,2481,2482],{"class":1993}," order",[1982,2484,2142],{"class":2003},[1968,2486,90],{"id":2487},"installation",[1891,2489,2490],{},"Requires Go 1.24+",[1973,2492,2496],{"className":2493,"code":2494,"language":2495,"meta":24,"style":24},"language-bash shiki shiki-themes","go get github.com/zoobz-io/flume\n","bash",[1979,2497,2498],{"__ignoreMap":24},[1982,2499,2500,2502,2505],{"class":1984,"line":9},[1982,2501,1977],{"class":2007},[1982,2503,2504],{"class":2045}," get",[1982,2506,2507],{"class":2045}," github.com/zoobz-io/flume\n",[1968,2509,2511],{"id":2510},"quick-start","Quick Start",[1973,2513,2515],{"className":1975,"code":2514,"language":1977,"meta":24,"style":24},"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",[1979,2516,2517,2525,2529,2538,2543,2548,2553,2558,2562,2566,2578,2586,2594,2599,2603,2664,2668,2679,2698,2702,2707,2717,2764,2781,2802,2807,2817,2822,2862,2887,2894,2898,2903,2908,2914,2936,2941,2946,2951,2957,2964,2980,2994,3000,3005,3011,3064,3108],{"__ignoreMap":24},[1982,2518,2519,2522],{"class":1984,"line":9},[1982,2520,2521],{"class":2052},"package",[1982,2523,2524],{"class":2013}," main\n",[1982,2526,2527],{"class":1984,"line":19},[1982,2528,2361],{"emptyLinePlaceholder":2360},[1982,2530,2531,2534],{"class":1984,"line":30},[1982,2532,2533],{"class":2052},"import",[1982,2535,2537],{"class":2536},"soy-K"," (\n",[1982,2539,2540],{"class":1984,"line":2031},[1982,2541,2542],{"class":2045},"    \"context\"\n",[1982,2544,2545],{"class":1984,"line":2096},[1982,2546,2547],{"class":2045},"    \"fmt\"\n",[1982,2549,2550],{"class":1984,"line":2119},[1982,2551,2552],{"class":2045},"    \"github.com/zoobz-io/flume\"\n",[1982,2554,2555],{"class":1984,"line":2145},[1982,2556,2557],{"class":2045},"    \"github.com/zoobz-io/pipz\"\n",[1982,2559,2560],{"class":1984,"line":2151},[1982,2561,2142],{"class":2536},[1982,2563,2564],{"class":1984,"line":2164},[1982,2565,2361],{"emptyLinePlaceholder":2360},[1982,2567,2568,2571,2573,2576],{"class":1984,"line":2170},[1982,2569,2570],{"class":2052},"type",[1982,2572,2075],{"class":2013},[1982,2574,2575],{"class":2052}," struct",[1982,2577,2093],{"class":2003},[1982,2579,2580,2583],{"class":1984,"line":2218},[1982,2581,2582],{"class":2285},"    ID",[1982,2584,2585],{"class":2013},"    string\n",[1982,2587,2588,2591],{"class":1984,"line":2237},[1982,2589,2590],{"class":2285},"    Total",[1982,2592,2593],{"class":2013}," float64\n",[1982,2595,2596],{"class":1984,"line":2248},[1982,2597,2598],{"class":2003},"}\n",[1982,2600,2601],{"class":1984,"line":2253},[1982,2602,2361],{"emptyLinePlaceholder":2360},[1982,2604,2605,2608,2610,2613,2615,2617,2620,2623,2625,2627,2629,2631,2634,2637,2639,2641,2643,2645,2647,2650,2652,2654,2656,2658,2661],{"class":1984,"line":2258},[1982,2606,2607],{"class":2052},"func",[1982,2609,2081],{"class":2003},[1982,2611,2612],{"class":2058},"o ",[1982,2614,2014],{"class":2013},[1982,2616,2078],{"class":2003},[1982,2618,2619],{"class":2007}," Clone",[1982,2621,2622],{"class":2003},"()",[1982,2624,2075],{"class":2013},[1982,2626,2329],{"class":2003},[1982,2628,2332],{"class":2099},[1982,2630,2075],{"class":2013},[1982,2632,2633],{"class":2003},"{",[1982,2635,2636],{"class":2285},"ID",[1982,2638,2289],{"class":2003},[1982,2640,2072],{"class":1993},[1982,2642,2004],{"class":2003},[1982,2644,2636],{"class":1993},[1982,2646,2049],{"class":2003},[1982,2648,2649],{"class":2285}," Total",[1982,2651,2289],{"class":2003},[1982,2653,2072],{"class":1993},[1982,2655,2004],{"class":2003},[1982,2657,2107],{"class":1993},[1982,2659,2660],{"class":2003},"}",[1982,2662,2663],{"class":2003}," }\n",[1982,2665,2666],{"class":1984,"line":2282},[1982,2667,2361],{"emptyLinePlaceholder":2360},[1982,2669,2670,2672,2675,2677],{"class":1984,"line":2298},[1982,2671,2607],{"class":2052},[1982,2673,2674],{"class":2007}," main",[1982,2676,2622],{"class":2003},[1982,2678,2093],{"class":2003},[1982,2680,2681,2684,2686,2688,2690,2692,2694,2696],{"class":1984,"line":2351},[1982,2682,2683],{"class":1993},"    factory",[1982,2685,1997],{"class":1993},[1982,2687,2000],{"class":1993},[1982,2689,2004],{"class":2003},[1982,2691,1153],{"class":2007},[1982,2693,2010],{"class":2003},[1982,2695,2014],{"class":2013},[1982,2697,2017],{"class":2003},[1982,2699,2700],{"class":1984,"line":2357},[1982,2701,2361],{"emptyLinePlaceholder":2360},[1982,2703,2704],{"class":1984,"line":2364},[1982,2705,2706],{"class":1987},"    // Register processors\n",[1982,2708,2709,2711,2713,2715],{"class":1984,"line":2370},[1982,2710,2683],{"class":1993},[1982,2712,2004],{"class":2003},[1982,2714,1162],{"class":2007},[1982,2716,2028],{"class":2003},[1982,2718,2719,2722,2724,2726,2728,2730,2732,2734,2736,2738,2740,2742,2744,2746,2748,2750,2752,2754,2756,2758,2760,2762],{"class":1984,"line":2395},[1982,2720,2721],{"class":1993},"        pipz",[1982,2723,2004],{"class":2003},[1982,2725,2039],{"class":2007},[1982,2727,2042],{"class":2003},[1982,2729,2046],{"class":2045},[1982,2731,2049],{"class":2003},[1982,2733,2053],{"class":2052},[1982,2735,2042],{"class":2003},[1982,2737,2059],{"class":2058},[1982,2739,2062],{"class":2013},[1982,2741,2004],{"class":2003},[1982,2743,2067],{"class":2013},[1982,2745,2049],{"class":2003},[1982,2747,2072],{"class":2058},[1982,2749,2075],{"class":2013},[1982,2751,2078],{"class":2003},[1982,2753,2081],{"class":2003},[1982,2755,2014],{"class":2013},[1982,2757,2049],{"class":2003},[1982,2759,2088],{"class":2013},[1982,2761,2078],{"class":2003},[1982,2763,2093],{"class":2003},[1982,2765,2766,2769,2771,2773,2775,2777,2779],{"class":1984,"line":2401},[1982,2767,2768],{"class":2099},"            if",[1982,2770,2072],{"class":1993},[1982,2772,2004],{"class":2003},[1982,2774,2107],{"class":1993},[1982,2776,2110],{"class":2099},[1982,2778,2114],{"class":2113},[1982,2780,2093],{"class":2003},[1982,2782,2783,2786,2788,2790,2792,2794,2796,2798,2800],{"class":1984,"line":2407},[1982,2784,2785],{"class":2099},"                return",[1982,2787,2072],{"class":1993},[1982,2789,2049],{"class":2003},[1982,2791,2129],{"class":1993},[1982,2793,2004],{"class":2003},[1982,2795,2134],{"class":2007},[1982,2797,2042],{"class":2003},[1982,2799,2139],{"class":2045},[1982,2801,2142],{"class":2003},[1982,2803,2804],{"class":1984,"line":2413},[1982,2805,2806],{"class":2003},"            }\n",[1982,2808,2809,2811,2813,2815],{"class":1984,"line":2419},[1982,2810,2122],{"class":2099},[1982,2812,2072],{"class":1993},[1982,2814,2049],{"class":2003},[1982,2816,2161],{"class":2052},[1982,2818,2819],{"class":1984,"line":2425},[1982,2820,2821],{"class":2003},"        }),\n",[1982,2823,2824,2826,2828,2831,2833,2836,2838,2840,2842,2844,2846,2848,2850,2852,2854,2856,2858,2860],{"class":1984,"line":2431},[1982,2825,2721],{"class":1993},[1982,2827,2004],{"class":2003},[1982,2829,2830],{"class":2007},"Transform",[1982,2832,2042],{"class":2003},[1982,2834,2835],{"class":2045},"\"enrich\"",[1982,2837,2049],{"class":2003},[1982,2839,2053],{"class":2052},[1982,2841,2042],{"class":2003},[1982,2843,2059],{"class":2058},[1982,2845,2062],{"class":2013},[1982,2847,2004],{"class":2003},[1982,2849,2067],{"class":2013},[1982,2851,2049],{"class":2003},[1982,2853,2072],{"class":2058},[1982,2855,2075],{"class":2013},[1982,2857,2078],{"class":2003},[1982,2859,2075],{"class":2013},[1982,2861,2093],{"class":2003},[1982,2863,2864,2867,2869,2871,2874,2877,2880,2882,2884],{"class":1984,"line":2437},[1982,2865,2866],{"class":1993},"            o",[1982,2868,2004],{"class":2003},[1982,2870,2636],{"class":1993},[1982,2872,2873],{"class":1993}," =",[1982,2875,2876],{"class":2045}," \"ORD-\"",[1982,2878,2879],{"class":1993}," +",[1982,2881,2072],{"class":1993},[1982,2883,2004],{"class":2003},[1982,2885,2886],{"class":1993},"ID\n",[1982,2888,2889,2891],{"class":1984,"line":2445},[1982,2890,2122],{"class":2099},[1982,2892,2893],{"class":1993}," o\n",[1982,2895,2896],{"class":1984,"line":2450},[1982,2897,2821],{"class":2003},[1982,2899,2900],{"class":1984,"line":2456},[1982,2901,2902],{"class":2003},"    )\n",[1982,2904,2906],{"class":1984,"line":2905},33,[1982,2907,2361],{"emptyLinePlaceholder":2360},[1982,2909,2911],{"class":1984,"line":2910},34,[1982,2912,2913],{"class":1987},"    // Build pipeline from YAML\n",[1982,2915,2917,2920,2922,2924,2926,2928,2930,2932,2934],{"class":1984,"line":2916},35,[1982,2918,2919],{"class":1993},"    pipeline",[1982,2921,2049],{"class":2003},[1982,2923,2464],{"class":1993},[1982,2925,1997],{"class":1993},[1982,2927,2383],{"class":1993},[1982,2929,2004],{"class":2003},[1982,2931,1272],{"class":2007},[1982,2933,2042],{"class":2003},[1982,2935,2392],{"class":2045},[1982,2937,2939],{"class":1984,"line":2938},36,[1982,2940,2398],{"class":2045},[1982,2942,2944],{"class":1984,"line":2943},37,[1982,2945,2404],{"class":2045},[1982,2947,2949],{"class":1984,"line":2948},38,[1982,2950,2410],{"class":2045},[1982,2952,2954],{"class":1984,"line":2953},39,[1982,2955,2956],{"class":2045},"  - ref: enrich\n",[1982,2958,2960,2962],{"class":1984,"line":2959},40,[1982,2961,2440],{"class":2045},[1982,2963,2142],{"class":2003},[1982,2965,2967,2970,2972,2975,2978],{"class":1984,"line":2966},41,[1982,2968,2969],{"class":2099},"    if",[1982,2971,2464],{"class":1993},[1982,2973,2974],{"class":2099}," !=",[1982,2976,2977],{"class":2052}," nil",[1982,2979,2093],{"class":2003},[1982,2981,2983,2987,2989,2992],{"class":1984,"line":2982},42,[1982,2984,2986],{"class":2985},"skxcq","        panic",[1982,2988,2042],{"class":2003},[1982,2990,2991],{"class":1993},"err",[1982,2993,2142],{"class":2003},[1982,2995,2997],{"class":1984,"line":2996},43,[1982,2998,2999],{"class":2003},"    }\n",[1982,3001,3003],{"class":1984,"line":3002},44,[1982,3004,2361],{"emptyLinePlaceholder":2360},[1982,3006,3008],{"class":1984,"line":3007},45,[1982,3009,3010],{"class":1987},"    // Process\n",[1982,3012,3014,3017,3019,3021,3023,3025,3027,3029,3031,3034,3036,3039,3042,3044,3046,3048,3050,3053,3055,3057,3059,3062],{"class":1984,"line":3013},46,[1982,3015,3016],{"class":1993},"    result",[1982,3018,2049],{"class":2003},[1982,3020,2464],{"class":1993},[1982,3022,1997],{"class":1993},[1982,3024,2469],{"class":1993},[1982,3026,2004],{"class":2003},[1982,3028,1326],{"class":2007},[1982,3030,2042],{"class":2003},[1982,3032,3033],{"class":1993},"context",[1982,3035,2004],{"class":2003},[1982,3037,3038],{"class":2007},"Background",[1982,3040,3041],{"class":2003},"(),",[1982,3043,2075],{"class":2013},[1982,3045,2633],{"class":2003},[1982,3047,2636],{"class":2285},[1982,3049,2289],{"class":2003},[1982,3051,3052],{"class":2045}," \"123\"",[1982,3054,2049],{"class":2003},[1982,3056,2649],{"class":2285},[1982,3058,2289],{"class":2003},[1982,3060,3061],{"class":2113}," 99.99",[1982,3063,2354],{"class":2003},[1982,3065,3067,3070,3072,3075,3077,3080,3084,3087,3090,3094,3097,3099,3102,3104,3106],{"class":1984,"line":3066},47,[1982,3068,3069],{"class":1993},"    fmt",[1982,3071,2004],{"class":2003},[1982,3073,3074],{"class":2007},"Printf",[1982,3076,2042],{"class":2003},[1982,3078,3079],{"class":2045},"\"Result: ",[1982,3081,3083],{"class":3082},"scyPU","%+v",[1982,3085,3086],{"class":2045},", Error: ",[1982,3088,3089],{"class":3082},"%v",[1982,3091,3093],{"class":3092},"suWN2","\\n",[1982,3095,3096],{"class":2045},"\"",[1982,3098,2049],{"class":2003},[1982,3100,3101],{"class":1993}," result",[1982,3103,2049],{"class":2003},[1982,3105,2464],{"class":1993},[1982,3107,2142],{"class":2003},[1982,3109,3111],{"class":1984,"line":3110},48,[1982,3112,2598],{"class":2003},[1968,3114,38],{"id":3115},"capabilities",[3117,3118,3119,3135],"table",{},[3120,3121,3122],"thead",{},[3123,3124,3125,3129,3132],"tr",{},[3126,3127,3128],"th",{},"Feature",[3126,3130,3131],{},"Description",[3126,3133,3134],{},"Docs",[3136,3137,3138,3152,3164,3177,3190,3203],"tbody",{},[3123,3139,3140,3144,3147],{},[3141,3142,3143],"td",{},"Schema-Driven Construction",[3141,3145,3146],{},"Define pipelines in YAML/JSON, build at runtime",[3141,3148,3149],{},[1894,3150,1416],{"href":3151},"docs/reference/schema-format",[3123,3153,3154,3156,3159],{},[3141,3155,219],{},[3141,3157,3158],{},"Update pipeline behavior without restarts",[3141,3160,3161],{},[1894,3162,219],{"href":3163},"docs/guides/hot-reloading",[3123,3165,3166,3169,3172],{},[3141,3167,3168],{},"Lock-Free Bindings",[3141,3170,3171],{},"Concurrent-safe pipeline access with auto-sync",[3141,3173,3174],{},[1894,3175,1140],{"href":3176},"docs/reference/api",[3123,3178,3179,3182,3185],{},[3141,3180,3181],{},"Comprehensive Validation",[3141,3183,3184],{},"Schema validation with detailed error messages",[3141,3186,3187],{},[1894,3188,443],{"href":3189},"docs/guides/schema-design",[3123,3191,3192,3195,3198],{},[3141,3193,3194],{},"14 Connector Types",[3141,3196,3197],{},"Sequence, filter, retry, timeout, circuit breaker, and more",[3141,3199,3200],{},[1894,3201,1443],{"href":3202},"docs/reference/connector-types",[3123,3204,3205,3208,3211],{},[3141,3206,3207],{},"Event Emission",[3141,3209,3210],{},"Built-in observability signals",[3141,3212,3213],{},[1894,3214,666],{"href":3215},"docs/guides/observability",[1968,3217,3219],{"id":3218},"why-flume","Why Flume?",[3221,3222,3223,3231,3237,3243,3249,3261],"ul",{},[3224,3225,3226,3230],"li",{},[3227,3228,3229],"strong",{},"Schema-driven",": Define pipelines in YAML/JSON, not code",[3224,3232,3233,3236],{},[3227,3234,3235],{},"Hot-reloadable",": Update pipeline behavior without restarts",[3224,3238,3239,3242],{},[3227,3240,3241],{},"Type-safe",": Full generics support with compile-time safety",[3224,3244,3245,3248],{},[3227,3246,3247],{},"Composable",": Build complex flows from simple, tested components",[3224,3250,3251,3254,3255,3260],{},[3227,3252,3253],{},"Observable",": Built-in ",[1894,3256,3259],{"href":3257,"rel":3258},"https://github.com/zoobz-io/capitan",[1898],"capitan"," event emission",[3224,3262,3263,3266],{},[3227,3264,3265],{},"Validated",": Comprehensive schema validation with detailed error messages",[1968,3268,3270],{"id":3269},"configuration-as-code","Configuration as Code",[1891,3272,3273,3274,2004],{},"Flume enables a pattern: ",[3227,3275,3276],{},"define once, reconfigure anywhere",[1891,3278,3279],{},"Register your processing components at startup. Define pipeline structure in configuration files. Update behavior at runtime without redeployment.",[1973,3281,3283],{"className":1975,"code":3282,"language":1977,"meta":24,"style":24},"// 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",[1979,3284,3285,3290,3320,3324,3329,3355,3359,3364],{"__ignoreMap":24},[1982,3286,3287],{"class":1984,"line":9},[1982,3288,3289],{"class":1987},"// Components registered once\n",[1982,3291,3292,3294,3296,3298,3300,3303,3305,3308,3310,3313,3315,3318],{"class":1984,"line":19},[1982,3293,1994],{"class":1993},[1982,3295,2004],{"class":2003},[1982,3297,1162],{"class":2007},[1982,3299,2042],{"class":2003},[1982,3301,3302],{"class":1993},"validate",[1982,3304,2049],{"class":2003},[1982,3306,3307],{"class":1993}," enrich",[1982,3309,2049],{"class":2003},[1982,3311,3312],{"class":1993}," notify",[1982,3314,2049],{"class":2003},[1982,3316,3317],{"class":1993}," discount",[1982,3319,2142],{"class":2003},[1982,3321,3322],{"class":1984,"line":30},[1982,3323,2361],{"emptyLinePlaceholder":2360},[1982,3325,3326],{"class":1984,"line":2031},[1982,3327,3328],{"class":1987},"// Structure defined in config\n",[1982,3330,3331,3333,3335,3337,3339,3342,3344,3347,3349,3352],{"class":1984,"line":2096},[1982,3332,1994],{"class":1993},[1982,3334,2004],{"class":2003},[1982,3336,1291],{"class":2007},[1982,3338,2042],{"class":2003},[1982,3340,3341],{"class":2045},"\"checkout\"",[1982,3343,2049],{"class":2003},[1982,3345,3346],{"class":2007}," loadYAML",[1982,3348,2042],{"class":2003},[1982,3350,3351],{"class":2045},"\"pipelines/checkout.yaml\"",[1982,3353,3354],{"class":2003},"))\n",[1982,3356,3357],{"class":1984,"line":2119},[1982,3358,2361],{"emptyLinePlaceholder":2360},[1982,3360,3361],{"class":1984,"line":2145},[1982,3362,3363],{"class":1987},"// Behavior changes without restart\n",[1982,3365,3366,3368,3370,3372,3374,3376,3378,3380,3382,3385],{"class":1984,"line":2151},[1982,3367,1994],{"class":1993},[1982,3369,2004],{"class":2003},[1982,3371,1291],{"class":2007},[1982,3373,2042],{"class":2003},[1982,3375,3341],{"class":2045},[1982,3377,2049],{"class":2003},[1982,3379,3346],{"class":2007},[1982,3381,2042],{"class":2003},[1982,3383,3384],{"class":2045},"\"pipelines/checkout-v2.yaml\"",[1982,3386,3354],{"class":2003},[1891,3388,3389,3390,3394,3395,3398],{},"The code defines ",[3391,3392,3393],"em",{},"what"," processors do. Configuration defines ",[3391,3396,3397],{},"how"," they combine.",[1968,3400,219],{"id":3401},"hot-reloading",[1891,3403,3404],{},"Update pipelines at runtime without restarts:",[1973,3406,3408],{"className":1975,"code":3407,"language":1977,"meta":24,"style":24},"// 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",[1979,3409,3410,3415,3435,3439,3444,3482,3486,3491,3518,3522,3527],{"__ignoreMap":24},[1982,3411,3412],{"class":1984,"line":9},[1982,3413,3414],{"class":1987},"// Register a named schema\n",[1982,3416,3417,3419,3421,3423,3425,3428,3430,3433],{"class":1984,"line":19},[1982,3418,1994],{"class":1993},[1982,3420,2004],{"class":2003},[1982,3422,1291],{"class":2007},[1982,3424,2042],{"class":2003},[1982,3426,3427],{"class":2045},"\"order-pipeline\"",[1982,3429,2049],{"class":2003},[1982,3431,3432],{"class":1993}," schema",[1982,3434,2142],{"class":2003},[1982,3436,3437],{"class":1984,"line":30},[1982,3438,2361],{"emptyLinePlaceholder":2360},[1982,3440,3441],{"class":1984,"line":2031},[1982,3442,3443],{"class":1987},"// Create a binding with auto-sync enabled\n",[1982,3445,3446,3449,3451,3453,3455,3457,3459,3461,3463,3466,3468,3471,3473,3475,3477,3479],{"class":1984,"line":2096},[1982,3447,3448],{"class":1993},"binding",[1982,3450,2049],{"class":2003},[1982,3452,2378],{"class":1993},[1982,3454,1997],{"class":1993},[1982,3456,2383],{"class":1993},[1982,3458,2004],{"class":2003},[1982,3460,1311],{"class":2007},[1982,3462,2042],{"class":2003},[1982,3464,3465],{"class":1993},"pipelineID",[1982,3467,2049],{"class":2003},[1982,3469,3470],{"class":2045}," \"order-pipeline\"",[1982,3472,2049],{"class":2003},[1982,3474,2000],{"class":1993},[1982,3476,2004],{"class":2003},[1982,3478,1331],{"class":2007},[1982,3480,3481],{"class":2003},"())\n",[1982,3483,3484],{"class":1984,"line":2119},[1982,3485,2361],{"emptyLinePlaceholder":2360},[1982,3487,3488],{"class":1984,"line":2145},[1982,3489,3490],{"class":1987},"// Process requests (lock-free)\n",[1982,3492,3493,3495,3497,3499,3501,3504,3506,3508,3510,3512,3514,3516],{"class":1984,"line":2151},[1982,3494,2459],{"class":1993},[1982,3496,2049],{"class":2003},[1982,3498,2378],{"class":1993},[1982,3500,1997],{"class":1993},[1982,3502,3503],{"class":1993}," binding",[1982,3505,2004],{"class":2003},[1982,3507,1326],{"class":2007},[1982,3509,2042],{"class":2003},[1982,3511,2059],{"class":1993},[1982,3513,2049],{"class":2003},[1982,3515,2482],{"class":1993},[1982,3517,2142],{"class":2003},[1982,3519,3520],{"class":1984,"line":2164},[1982,3521,2361],{"emptyLinePlaceholder":2360},[1982,3523,3524],{"class":1984,"line":2170},[1982,3525,3526],{"class":1987},"// Update schema - all auto-sync bindings rebuild automatically\n",[1982,3528,3529,3531,3533,3535,3537,3539,3541,3544],{"class":1984,"line":2218},[1982,3530,1994],{"class":1993},[1982,3532,2004],{"class":2003},[1982,3534,1291],{"class":2007},[1982,3536,2042],{"class":2003},[1982,3538,3427],{"class":2045},[1982,3540,2049],{"class":2003},[1982,3542,3543],{"class":1993}," newSchema",[1982,3545,2142],{"class":2003},[1968,3547,62],{"id":3548},"documentation",[1891,3550,3551,3552,3555],{},"Full documentation is available in the ",[1894,3553,3554],{"href":3554},"docs/"," directory:",[3557,3558,66],"h3",{"id":3559},"learn",[3221,3561,3562,3568,3574,3580],{},[3224,3563,3564,3567],{},[1894,3565,81],{"href":3566},"docs/learn/quickstart"," — Your first pipeline in 5 minutes",[3224,3569,3570,3573],{},[1894,3571,155],{"href":3572},"docs/learn/core-concepts"," — Factories, schemas, and components",[3224,3575,3576,3579],{},[1894,3577,16],{"href":3578},"docs/learn/architecture"," — How Flume works under the hood",[3224,3581,3582,3585],{},[1894,3583,209],{"href":3584},"docs/learn/building-pipelines"," — From simple to complex",[3557,3587,71],{"id":3588},"guides",[3221,3590,3591,3596,3601,3607,3613],{},[3224,3592,3593,3595],{},[1894,3594,443],{"href":3189}," — Best practices for schema structure",[3224,3597,3598,3600],{},[1894,3599,219],{"href":3163}," — Runtime pipeline updates",[3224,3602,3603,3606],{},[1894,3604,363],{"href":3605},"docs/guides/error-handling"," — Retry, fallback, circuit breakers",[3224,3608,3609,3612],{},[1894,3610,879],{"href":3611},"docs/guides/testing"," — Testing strategies and CI/CD linting",[3224,3614,3615,3617],{},[1894,3616,666],{"href":3215}," — Monitoring with capitan events",[3557,3619,1834],{"id":3620},"cookbook",[3221,3622,3623],{},[3224,3624,3625,3628],{},[1894,3626,1096],{"href":3627},"docs/cookbook/common-patterns"," — Recipes and patterns",[3557,3630,76],{"id":3631},"reference",[3221,3633,3634,3639,3644,3649],{},[3224,3635,3636,3638],{},[1894,3637,1140],{"href":3176}," — Complete API documentation",[3224,3640,3641,3643],{},[1894,3642,1416],{"href":3151}," — YAML/JSON specification",[3224,3645,3646,3648],{},[1894,3647,1443],{"href":3202}," — All 14 connectors",[3224,3650,3651,3654],{},[1894,3652,1642],{"href":3653},"docs/reference/events"," — Observability signals",[1968,3656,3658],{"id":3657},"contributing","Contributing",[1891,3660,3661,3662,3666],{},"See ",[1894,3663,3665],{"href":3664},"CONTRIBUTING","CONTRIBUTING.md"," for development guidelines.",[1968,3668,1941],{"id":3669},"license",[1891,3671,3672,3673,3675],{},"MIT License - see ",[1894,3674,1938],{"href":1938}," file.",[3677,3678,3679],"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":24,"searchDepth":19,"depth":19,"links":3681},[3682,3683,3684,3685,3686,3687,3688,3689,3695,3696],{"id":1970,"depth":19,"text":1971},{"id":2487,"depth":19,"text":90},{"id":2510,"depth":19,"text":2511},{"id":3115,"depth":19,"text":38},{"id":3218,"depth":19,"text":3219},{"id":3269,"depth":19,"text":3270},{"id":3401,"depth":19,"text":219},{"id":3548,"depth":19,"text":62,"children":3690},[3691,3692,3693,3694],{"id":3559,"depth":30,"text":66},{"id":3588,"depth":30,"text":71},{"id":3620,"depth":30,"text":1834},{"id":3631,"depth":30,"text":76},{"id":3657,"depth":19,"text":3658},{"id":3669,"depth":19,"text":1941},"md","book-open",{},"/readme",{"title":1881,"description":24},"readme","LjAqx_lMY-Zlq3kuqe9-dcIyrawIt1pBffmeMtv78rE",{"id":3705,"title":3706,"body":3707,"description":24,"extension":3697,"icon":4146,"meta":4147,"navigation":2360,"path":4148,"seo":4149,"stem":4150,"__hash__":4151},"resources/security.md","Security",{"type":1883,"value":3708,"toc":4132},[3709,3713,3717,3720,3759,3763,3766,3770,3775,3778,3817,3821,3824,3873,3877,3903,3907,3910,3914,3917,4012,4016,4019,4054,4058,4061,4090,4094,4108,4112,4115,4120,4123,4129],[1886,3710,3712],{"id":3711},"security-policy","Security Policy",[1968,3714,3716],{"id":3715},"supported-versions","Supported Versions",[1891,3718,3719],{},"We release patches for security vulnerabilities. Which versions are eligible for receiving such patches depends on the CVSS v3.0 Rating:",[3117,3721,3722,3735],{},[3120,3723,3724],{},[3123,3725,3726,3729,3732],{},[3126,3727,3728],{},"Version",[3126,3730,3731],{},"Supported",[3126,3733,3734],{},"Status",[3136,3736,3737,3748],{},[3123,3738,3739,3742,3745],{},[3141,3740,3741],{},"latest",[3141,3743,3744],{},"✅",[3141,3746,3747],{},"Active development",[3123,3749,3750,3753,3756],{},[3141,3751,3752],{},"\u003C latest",[3141,3754,3755],{},"❌",[3141,3757,3758],{},"Security fixes only for critical issues",[1968,3760,3762],{"id":3761},"reporting-a-vulnerability","Reporting a Vulnerability",[1891,3764,3765],{},"We take the security of flume seriously. If you have discovered a security vulnerability in this project, please report it responsibly.",[3557,3767,3769],{"id":3768},"how-to-report","How to Report",[1891,3771,3772],{},[3227,3773,3774],{},"Please DO NOT report security vulnerabilities through public GitHub issues.",[1891,3776,3777],{},"Instead, please report them via one of the following methods:",[3779,3780,3781,3804],"ol",{},[3224,3782,3783,3786,3787],{},[3227,3784,3785],{},"GitHub Security Advisories"," (Preferred)",[3221,3788,3789,3798,3801],{},[3224,3790,3791,3792,3797],{},"Go to the ",[1894,3793,3796],{"href":3794,"rel":3795},"https://github.com/zoobz-io/flume/security",[1898],"Security tab"," of this repository",[3224,3799,3800],{},"Click \"Report a vulnerability\"",[3224,3802,3803],{},"Fill out the form with details about the vulnerability",[3224,3805,3806,3809],{},[3227,3807,3808],{},"Email",[3221,3810,3811,3814],{},[3224,3812,3813],{},"Send details to the repository maintainer through GitHub profile contact information",[3224,3815,3816],{},"Use PGP encryption if possible for sensitive details",[3557,3818,3820],{"id":3819},"what-to-include","What to Include",[1891,3822,3823],{},"Please include the following information (as much as you can provide) to help us better understand the nature and scope of the possible issue:",[3221,3825,3826,3832,3838,3844,3850,3855,3861,3867],{},[3224,3827,3828,3831],{},[3227,3829,3830],{},"Type of issue"," (e.g., race condition, schema injection, validation bypass, etc.)",[3224,3833,3834,3837],{},[3227,3835,3836],{},"Full paths of source file(s)"," related to the manifestation of the issue",[3224,3839,3840,3843],{},[3227,3841,3842],{},"The location of the affected source code"," (tag/branch/commit or direct URL)",[3224,3845,3846,3849],{},[3227,3847,3848],{},"Any special configuration required"," to reproduce the issue",[3224,3851,3852,3849],{},[3227,3853,3854],{},"Step-by-step instructions",[3224,3856,3857,3860],{},[3227,3858,3859],{},"Proof-of-concept or exploit code"," (if possible)",[3224,3862,3863,3866],{},[3227,3864,3865],{},"Impact of the issue",", including how an attacker might exploit the issue",[3224,3868,3869,3872],{},[3227,3870,3871],{},"Your name and affiliation"," (optional)",[3557,3874,3876],{"id":3875},"what-to-expect","What to Expect",[3221,3878,3879,3885,3891,3897],{},[3224,3880,3881,3884],{},[3227,3882,3883],{},"Acknowledgment",": We will acknowledge receipt of your vulnerability report within 48 hours",[3224,3886,3887,3890],{},[3227,3888,3889],{},"Initial Assessment",": Within 7 days, we will provide an initial assessment of the report",[3224,3892,3893,3896],{},[3227,3894,3895],{},"Resolution Timeline",": We aim to resolve critical issues within 30 days",[3224,3898,3899,3902],{},[3227,3900,3901],{},"Disclosure",": We will coordinate with you on the disclosure timeline",[3557,3904,3906],{"id":3905},"preferred-languages","Preferred Languages",[1891,3908,3909],{},"We prefer all communications to be in English.",[1968,3911,3913],{"id":3912},"security-best-practices","Security Best Practices",[1891,3915,3916],{},"When using flume in your applications, we recommend:",[3779,3918,3919,3940,3960,3976,3992],{},[3224,3920,3921,3924],{},[3227,3922,3923],{},"Keep Dependencies Updated",[1973,3925,3927],{"className":2493,"code":3926,"language":2495,"meta":24,"style":24},"go get -u github.com/zoobz-io/flume\n",[1979,3928,3929],{"__ignoreMap":24},[1982,3930,3931,3933,3935,3938],{"class":1984,"line":9},[1982,3932,1977],{"class":2007},[1982,3934,2504],{"class":2045},[1982,3936,3937],{"class":2052}," -u",[1982,3939,2507],{"class":2045},[3224,3941,3942,3944],{},[3227,3943,1660],{},[3221,3945,3946,3951,3957],{},[3224,3947,3948,3949],{},"Always validate schemas before deployment using ",[1979,3950,1349],{},[3224,3952,3953,3954,3956],{},"Use ",[1979,3955,1344],{}," at runtime with a configured factory",[3224,3958,3959],{},"Don't load schemas from untrusted sources without validation",[3224,3961,3962,3965],{},[3227,3963,3964],{},"Hot Reload Security",[3221,3966,3967,3970,3973],{},[3224,3968,3969],{},"Secure the source of schema updates (e.g., authenticated API endpoints)",[3224,3971,3972],{},"Log all schema changes for audit purposes",[3224,3974,3975],{},"Consider schema versioning for rollback capability",[3224,3977,3978,3981],{},[3227,3979,3980],{},"Resource Management",[3221,3982,3983,3986,3989],{},[3224,3984,3985],{},"Close channels when no longer needed",[3224,3987,3988],{},"Set appropriate timeouts for pipeline operations",[3224,3990,3991],{},"Configure circuit breakers for external dependencies",[3224,3993,3994,3997],{},[3227,3995,3996],{},"Concurrency Safety",[3221,3998,3999,4006,4009],{},[3224,4000,4001,4002,4005],{},"Ensure your data type's ",[1979,4003,4004],{},"Clone()"," method creates deep copies",[3224,4007,4008],{},"Don't share mutable state across processors without synchronization",[3224,4010,4011],{},"Be aware that concurrent/race nodes run in parallel",[1968,4013,4015],{"id":4014},"security-features","Security Features",[1891,4017,4018],{},"flume includes several built-in security features:",[3221,4020,4021,4026,4031,4037,4042,4048],{},[3224,4022,4023,4025],{},[3227,4024,47],{},": Go generics ensure compile-time type checking",[3224,4027,4028,4030],{},[3227,4029,1660],{},": Comprehensive validation catches errors before building",[3224,4032,4033,4036],{},[3227,4034,4035],{},"Reference Validation",": All processor/predicate/condition references verified",[3224,4038,4039,4041],{},[3227,4040,264],{},": Atomic operations for hot-reload scenarios",[3224,4043,4044,4047],{},[3227,4045,4046],{},"Timeout Enforcement",": Built-in timeout connector prevents runaway operations",[3224,4049,4050,4053],{},[3227,4051,4052],{},"Circuit Breakers",": Built-in circuit breaker pattern for fault isolation",[1968,4055,4057],{"id":4056},"automated-security-scanning","Automated Security Scanning",[1891,4059,4060],{},"This project uses:",[3221,4062,4063,4068,4074,4080],{},[3224,4064,4065,4067],{},[3227,4066,1926],{},": GitHub's semantic code analysis for security vulnerabilities",[3224,4069,4070,4073],{},[3227,4071,4072],{},"golangci-lint",": Static analysis including security linters (gosec)",[3224,4075,4076,4079],{},[3227,4077,4078],{},"Codecov",": Coverage tracking to ensure security-critical code is tested",[3224,4081,4082,4085,4086,4089],{},[3227,4083,4084],{},"Race Detection",": Tests run with ",[1979,4087,4088],{},"-race"," flag to detect data races",[1968,4091,4093],{"id":4092},"vulnerability-disclosure-policy","Vulnerability Disclosure Policy",[3221,4095,4096,4099,4102,4105],{},[3224,4097,4098],{},"Security vulnerabilities will be disclosed via GitHub Security Advisories",[3224,4100,4101],{},"We follow a 90-day disclosure timeline for non-critical issues",[3224,4103,4104],{},"Critical vulnerabilities may be disclosed sooner after patches are available",[3224,4106,4107],{},"We will credit reporters who follow responsible disclosure practices",[1968,4109,4111],{"id":4110},"credits","Credits",[1891,4113,4114],{},"We thank the following individuals for responsibly disclosing security issues:",[1891,4116,4117],{},[3391,4118,4119],{},"This list is currently empty. Be the first to help improve our security!",[4121,4122],"hr",{},[1891,4124,4125,4128],{},[3227,4126,4127],{},"Last Updated",": 2025-12-12",[3677,4130,4131],{},"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":24,"searchDepth":19,"depth":19,"links":4133},[4134,4135,4141,4142,4143,4144,4145],{"id":3715,"depth":19,"text":3716},{"id":3761,"depth":19,"text":3762,"children":4136},[4137,4138,4139,4140],{"id":3768,"depth":30,"text":3769},{"id":3819,"depth":30,"text":3820},{"id":3875,"depth":30,"text":3876},{"id":3905,"depth":30,"text":3906},{"id":3912,"depth":19,"text":3913},{"id":4014,"depth":19,"text":4015},{"id":4056,"depth":19,"text":4057},{"id":4092,"depth":19,"text":4093},{"id":4110,"depth":19,"text":4111},"shield",{},"/security",{"title":3706,"description":24},"security","8Hgch7Pp-e-NyfBxgZdJF8RyzhItCJT0gGPopLjI8Wk",{"id":4153,"title":3658,"body":4154,"description":4162,"extension":3697,"icon":1979,"meta":4727,"navigation":2360,"path":4728,"seo":4729,"stem":3657,"__hash__":4730},"resources/contributing.md",{"type":1883,"value":4155,"toc":4702},[4156,4160,4163,4167,4170,4174,4212,4216,4220,4238,4241,4257,4259,4270,4274,4278,4292,4296,4307,4311,4316,4319,4336,4340,4343,4360,4364,4367,4381,4385,4413,4416,4419,4434,4437,4453,4456,4472,4475,4488,4492,4500,4504,4507,4551,4555,4559,4562,4573,4576,4590,4594,4597,4625,4629,4657,4663,4667,4670,4681,4685,4696,4699],[1886,4157,4159],{"id":4158},"contributing-to-flume","Contributing to flume",[1891,4161,4162],{},"Thank you for your interest in contributing to flume! This guide will help you get started.",[1968,4164,4166],{"id":4165},"code-of-conduct","Code of Conduct",[1891,4168,4169],{},"By participating in this project, you agree to maintain a respectful and inclusive environment for all contributors.",[1968,4171,4173],{"id":4172},"getting-started","Getting Started",[3779,4175,4176,4179,4185,4191,4194,4200,4203,4209],{},[3224,4177,4178],{},"Fork the repository",[3224,4180,4181,4182],{},"Clone your fork: ",[1979,4183,4184],{},"git clone https://github.com/yourusername/flume.git",[3224,4186,4187,4188],{},"Create a feature branch: ",[1979,4189,4190],{},"git checkout -b feature/your-feature-name",[3224,4192,4193],{},"Make your changes",[3224,4195,4196,4197],{},"Run tests: ",[1979,4198,4199],{},"go test ./...",[3224,4201,4202],{},"Commit your changes with a descriptive message",[3224,4204,4205,4206],{},"Push to your fork: ",[1979,4207,4208],{},"git push origin feature/your-feature-name",[3224,4210,4211],{},"Create a Pull Request",[1968,4213,4215],{"id":4214},"development-guidelines","Development Guidelines",[3557,4217,4219],{"id":4218},"code-style","Code Style",[3221,4221,4222,4225,4232,4235],{},[3224,4223,4224],{},"Follow standard Go conventions",[3224,4226,4227,4228,4231],{},"Run ",[1979,4229,4230],{},"go fmt"," before committing",[3224,4233,4234],{},"Add comments for exported functions and types",[3224,4236,4237],{},"Keep functions small and focused",[3557,4239,879],{"id":4240},"testing",[3221,4242,4243,4246,4251,4254],{},[3224,4244,4245],{},"Write tests for new functionality",[3224,4247,4248,4249],{},"Ensure all tests pass: ",[1979,4250,4199],{},[3224,4252,4253],{},"Include benchmarks for performance-critical code",[3224,4255,4256],{},"Aim for good test coverage",[3557,4258,62],{"id":3548},[3221,4260,4261,4264,4267],{},[3224,4262,4263],{},"Update documentation for API changes",[3224,4265,4266],{},"Add examples for new features",[3224,4268,4269],{},"Keep doc comments clear and concise",[1968,4271,4273],{"id":4272},"types-of-contributions","Types of Contributions",[3557,4275,4277],{"id":4276},"bug-reports","Bug Reports",[3221,4279,4280,4283,4286,4289],{},[3224,4281,4282],{},"Use GitHub Issues",[3224,4284,4285],{},"Include minimal reproduction code",[3224,4287,4288],{},"Describe expected vs actual behavior",[3224,4290,4291],{},"Include Go version and OS",[3557,4293,4295],{"id":4294},"feature-requests","Feature Requests",[3221,4297,4298,4301,4304],{},[3224,4299,4300],{},"Open an issue for discussion first",[3224,4302,4303],{},"Explain the use case",[3224,4305,4306],{},"Consider backwards compatibility",[3557,4308,4310],{"id":4309},"code-contributions","Code Contributions",[4312,4313,4315],"h4",{"id":4314},"adding-processors","Adding Processors",[1891,4317,4318],{},"New processor builders should:",[3221,4320,4321,4327,4330,4333],{},[3224,4322,4323,4324],{},"Follow the existing pattern in ",[1979,4325,4326],{},"builders.go",[3224,4328,4329],{},"Include comprehensive tests",[3224,4331,4332],{},"Add documentation with examples",[3224,4334,4335],{},"Update schema validation if needed",[4312,4337,4339],{"id":4338},"adding-schema-features","Adding Schema Features",[1891,4341,4342],{},"New schema features should:",[3221,4344,4345,4351,4354,4357],{},[3224,4346,4347,4348,4350],{},"Extend the ",[1979,4349,1363],{}," type appropriately",[3224,4352,4353],{},"Include validation rules",[3224,4355,4356],{},"Add builder support",[3224,4358,4359],{},"Document the YAML/JSON format",[4312,4361,4363],{"id":4362},"examples","Examples",[1891,4365,4366],{},"New examples should:",[3221,4368,4369,4372,4375,4378],{},[3224,4370,4371],{},"Solve a real-world problem",[3224,4373,4374],{},"Include tests",[3224,4376,4377],{},"Have clear documentation",[3224,4379,4380],{},"Follow the existing structure",[1968,4382,4384],{"id":4383},"pull-request-process","Pull Request Process",[3779,4386,4387,4393,4398,4403,4408],{},[3224,4388,4389,4392],{},[3227,4390,4391],{},"Keep PRs focused"," - One feature/fix per PR",[3224,4394,4395],{},[3227,4396,4397],{},"Write descriptive commit messages",[3224,4399,4400],{},[3227,4401,4402],{},"Update tests and documentation",[3224,4404,4405],{},[3227,4406,4407],{},"Ensure CI passes",[3224,4409,4410],{},[3227,4411,4412],{},"Respond to review feedback",[1968,4414,879],{"id":4415},"testing-1",[1891,4417,4418],{},"Run the full test suite:",[1973,4420,4422],{"className":2493,"code":4421,"language":2495,"meta":24,"style":24},"go test ./...\n",[1979,4423,4424],{"__ignoreMap":24},[1982,4425,4426,4428,4431],{"class":1984,"line":9},[1982,4427,1977],{"class":2007},[1982,4429,4430],{"class":2045}," test",[1982,4432,4433],{"class":2045}," ./...\n",[1891,4435,4436],{},"Run with race detection:",[1973,4438,4440],{"className":2493,"code":4439,"language":2495,"meta":24,"style":24},"go test -race ./...\n",[1979,4441,4442],{"__ignoreMap":24},[1982,4443,4444,4446,4448,4451],{"class":1984,"line":9},[1982,4445,1977],{"class":2007},[1982,4447,4430],{"class":2045},[1982,4449,4450],{"class":2052}," -race",[1982,4452,4433],{"class":2045},[1891,4454,4455],{},"Run benchmarks:",[1973,4457,4459],{"className":2493,"code":4458,"language":2495,"meta":24,"style":24},"go test -bench=. ./...\n",[1979,4460,4461],{"__ignoreMap":24},[1982,4462,4463,4465,4467,4470],{"class":1984,"line":9},[1982,4464,1977],{"class":2007},[1982,4466,4430],{"class":2045},[1982,4468,4469],{"class":2052}," -bench=.",[1982,4471,4433],{"class":2045},[1891,4473,4474],{},"Run linter:",[1973,4476,4478],{"className":2493,"code":4477,"language":2495,"meta":24,"style":24},"make lint\n",[1979,4479,4480],{"__ignoreMap":24},[1982,4481,4482,4485],{"class":1984,"line":9},[1982,4483,4484],{"class":2007},"make",[1982,4486,4487],{"class":2045}," lint\n",[1968,4489,4491],{"id":4490},"project-structure","Project Structure",[1973,4493,4498],{"className":4494,"code":4496,"language":4497},[4495],"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",[1979,4499,4496],{"__ignoreMap":24},[1968,4501,4503],{"id":4502},"commit-messages","Commit Messages",[1891,4505,4506],{},"Follow conventional commits:",[3221,4508,4509,4515,4521,4527,4533,4539,4545],{},[3224,4510,4511,4514],{},[1979,4512,4513],{},"feat:"," New feature",[3224,4516,4517,4520],{},[1979,4518,4519],{},"fix:"," Bug fix",[3224,4522,4523,4526],{},[1979,4524,4525],{},"docs:"," Documentation changes",[3224,4528,4529,4532],{},[1979,4530,4531],{},"test:"," Test additions/changes",[3224,4534,4535,4538],{},[1979,4536,4537],{},"refactor:"," Code refactoring",[3224,4540,4541,4544],{},[1979,4542,4543],{},"perf:"," Performance improvements",[3224,4546,4547,4550],{},[1979,4548,4549],{},"chore:"," Maintenance tasks",[1968,4552,4554],{"id":4553},"release-process","Release Process",[3557,4556,4558],{"id":4557},"automated-releases","Automated Releases",[1891,4560,4561],{},"This project uses automated release versioning. To create a release:",[3779,4563,4564,4567,4570],{},[3224,4565,4566],{},"Go to Actions -> Release -> Run workflow",[3224,4568,4569],{},"Leave \"Version override\" empty for automatic version inference",[3224,4571,4572],{},"Click \"Run workflow\"",[1891,4574,4575],{},"The system will:",[3221,4577,4578,4581,4584,4587],{},[3224,4579,4580],{},"Automatically determine the next version from conventional commits",[3224,4582,4583],{},"Create a git tag",[3224,4585,4586],{},"Generate release notes via GoReleaser",[3224,4588,4589],{},"Publish the release to GitHub",[3557,4591,4593],{"id":4592},"manual-release-legacy","Manual Release (Legacy)",[1891,4595,4596],{},"You can still create releases manually:",[1973,4598,4600],{"className":2493,"code":4599,"language":2495,"meta":24,"style":24},"git tag v1.2.3\ngit push origin v1.2.3\n",[1979,4601,4602,4613],{"__ignoreMap":24},[1982,4603,4604,4607,4610],{"class":1984,"line":9},[1982,4605,4606],{"class":2007},"git",[1982,4608,4609],{"class":2045}," tag",[1982,4611,4612],{"class":2045}," v1.2.3\n",[1982,4614,4615,4617,4620,4623],{"class":1984,"line":19},[1982,4616,4606],{"class":2007},[1982,4618,4619],{"class":2045}," push",[1982,4621,4622],{"class":2045}," origin",[1982,4624,4612],{"class":2045},[3557,4626,4628],{"id":4627},"commit-conventions-for-versioning","Commit Conventions for Versioning",[3221,4630,4631,4636,4641,4647],{},[3224,4632,4633,4635],{},[1979,4634,4513],{}," new features (minor version: 1.2.0 -> 1.3.0)",[3224,4637,4638,4640],{},[1979,4639,4519],{}," bug fixes (patch version: 1.2.0 -> 1.2.1)",[3224,4642,4643,4646],{},[1979,4644,4645],{},"feat!:"," breaking changes (major version: 1.2.0 -> 2.0.0)",[3224,4648,4649,4651,4652,4651,4654,4656],{},[1979,4650,4525],{},", ",[1979,4653,4531],{},[1979,4655,4549],{}," no version change",[1891,4658,4659,4660],{},"Example: ",[1979,4661,4662],{},"feat(schema): add support for custom connector types",[3557,4664,4666],{"id":4665},"version-preview-on-pull-requests","Version Preview on Pull Requests",[1891,4668,4669],{},"Every PR automatically shows the next version that will be created:",[3221,4671,4672,4675,4678],{},[3224,4673,4674],{},"Check PR comments for \"Version Preview\"",[3224,4676,4677],{},"Updates automatically as you add commits",[3224,4679,4680],{},"Helps verify your commits have the intended effect",[1968,4682,4684],{"id":4683},"questions","Questions?",[3221,4686,4687,4690,4693],{},[3224,4688,4689],{},"Open an issue for questions",[3224,4691,4692],{},"Check existing issues first",[3224,4694,4695],{},"Be patient and respectful",[1891,4697,4698],{},"Thank you for contributing to flume!",[3677,4700,4701],{},"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":24,"searchDepth":19,"depth":19,"links":4703},[4704,4705,4706,4711,4716,4717,4718,4719,4720,4726],{"id":4165,"depth":19,"text":4166},{"id":4172,"depth":19,"text":4173},{"id":4214,"depth":19,"text":4215,"children":4707},[4708,4709,4710],{"id":4218,"depth":30,"text":4219},{"id":4240,"depth":30,"text":879},{"id":3548,"depth":30,"text":62},{"id":4272,"depth":19,"text":4273,"children":4712},[4713,4714,4715],{"id":4276,"depth":30,"text":4277},{"id":4294,"depth":30,"text":4295},{"id":4309,"depth":30,"text":4310},{"id":4383,"depth":19,"text":4384},{"id":4415,"depth":19,"text":879},{"id":4490,"depth":19,"text":4491},{"id":4502,"depth":19,"text":4503},{"id":4553,"depth":19,"text":4554,"children":4721},[4722,4723,4724,4725],{"id":4557,"depth":30,"text":4558},{"id":4592,"depth":30,"text":4593},{"id":4627,"depth":30,"text":4628},{"id":4665,"depth":30,"text":4666},{"id":4683,"depth":19,"text":4684},{},"/contributing",{"title":3658,"description":4162},"XNSK9mlai_COIso6Z9bL54kGavHd1YbB2SBaSuGIqdk",{"id":4732,"title":666,"author":4733,"body":4734,"description":976,"extension":3697,"meta":7775,"navigation":2360,"path":974,"published":7776,"readtime":7777,"seo":7778,"stem":1832,"tags":7779,"updated":7782,"__hash__":7783},"flume/v1.0.1/3.guides/5.observability.md","zoobzio",{"type":1883,"value":4735,"toc":7744},[4736,4739,4747,4750,4753,4767,4770,4773,4860,4863,4934,4937,4987,4990,5053,5056,5059,5196,5199,5202,5653,5656,6259,6262,6500,6503,6506,6715,6718,6846,6849,6968,6971,6974,7208,7211,7390,7393,7396,7399,7507,7510,7513,7682,7685,7688,7705,7708,7722,7725,7741],[1886,4737,666],{"id":4738},"observability",[1891,4740,4741,4742,4746],{},"Flume integrates with ",[1894,4743,4745],{"href":3257,"rel":4744},[1898],"Capitan"," for comprehensive observability.",[1968,4748,6],{"id":4749},"overview",[1891,4751,4752],{},"Flume emits structured events throughout its lifecycle:",[3221,4754,4755,4758,4761,4764],{},[3224,4756,4757],{},"Factory creation and component registration",[3224,4759,4760],{},"Schema validation, building, and updates",[3224,4762,4763],{},"Pipeline retrieval and execution",[3224,4765,4766],{},"File loading and parsing",[1968,4768,987],{"id":4769},"event-categories",[3557,4771,991],{"id":4772},"factory-events",[1973,4774,4776],{"className":1975,"code":4775,"language":1977,"meta":24,"style":24},"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\n",[1979,4777,4778,4789,4800,4812,4824,4836,4848],{"__ignoreMap":24},[1982,4779,4780,4782,4784,4786],{"class":1984,"line":9},[1982,4781,1888],{"class":1993},[1982,4783,2004],{"class":2003},[1982,4785,1707],{"class":1993},[1982,4787,4788],{"class":1987},"      // Factory instantiated\n",[1982,4790,4791,4793,4795,4797],{"class":1984,"line":19},[1982,4792,1888],{"class":1993},[1982,4794,2004],{"class":2003},[1982,4796,1712],{"class":1993},[1982,4798,4799],{"class":1987}," // Processor added\n",[1982,4801,4802,4804,4806,4809],{"class":1984,"line":30},[1982,4803,1888],{"class":1993},[1982,4805,2004],{"class":2003},[1982,4807,4808],{"class":1993},"PredicateRegistered",[1982,4810,4811],{"class":1987}," // Predicate added\n",[1982,4813,4814,4816,4818,4821],{"class":1984,"line":2031},[1982,4815,1888],{"class":1993},[1982,4817,2004],{"class":2003},[1982,4819,4820],{"class":1993},"ConditionRegistered",[1982,4822,4823],{"class":1987}," // Condition added\n",[1982,4825,4826,4828,4830,4833],{"class":1984,"line":2096},[1982,4827,1888],{"class":1993},[1982,4829,2004],{"class":2003},[1982,4831,4832],{"class":1993},"ProcessorRemoved",[1982,4834,4835],{"class":1987},"    // Processor removed\n",[1982,4837,4838,4840,4842,4845],{"class":1984,"line":2119},[1982,4839,1888],{"class":1993},[1982,4841,2004],{"class":2003},[1982,4843,4844],{"class":1993},"PredicateRemoved",[1982,4846,4847],{"class":1987},"    // Predicate removed\n",[1982,4849,4850,4852,4854,4857],{"class":1984,"line":2145},[1982,4851,1888],{"class":1993},[1982,4853,2004],{"class":2003},[1982,4855,4856],{"class":1993},"ConditionRemoved",[1982,4858,4859],{"class":1987},"    // Condition removed\n",[3557,4861,996],{"id":4862},"schema-events",[1973,4864,4866],{"className":1975,"code":4865,"language":1977,"meta":24,"style":24},"flume.SchemaValidationStarted   // Validation began\nflume.SchemaValidationCompleted // Validation successful\nflume.SchemaValidationFailed    // Validation failed\nflume.SchemaBuildStarted        // Build began\nflume.SchemaBuildCompleted      // Build successful\nflume.SchemaBuildFailed         // Build failed\n",[1979,4867,4868,4879,4890,4901,4912,4923],{"__ignoreMap":24},[1982,4869,4870,4872,4874,4876],{"class":1984,"line":9},[1982,4871,1888],{"class":1993},[1982,4873,2004],{"class":2003},[1982,4875,1717],{"class":1993},[1982,4877,4878],{"class":1987},"   // Validation began\n",[1982,4880,4881,4883,4885,4887],{"class":1984,"line":19},[1982,4882,1888],{"class":1993},[1982,4884,2004],{"class":2003},[1982,4886,1722],{"class":1993},[1982,4888,4889],{"class":1987}," // Validation successful\n",[1982,4891,4892,4894,4896,4898],{"class":1984,"line":30},[1982,4893,1888],{"class":1993},[1982,4895,2004],{"class":2003},[1982,4897,1727],{"class":1993},[1982,4899,4900],{"class":1987},"    // Validation failed\n",[1982,4902,4903,4905,4907,4909],{"class":1984,"line":2031},[1982,4904,1888],{"class":1993},[1982,4906,2004],{"class":2003},[1982,4908,1732],{"class":1993},[1982,4910,4911],{"class":1987},"        // Build began\n",[1982,4913,4914,4916,4918,4920],{"class":1984,"line":2096},[1982,4915,1888],{"class":1993},[1982,4917,2004],{"class":2003},[1982,4919,1737],{"class":1993},[1982,4921,4922],{"class":1987},"      // Build successful\n",[1982,4924,4925,4927,4929,4931],{"class":1984,"line":2119},[1982,4926,1888],{"class":1993},[1982,4928,2004],{"class":2003},[1982,4930,1742],{"class":1993},[1982,4932,4933],{"class":1987},"         // Build failed\n",[3557,4935,1001],{"id":4936},"dynamic-schema-events",[1973,4938,4940],{"className":1975,"code":4939,"language":1977,"meta":24,"style":24},"flume.SchemaRegistered   // New schema added\nflume.SchemaUpdated      // Existing schema replaced\nflume.SchemaRemoved      // Schema deleted\nflume.PipelineRetrieved  // Pipeline accessed\n",[1979,4941,4942,4953,4964,4976],{"__ignoreMap":24},[1982,4943,4944,4946,4948,4950],{"class":1984,"line":9},[1982,4945,1888],{"class":1993},[1982,4947,2004],{"class":2003},[1982,4949,1747],{"class":1993},[1982,4951,4952],{"class":1987},"   // New schema added\n",[1982,4954,4955,4957,4959,4961],{"class":1984,"line":19},[1982,4956,1888],{"class":1993},[1982,4958,2004],{"class":2003},[1982,4960,1752],{"class":1993},[1982,4962,4963],{"class":1987},"      // Existing schema replaced\n",[1982,4965,4966,4968,4970,4973],{"class":1984,"line":30},[1982,4967,1888],{"class":1993},[1982,4969,2004],{"class":2003},[1982,4971,4972],{"class":1993},"SchemaRemoved",[1982,4974,4975],{"class":1987},"      // Schema deleted\n",[1982,4977,4978,4980,4982,4984],{"class":1984,"line":2031},[1982,4979,1888],{"class":1993},[1982,4981,2004],{"class":2003},[1982,4983,1757],{"class":1993},[1982,4985,4986],{"class":1987},"  // Pipeline accessed\n",[3557,4988,1006],{"id":4989},"file-events",[1973,4991,4993],{"className":1975,"code":4992,"language":1977,"meta":24,"style":24},"flume.SchemaFileLoaded  // File read successfully\nflume.SchemaFileFailed  // File read error\nflume.SchemaYAMLParsed  // YAML parsed\nflume.SchemaJSONParsed  // JSON parsed\nflume.SchemaParseFailed // Parse error\n",[1979,4994,4995,5006,5018,5030,5042],{"__ignoreMap":24},[1982,4996,4997,4999,5001,5003],{"class":1984,"line":9},[1982,4998,1888],{"class":1993},[1982,5000,2004],{"class":2003},[1982,5002,1762],{"class":1993},[1982,5004,5005],{"class":1987},"  // File read successfully\n",[1982,5007,5008,5010,5012,5015],{"class":1984,"line":19},[1982,5009,1888],{"class":1993},[1982,5011,2004],{"class":2003},[1982,5013,5014],{"class":1993},"SchemaFileFailed",[1982,5016,5017],{"class":1987},"  // File read error\n",[1982,5019,5020,5022,5024,5027],{"class":1984,"line":30},[1982,5021,1888],{"class":1993},[1982,5023,2004],{"class":2003},[1982,5025,5026],{"class":1993},"SchemaYAMLParsed",[1982,5028,5029],{"class":1987},"  // YAML parsed\n",[1982,5031,5032,5034,5036,5039],{"class":1984,"line":2031},[1982,5033,1888],{"class":1993},[1982,5035,2004],{"class":2003},[1982,5037,5038],{"class":1993},"SchemaJSONParsed",[1982,5040,5041],{"class":1987},"  // JSON parsed\n",[1982,5043,5044,5046,5048,5050],{"class":1984,"line":2096},[1982,5045,1888],{"class":1993},[1982,5047,2004],{"class":2003},[1982,5049,1767],{"class":1993},[1982,5051,5052],{"class":1987}," // Parse error\n",[1968,5054,1011],{"id":5055},"event-fields",[1891,5057,5058],{},"Events include typed fields for structured data:",[1973,5060,5062],{"className":1975,"code":5061,"language":1977,"meta":24,"style":24},"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\n",[1979,5063,5064,5076,5088,5100,5112,5124,5136,5148,5160,5172,5184],{"__ignoreMap":24},[1982,5065,5066,5068,5070,5073],{"class":1984,"line":9},[1982,5067,1888],{"class":1993},[1982,5069,2004],{"class":2003},[1982,5071,5072],{"class":1993},"KeyName",[1982,5074,5075],{"class":1987},"       // string: component/schema name\n",[1982,5077,5078,5080,5082,5085],{"class":1984,"line":19},[1982,5079,1888],{"class":1993},[1982,5081,2004],{"class":2003},[1982,5083,5084],{"class":1993},"KeyType",[1982,5086,5087],{"class":1987},"       // string: data type\n",[1982,5089,5090,5092,5094,5097],{"class":1984,"line":30},[1982,5091,1888],{"class":1993},[1982,5093,2004],{"class":2003},[1982,5095,5096],{"class":1993},"KeyVersion",[1982,5098,5099],{"class":1987},"    // string: schema version\n",[1982,5101,5102,5104,5106,5109],{"class":1984,"line":2031},[1982,5103,1888],{"class":1993},[1982,5105,2004],{"class":2003},[1982,5107,5108],{"class":1993},"KeyOldVersion",[1982,5110,5111],{"class":1987}," // string: previous version (updates)\n",[1982,5113,5114,5116,5118,5121],{"class":1984,"line":2096},[1982,5115,1888],{"class":1993},[1982,5117,2004],{"class":2003},[1982,5119,5120],{"class":1993},"KeyNewVersion",[1982,5122,5123],{"class":1987}," // string: new version (updates)\n",[1982,5125,5126,5128,5130,5133],{"class":1984,"line":2119},[1982,5127,1888],{"class":1993},[1982,5129,2004],{"class":2003},[1982,5131,5132],{"class":1993},"KeyPath",[1982,5134,5135],{"class":1987},"       // string: file path\n",[1982,5137,5138,5140,5142,5145],{"class":1984,"line":2145},[1982,5139,1888],{"class":1993},[1982,5141,2004],{"class":2003},[1982,5143,5144],{"class":1993},"KeyError",[1982,5146,5147],{"class":1987},"      // string: error message\n",[1982,5149,5150,5152,5154,5157],{"class":1984,"line":2151},[1982,5151,1888],{"class":1993},[1982,5153,2004],{"class":2003},[1982,5155,5156],{"class":1993},"KeyDuration",[1982,5158,5159],{"class":1987},"   // time.Duration: operation duration\n",[1982,5161,5162,5164,5166,5169],{"class":1984,"line":2164},[1982,5163,1888],{"class":1993},[1982,5165,2004],{"class":2003},[1982,5167,5168],{"class":1993},"KeyErrorCount",[1982,5170,5171],{"class":1987}," // int: number of errors\n",[1982,5173,5174,5176,5178,5181],{"class":1984,"line":2170},[1982,5175,1888],{"class":1993},[1982,5177,2004],{"class":2003},[1982,5179,5180],{"class":1993},"KeySizeBytes",[1982,5182,5183],{"class":1987},"  // int: file size\n",[1982,5185,5186,5188,5190,5193],{"class":1984,"line":2218},[1982,5187,1888],{"class":1993},[1982,5189,2004],{"class":2003},[1982,5191,5192],{"class":1993},"KeyFound",[1982,5194,5195],{"class":1987},"      // bool: retrieval success\n",[1968,5197,1016],{"id":5198},"setting-up-handlers",[3557,5200,1020],{"id":5201},"basic-logging",[1973,5203,5205],{"className":1975,"code":5204,"language":1977,"meta":24,"style":24},"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}\n",[1979,5206,5207,5214,5218,5229,5234,5285,5321,5326,5330,5376,5405,5421,5436,5451,5455,5459,5505,5537,5541,5545,5549,5581,5602,5619,5633,5637,5641,5649],{"__ignoreMap":24},[1982,5208,5209,5211],{"class":1984,"line":9},[1982,5210,2533],{"class":2052},[1982,5212,5213],{"class":2045}," \"github.com/zoobz-io/capitan\"\n",[1982,5215,5216],{"class":1984,"line":19},[1982,5217,2361],{"emptyLinePlaceholder":2360},[1982,5219,5220,5222,5225,5227],{"class":1984,"line":30},[1982,5221,2607],{"class":2052},[1982,5223,5224],{"class":2007}," setupLogging",[1982,5226,2622],{"class":2003},[1982,5228,2093],{"class":2003},[1982,5230,5231],{"class":1984,"line":2031},[1982,5232,5233],{"class":1987},"    // Log all schema events\n",[1982,5235,5236,5239,5241,5244,5246,5248,5250,5252,5254,5256,5258,5260,5262,5264,5266,5268,5271,5274,5276,5278,5281,5283],{"class":1984,"line":2096},[1982,5237,5238],{"class":1993},"    capitan",[1982,5240,2004],{"class":2003},[1982,5242,5243],{"class":2007},"Handle",[1982,5245,2042],{"class":2003},[1982,5247,1888],{"class":1993},[1982,5249,2004],{"class":2003},[1982,5251,1747],{"class":1993},[1982,5253,2049],{"class":2003},[1982,5255,2053],{"class":2052},[1982,5257,2042],{"class":2003},[1982,5259,2059],{"class":2058},[1982,5261,2062],{"class":2013},[1982,5263,2004],{"class":2003},[1982,5265,2067],{"class":2013},[1982,5267,2049],{"class":2003},[1982,5269,5270],{"class":2058}," fields",[1982,5272,5273],{"class":2003}," []",[1982,5275,3259],{"class":2013},[1982,5277,2004],{"class":2003},[1982,5279,5280],{"class":2013},"Field",[1982,5282,2078],{"class":2003},[1982,5284,2093],{"class":2003},[1982,5286,5287,5290,5292,5294,5296,5299,5302,5304,5306,5309,5311,5314,5316,5319],{"class":1984,"line":2119},[1982,5288,5289],{"class":1993},"        log",[1982,5291,2004],{"class":2003},[1982,5293,3074],{"class":2007},[1982,5295,2042],{"class":2003},[1982,5297,5298],{"class":2045},"\"Schema registered: ",[1982,5300,5301],{"class":3082},"%s",[1982,5303,3096],{"class":2045},[1982,5305,2049],{"class":2003},[1982,5307,5308],{"class":2007}," extractString",[1982,5310,2042],{"class":2003},[1982,5312,5313],{"class":1993},"fields",[1982,5315,2049],{"class":2003},[1982,5317,5318],{"class":2045}," \"name\"",[1982,5320,3354],{"class":2003},[1982,5322,5323],{"class":1984,"line":2145},[1982,5324,5325],{"class":2003},"    })\n",[1982,5327,5328],{"class":1984,"line":2151},[1982,5329,2361],{"emptyLinePlaceholder":2360},[1982,5331,5332,5334,5336,5338,5340,5342,5344,5346,5348,5350,5352,5354,5356,5358,5360,5362,5364,5366,5368,5370,5372,5374],{"class":1984,"line":2164},[1982,5333,5238],{"class":1993},[1982,5335,2004],{"class":2003},[1982,5337,5243],{"class":2007},[1982,5339,2042],{"class":2003},[1982,5341,1888],{"class":1993},[1982,5343,2004],{"class":2003},[1982,5345,1752],{"class":1993},[1982,5347,2049],{"class":2003},[1982,5349,2053],{"class":2052},[1982,5351,2042],{"class":2003},[1982,5353,2059],{"class":2058},[1982,5355,2062],{"class":2013},[1982,5357,2004],{"class":2003},[1982,5359,2067],{"class":2013},[1982,5361,2049],{"class":2003},[1982,5363,5270],{"class":2058},[1982,5365,5273],{"class":2003},[1982,5367,3259],{"class":2013},[1982,5369,2004],{"class":2003},[1982,5371,5280],{"class":2013},[1982,5373,2078],{"class":2003},[1982,5375,2093],{"class":2003},[1982,5377,5378,5380,5382,5384,5386,5389,5391,5393,5395,5398,5400,5403],{"class":1984,"line":2170},[1982,5379,5289],{"class":1993},[1982,5381,2004],{"class":2003},[1982,5383,3074],{"class":2007},[1982,5385,2042],{"class":2003},[1982,5387,5388],{"class":2045},"\"Schema updated: ",[1982,5390,5301],{"class":3082},[1982,5392,2081],{"class":2045},[1982,5394,5301],{"class":3082},[1982,5396,5397],{"class":2045}," -> ",[1982,5399,5301],{"class":3082},[1982,5401,5402],{"class":2045},")\"",[1982,5404,2295],{"class":2003},[1982,5406,5407,5410,5412,5414,5416,5418],{"class":1984,"line":2218},[1982,5408,5409],{"class":2007},"            extractString",[1982,5411,2042],{"class":2003},[1982,5413,5313],{"class":1993},[1982,5415,2049],{"class":2003},[1982,5417,5318],{"class":2045},[1982,5419,5420],{"class":2003},"),\n",[1982,5422,5423,5425,5427,5429,5431,5434],{"class":1984,"line":2237},[1982,5424,5409],{"class":2007},[1982,5426,2042],{"class":2003},[1982,5428,5313],{"class":1993},[1982,5430,2049],{"class":2003},[1982,5432,5433],{"class":2045}," \"old_version\"",[1982,5435,5420],{"class":2003},[1982,5437,5438,5440,5442,5444,5446,5449],{"class":1984,"line":2248},[1982,5439,5409],{"class":2007},[1982,5441,2042],{"class":2003},[1982,5443,5313],{"class":1993},[1982,5445,2049],{"class":2003},[1982,5447,5448],{"class":2045}," \"new_version\"",[1982,5450,3354],{"class":2003},[1982,5452,5453],{"class":1984,"line":2253},[1982,5454,5325],{"class":2003},[1982,5456,5457],{"class":1984,"line":2258},[1982,5458,2361],{"emptyLinePlaceholder":2360},[1982,5460,5461,5463,5465,5467,5469,5471,5473,5475,5477,5479,5481,5483,5485,5487,5489,5491,5493,5495,5497,5499,5501,5503],{"class":1984,"line":2282},[1982,5462,5238],{"class":1993},[1982,5464,2004],{"class":2003},[1982,5466,5243],{"class":2007},[1982,5468,2042],{"class":2003},[1982,5470,1888],{"class":1993},[1982,5472,2004],{"class":2003},[1982,5474,1742],{"class":1993},[1982,5476,2049],{"class":2003},[1982,5478,2053],{"class":2052},[1982,5480,2042],{"class":2003},[1982,5482,2059],{"class":2058},[1982,5484,2062],{"class":2013},[1982,5486,2004],{"class":2003},[1982,5488,2067],{"class":2013},[1982,5490,2049],{"class":2003},[1982,5492,5270],{"class":2058},[1982,5494,5273],{"class":2003},[1982,5496,3259],{"class":2013},[1982,5498,2004],{"class":2003},[1982,5500,5280],{"class":2013},[1982,5502,2078],{"class":2003},[1982,5504,2093],{"class":2003},[1982,5506,5507,5509,5511,5513,5515,5518,5520,5522,5524,5526,5528,5530,5532,5535],{"class":1984,"line":2298},[1982,5508,5289],{"class":1993},[1982,5510,2004],{"class":2003},[1982,5512,3074],{"class":2007},[1982,5514,2042],{"class":2003},[1982,5516,5517],{"class":2045},"\"Build failed: ",[1982,5519,5301],{"class":3082},[1982,5521,3096],{"class":2045},[1982,5523,2049],{"class":2003},[1982,5525,5308],{"class":2007},[1982,5527,2042],{"class":2003},[1982,5529,5313],{"class":1993},[1982,5531,2049],{"class":2003},[1982,5533,5534],{"class":2045}," \"error\"",[1982,5536,3354],{"class":2003},[1982,5538,5539],{"class":1984,"line":2351},[1982,5540,5325],{"class":2003},[1982,5542,5543],{"class":1984,"line":2357},[1982,5544,2598],{"class":2003},[1982,5546,5547],{"class":1984,"line":2364},[1982,5548,2361],{"emptyLinePlaceholder":2360},[1982,5550,5551,5553,5555,5557,5559,5561,5563,5565,5567,5569,5572,5575,5577,5579],{"class":1984,"line":2370},[1982,5552,2607],{"class":2052},[1982,5554,5308],{"class":2007},[1982,5556,2042],{"class":2003},[1982,5558,5313],{"class":2058},[1982,5560,5273],{"class":2003},[1982,5562,3259],{"class":2013},[1982,5564,2004],{"class":2003},[1982,5566,5280],{"class":2013},[1982,5568,2049],{"class":2003},[1982,5570,5571],{"class":2058}," key",[1982,5573,5574],{"class":2013}," string",[1982,5576,2078],{"class":2003},[1982,5578,5574],{"class":2013},[1982,5580,2093],{"class":2003},[1982,5582,5583,5586,5588,5590,5593,5595,5598,5600],{"class":1984,"line":2395},[1982,5584,5585],{"class":2099},"    for",[1982,5587,2378],{"class":1993},[1982,5589,2049],{"class":2003},[1982,5591,5592],{"class":1993}," f",[1982,5594,1997],{"class":1993},[1982,5596,5597],{"class":2099}," range",[1982,5599,5270],{"class":1993},[1982,5601,2093],{"class":2003},[1982,5603,5604,5606,5608,5610,5613,5615,5617],{"class":1984,"line":2401},[1982,5605,2100],{"class":2099},[1982,5607,5592],{"class":1993},[1982,5609,2004],{"class":2003},[1982,5611,5612],{"class":1993},"Key",[1982,5614,2342],{"class":2099},[1982,5616,5571],{"class":1993},[1982,5618,2093],{"class":2003},[1982,5620,5621,5623,5625,5627,5630],{"class":1984,"line":2407},[1982,5622,2122],{"class":2099},[1982,5624,5592],{"class":1993},[1982,5626,2004],{"class":2003},[1982,5628,5629],{"class":2007},"String",[1982,5631,5632],{"class":2003},"()\n",[1982,5634,5635],{"class":1984,"line":2413},[1982,5636,2148],{"class":2003},[1982,5638,5639],{"class":1984,"line":2419},[1982,5640,2999],{"class":2003},[1982,5642,5643,5646],{"class":1984,"line":2425},[1982,5644,5645],{"class":2099},"    return",[1982,5647,5648],{"class":2045}," \"\"\n",[1982,5650,5651],{"class":1984,"line":2431},[1982,5652,2598],{"class":2003},[3557,5654,1025],{"id":5655},"metrics-collection",[1973,5657,5659],{"className":1975,"code":5658,"language":1977,"meta":24,"style":24},"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}\n",[1979,5660,5661,5667,5672,5677,5681,5685,5692,5709,5722,5734,5746,5751,5767,5771,5775,5791,5802,5813,5824,5840,5844,5857,5861,5865,5881,5891,5902,5913,5917,5921,5925,5929,5940,5967,5971,6017,6036,6059,6063,6067,6113,6133,6154,6185,6189,6193,6239,6250,6254],{"__ignoreMap":24},[1982,5662,5663,5665],{"class":1984,"line":9},[1982,5664,2533],{"class":2052},[1982,5666,2537],{"class":2536},[1982,5668,5669],{"class":1984,"line":19},[1982,5670,5671],{"class":2045},"    \"github.com/prometheus/client_golang/prometheus\"\n",[1982,5673,5674],{"class":1984,"line":30},[1982,5675,5676],{"class":2045},"    \"github.com/zoobz-io/capitan\"\n",[1982,5678,5679],{"class":1984,"line":2031},[1982,5680,2142],{"class":2536},[1982,5682,5683],{"class":1984,"line":2096},[1982,5684,2361],{"emptyLinePlaceholder":2360},[1982,5686,5687,5690],{"class":1984,"line":2119},[1982,5688,5689],{"class":2052},"var",[1982,5691,2537],{"class":2003},[1982,5693,5694,5697,5699,5702,5704,5707],{"class":1984,"line":2145},[1982,5695,5696],{"class":1993},"    schemaUpdates",[1982,5698,2873],{"class":1993},[1982,5700,5701],{"class":1993}," prometheus",[1982,5703,2004],{"class":2003},[1982,5705,5706],{"class":2007},"NewCounterVec",[1982,5708,2028],{"class":2003},[1982,5710,5711,5714,5716,5719],{"class":1984,"line":2151},[1982,5712,5713],{"class":2013},"        prometheus",[1982,5715,2004],{"class":2003},[1982,5717,5718],{"class":2013},"CounterOpts",[1982,5720,5721],{"class":2003},"{\n",[1982,5723,5724,5727,5729,5732],{"class":1984,"line":2164},[1982,5725,5726],{"class":2285},"            Name",[1982,5728,2289],{"class":2003},[1982,5730,5731],{"class":2045}," \"flume_schema_updates_total\"",[1982,5733,2295],{"class":2003},[1982,5735,5736,5739,5741,5744],{"class":1984,"line":2170},[1982,5737,5738],{"class":2285},"            Help",[1982,5740,2289],{"class":2003},[1982,5742,5743],{"class":2045}," \"Total schema updates\"",[1982,5745,2295],{"class":2003},[1982,5747,5748],{"class":1984,"line":2218},[1982,5749,5750],{"class":2003},"        },\n",[1982,5752,5753,5756,5759,5761,5764],{"class":1984,"line":2237},[1982,5754,5755],{"class":2003},"        []",[1982,5757,5758],{"class":2013},"string",[1982,5760,2633],{"class":2003},[1982,5762,5763],{"class":2045},"\"name\"",[1982,5765,5766],{"class":2003},"},\n",[1982,5768,5769],{"class":1984,"line":2248},[1982,5770,2902],{"class":2003},[1982,5772,5773],{"class":1984,"line":2253},[1982,5774,2361],{"emptyLinePlaceholder":2360},[1982,5776,5777,5780,5782,5784,5786,5789],{"class":1984,"line":2258},[1982,5778,5779],{"class":1993},"    buildDuration",[1982,5781,2873],{"class":1993},[1982,5783,5701],{"class":1993},[1982,5785,2004],{"class":2003},[1982,5787,5788],{"class":2007},"NewHistogramVec",[1982,5790,2028],{"class":2003},[1982,5792,5793,5795,5797,5800],{"class":1984,"line":2282},[1982,5794,5713],{"class":2013},[1982,5796,2004],{"class":2003},[1982,5798,5799],{"class":2013},"HistogramOpts",[1982,5801,5721],{"class":2003},[1982,5803,5804,5806,5808,5811],{"class":1984,"line":2298},[1982,5805,5726],{"class":2285},[1982,5807,2289],{"class":2003},[1982,5809,5810],{"class":2045},"    \"flume_build_duration_seconds\"",[1982,5812,2295],{"class":2003},[1982,5814,5815,5817,5819,5822],{"class":1984,"line":2351},[1982,5816,5738],{"class":2285},[1982,5818,2289],{"class":2003},[1982,5820,5821],{"class":2045},"    \"Schema build duration\"",[1982,5823,2295],{"class":2003},[1982,5825,5826,5829,5831,5833,5835,5838],{"class":1984,"line":2357},[1982,5827,5828],{"class":2285},"            Buckets",[1982,5830,2289],{"class":2003},[1982,5832,5701],{"class":1993},[1982,5834,2004],{"class":2003},[1982,5836,5837],{"class":1993},"DefBuckets",[1982,5839,2295],{"class":2003},[1982,5841,5842],{"class":1984,"line":2364},[1982,5843,5750],{"class":2003},[1982,5845,5846,5848,5850,5852,5855],{"class":1984,"line":2370},[1982,5847,5755],{"class":2003},[1982,5849,5758],{"class":2013},[1982,5851,2633],{"class":2003},[1982,5853,5854],{"class":2045},"\"version\"",[1982,5856,5766],{"class":2003},[1982,5858,5859],{"class":1984,"line":2395},[1982,5860,2902],{"class":2003},[1982,5862,5863],{"class":1984,"line":2401},[1982,5864,2361],{"emptyLinePlaceholder":2360},[1982,5866,5867,5870,5872,5874,5876,5879],{"class":1984,"line":2407},[1982,5868,5869],{"class":1993},"    buildFailures",[1982,5871,2873],{"class":1993},[1982,5873,5701],{"class":1993},[1982,5875,2004],{"class":2003},[1982,5877,5878],{"class":2007},"NewCounter",[1982,5880,2028],{"class":2003},[1982,5882,5883,5885,5887,5889],{"class":1984,"line":2413},[1982,5884,5713],{"class":2013},[1982,5886,2004],{"class":2003},[1982,5888,5718],{"class":2013},[1982,5890,5721],{"class":2003},[1982,5892,5893,5895,5897,5900],{"class":1984,"line":2419},[1982,5894,5726],{"class":2285},[1982,5896,2289],{"class":2003},[1982,5898,5899],{"class":2045}," \"flume_build_failures_total\"",[1982,5901,2295],{"class":2003},[1982,5903,5904,5906,5908,5911],{"class":1984,"line":2425},[1982,5905,5738],{"class":2285},[1982,5907,2289],{"class":2003},[1982,5909,5910],{"class":2045}," \"Total build failures\"",[1982,5912,2295],{"class":2003},[1982,5914,5915],{"class":1984,"line":2431},[1982,5916,5750],{"class":2003},[1982,5918,5919],{"class":1984,"line":2437},[1982,5920,2902],{"class":2003},[1982,5922,5923],{"class":1984,"line":2445},[1982,5924,2142],{"class":2003},[1982,5926,5927],{"class":1984,"line":2450},[1982,5928,2361],{"emptyLinePlaceholder":2360},[1982,5930,5931,5933,5936,5938],{"class":1984,"line":2456},[1982,5932,2607],{"class":2052},[1982,5934,5935],{"class":2007}," setupMetrics",[1982,5937,2622],{"class":2003},[1982,5939,2093],{"class":2003},[1982,5941,5942,5945,5947,5950,5952,5955,5957,5960,5962,5965],{"class":1984,"line":2905},[1982,5943,5944],{"class":1993},"    prometheus",[1982,5946,2004],{"class":2003},[1982,5948,5949],{"class":2007},"MustRegister",[1982,5951,2042],{"class":2003},[1982,5953,5954],{"class":1993},"schemaUpdates",[1982,5956,2049],{"class":2003},[1982,5958,5959],{"class":1993}," buildDuration",[1982,5961,2049],{"class":2003},[1982,5963,5964],{"class":1993}," buildFailures",[1982,5966,2142],{"class":2003},[1982,5968,5969],{"class":1984,"line":2910},[1982,5970,2361],{"emptyLinePlaceholder":2360},[1982,5972,5973,5975,5977,5979,5981,5983,5985,5987,5989,5991,5993,5995,5997,5999,6001,6003,6005,6007,6009,6011,6013,6015],{"class":1984,"line":2916},[1982,5974,5238],{"class":1993},[1982,5976,2004],{"class":2003},[1982,5978,5243],{"class":2007},[1982,5980,2042],{"class":2003},[1982,5982,1888],{"class":1993},[1982,5984,2004],{"class":2003},[1982,5986,1752],{"class":1993},[1982,5988,2049],{"class":2003},[1982,5990,2053],{"class":2052},[1982,5992,2042],{"class":2003},[1982,5994,2059],{"class":2058},[1982,5996,2062],{"class":2013},[1982,5998,2004],{"class":2003},[1982,6000,2067],{"class":2013},[1982,6002,2049],{"class":2003},[1982,6004,5270],{"class":2058},[1982,6006,5273],{"class":2003},[1982,6008,3259],{"class":2013},[1982,6010,2004],{"class":2003},[1982,6012,5280],{"class":2013},[1982,6014,2078],{"class":2003},[1982,6016,2093],{"class":2003},[1982,6018,6019,6022,6024,6026,6028,6030,6032,6034],{"class":1984,"line":2938},[1982,6020,6021],{"class":1993},"        name",[1982,6023,1997],{"class":1993},[1982,6025,5308],{"class":2007},[1982,6027,2042],{"class":2003},[1982,6029,5313],{"class":1993},[1982,6031,2049],{"class":2003},[1982,6033,5318],{"class":2045},[1982,6035,2142],{"class":2003},[1982,6037,6038,6041,6043,6046,6048,6051,6054,6057],{"class":1984,"line":2943},[1982,6039,6040],{"class":1993},"        schemaUpdates",[1982,6042,2004],{"class":2003},[1982,6044,6045],{"class":2007},"WithLabelValues",[1982,6047,2042],{"class":2003},[1982,6049,6050],{"class":1993},"name",[1982,6052,6053],{"class":2003},").",[1982,6055,6056],{"class":2007},"Inc",[1982,6058,5632],{"class":2003},[1982,6060,6061],{"class":1984,"line":2948},[1982,6062,5325],{"class":2003},[1982,6064,6065],{"class":1984,"line":2953},[1982,6066,2361],{"emptyLinePlaceholder":2360},[1982,6068,6069,6071,6073,6075,6077,6079,6081,6083,6085,6087,6089,6091,6093,6095,6097,6099,6101,6103,6105,6107,6109,6111],{"class":1984,"line":2959},[1982,6070,5238],{"class":1993},[1982,6072,2004],{"class":2003},[1982,6074,5243],{"class":2007},[1982,6076,2042],{"class":2003},[1982,6078,1888],{"class":1993},[1982,6080,2004],{"class":2003},[1982,6082,1737],{"class":1993},[1982,6084,2049],{"class":2003},[1982,6086,2053],{"class":2052},[1982,6088,2042],{"class":2003},[1982,6090,2059],{"class":2058},[1982,6092,2062],{"class":2013},[1982,6094,2004],{"class":2003},[1982,6096,2067],{"class":2013},[1982,6098,2049],{"class":2003},[1982,6100,5270],{"class":2058},[1982,6102,5273],{"class":2003},[1982,6104,3259],{"class":2013},[1982,6106,2004],{"class":2003},[1982,6108,5280],{"class":2013},[1982,6110,2078],{"class":2003},[1982,6112,2093],{"class":2003},[1982,6114,6115,6118,6120,6122,6124,6126,6128,6131],{"class":1984,"line":2966},[1982,6116,6117],{"class":1993},"        version",[1982,6119,1997],{"class":1993},[1982,6121,5308],{"class":2007},[1982,6123,2042],{"class":2003},[1982,6125,5313],{"class":1993},[1982,6127,2049],{"class":2003},[1982,6129,6130],{"class":2045}," \"version\"",[1982,6132,2142],{"class":2003},[1982,6134,6135,6138,6140,6143,6145,6147,6149,6152],{"class":1984,"line":2982},[1982,6136,6137],{"class":1993},"        duration",[1982,6139,1997],{"class":1993},[1982,6141,6142],{"class":2007}," extractDuration",[1982,6144,2042],{"class":2003},[1982,6146,5313],{"class":1993},[1982,6148,2049],{"class":2003},[1982,6150,6151],{"class":2045}," \"duration\"",[1982,6153,2142],{"class":2003},[1982,6155,6156,6159,6161,6163,6165,6168,6170,6173,6175,6178,6180,6183],{"class":1984,"line":2996},[1982,6157,6158],{"class":1993},"        buildDuration",[1982,6160,2004],{"class":2003},[1982,6162,6045],{"class":2007},[1982,6164,2042],{"class":2003},[1982,6166,6167],{"class":1993},"version",[1982,6169,6053],{"class":2003},[1982,6171,6172],{"class":2007},"Observe",[1982,6174,2042],{"class":2003},[1982,6176,6177],{"class":1993},"duration",[1982,6179,2004],{"class":2003},[1982,6181,6182],{"class":2007},"Seconds",[1982,6184,3481],{"class":2003},[1982,6186,6187],{"class":1984,"line":3002},[1982,6188,5325],{"class":2003},[1982,6190,6191],{"class":1984,"line":3007},[1982,6192,2361],{"emptyLinePlaceholder":2360},[1982,6194,6195,6197,6199,6201,6203,6205,6207,6209,6211,6213,6215,6217,6219,6221,6223,6225,6227,6229,6231,6233,6235,6237],{"class":1984,"line":3013},[1982,6196,5238],{"class":1993},[1982,6198,2004],{"class":2003},[1982,6200,5243],{"class":2007},[1982,6202,2042],{"class":2003},[1982,6204,1888],{"class":1993},[1982,6206,2004],{"class":2003},[1982,6208,1742],{"class":1993},[1982,6210,2049],{"class":2003},[1982,6212,2053],{"class":2052},[1982,6214,2042],{"class":2003},[1982,6216,2059],{"class":2058},[1982,6218,2062],{"class":2013},[1982,6220,2004],{"class":2003},[1982,6222,2067],{"class":2013},[1982,6224,2049],{"class":2003},[1982,6226,5270],{"class":2058},[1982,6228,5273],{"class":2003},[1982,6230,3259],{"class":2013},[1982,6232,2004],{"class":2003},[1982,6234,5280],{"class":2013},[1982,6236,2078],{"class":2003},[1982,6238,2093],{"class":2003},[1982,6240,6241,6244,6246,6248],{"class":1984,"line":3066},[1982,6242,6243],{"class":1993},"        buildFailures",[1982,6245,2004],{"class":2003},[1982,6247,6056],{"class":2007},[1982,6249,5632],{"class":2003},[1982,6251,6252],{"class":1984,"line":3110},[1982,6253,5325],{"class":2003},[1982,6255,6257],{"class":1984,"line":6256},49,[1982,6258,2598],{"class":2003},[3557,6260,1030],{"id":6261},"distributed-tracing",[1973,6263,6265],{"className":1975,"code":6264,"language":1977,"meta":24,"style":24},"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}\n",[1979,6266,6267,6274,6278,6302,6348,6379,6397,6428,6433,6437,6441,6487,6492,6496],{"__ignoreMap":24},[1982,6268,6269,6271],{"class":1984,"line":9},[1982,6270,2533],{"class":2052},[1982,6272,6273],{"class":2045}," \"go.opentelemetry.io/otel/trace\"\n",[1982,6275,6276],{"class":1984,"line":19},[1982,6277,2361],{"emptyLinePlaceholder":2360},[1982,6279,6280,6282,6285,6287,6290,6293,6295,6298,6300],{"class":1984,"line":30},[1982,6281,2607],{"class":2052},[1982,6283,6284],{"class":2007}," setupTracing",[1982,6286,2042],{"class":2003},[1982,6288,6289],{"class":2058},"tracer",[1982,6291,6292],{"class":2013}," trace",[1982,6294,2004],{"class":2003},[1982,6296,6297],{"class":2013},"Tracer",[1982,6299,2078],{"class":2003},[1982,6301,2093],{"class":2003},[1982,6303,6304,6306,6308,6310,6312,6314,6316,6318,6320,6322,6324,6326,6328,6330,6332,6334,6336,6338,6340,6342,6344,6346],{"class":1984,"line":2031},[1982,6305,5238],{"class":1993},[1982,6307,2004],{"class":2003},[1982,6309,5243],{"class":2007},[1982,6311,2042],{"class":2003},[1982,6313,1888],{"class":1993},[1982,6315,2004],{"class":2003},[1982,6317,1732],{"class":1993},[1982,6319,2049],{"class":2003},[1982,6321,2053],{"class":2052},[1982,6323,2042],{"class":2003},[1982,6325,2059],{"class":2058},[1982,6327,2062],{"class":2013},[1982,6329,2004],{"class":2003},[1982,6331,2067],{"class":2013},[1982,6333,2049],{"class":2003},[1982,6335,5270],{"class":2058},[1982,6337,5273],{"class":2003},[1982,6339,3259],{"class":2013},[1982,6341,2004],{"class":2003},[1982,6343,5280],{"class":2013},[1982,6345,2078],{"class":2003},[1982,6347,2093],{"class":2003},[1982,6349,6350,6353,6355,6358,6360,6363,6365,6368,6370,6372,6374,6377],{"class":1984,"line":2096},[1982,6351,6352],{"class":1993},"        _",[1982,6354,2049],{"class":2003},[1982,6356,6357],{"class":1993}," span",[1982,6359,1997],{"class":1993},[1982,6361,6362],{"class":1993}," tracer",[1982,6364,2004],{"class":2003},[1982,6366,6367],{"class":2007},"Start",[1982,6369,2042],{"class":2003},[1982,6371,2059],{"class":1993},[1982,6373,2049],{"class":2003},[1982,6375,6376],{"class":2045}," \"flume.build\"",[1982,6378,2142],{"class":2003},[1982,6380,6381,6383,6385,6387,6389,6391,6393,6395],{"class":1984,"line":2119},[1982,6382,6117],{"class":1993},[1982,6384,1997],{"class":1993},[1982,6386,5308],{"class":2007},[1982,6388,2042],{"class":2003},[1982,6390,5313],{"class":1993},[1982,6392,2049],{"class":2003},[1982,6394,6130],{"class":2045},[1982,6396,2142],{"class":2003},[1982,6398,6399,6402,6404,6407,6409,6412,6414,6416,6418,6421,6423,6426],{"class":1984,"line":2145},[1982,6400,6401],{"class":1993},"        span",[1982,6403,2004],{"class":2003},[1982,6405,6406],{"class":2007},"SetAttributes",[1982,6408,2042],{"class":2003},[1982,6410,6411],{"class":1993},"attribute",[1982,6413,2004],{"class":2003},[1982,6415,5629],{"class":2007},[1982,6417,2042],{"class":2003},[1982,6419,6420],{"class":2045},"\"schema.version\"",[1982,6422,2049],{"class":2003},[1982,6424,6425],{"class":1993}," version",[1982,6427,3354],{"class":2003},[1982,6429,6430],{"class":1984,"line":2151},[1982,6431,6432],{"class":1987},"        // Store span for completion handler\n",[1982,6434,6435],{"class":1984,"line":2164},[1982,6436,5325],{"class":2003},[1982,6438,6439],{"class":1984,"line":2170},[1982,6440,2361],{"emptyLinePlaceholder":2360},[1982,6442,6443,6445,6447,6449,6451,6453,6455,6457,6459,6461,6463,6465,6467,6469,6471,6473,6475,6477,6479,6481,6483,6485],{"class":1984,"line":2218},[1982,6444,5238],{"class":1993},[1982,6446,2004],{"class":2003},[1982,6448,5243],{"class":2007},[1982,6450,2042],{"class":2003},[1982,6452,1888],{"class":1993},[1982,6454,2004],{"class":2003},[1982,6456,1737],{"class":1993},[1982,6458,2049],{"class":2003},[1982,6460,2053],{"class":2052},[1982,6462,2042],{"class":2003},[1982,6464,2059],{"class":2058},[1982,6466,2062],{"class":2013},[1982,6468,2004],{"class":2003},[1982,6470,2067],{"class":2013},[1982,6472,2049],{"class":2003},[1982,6474,5270],{"class":2058},[1982,6476,5273],{"class":2003},[1982,6478,3259],{"class":2013},[1982,6480,2004],{"class":2003},[1982,6482,5280],{"class":2013},[1982,6484,2078],{"class":2003},[1982,6486,2093],{"class":2003},[1982,6488,6489],{"class":1984,"line":2237},[1982,6490,6491],{"class":1987},"        // End span\n",[1982,6493,6494],{"class":1984,"line":2248},[1982,6495,5325],{"class":2003},[1982,6497,6498],{"class":1984,"line":2253},[1982,6499,2598],{"class":2003},[1968,6501,1035],{"id":6502},"common-monitoring-patterns",[3557,6504,1039],{"id":6505},"schema-change-alerting",[1973,6507,6509],{"className":1975,"code":6508,"language":1977,"meta":24,"style":24},"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})\n",[1979,6510,6511,6557,6576,6595,6614,6618,6639,6670,6691,6707,6711],{"__ignoreMap":24},[1982,6512,6513,6515,6517,6519,6521,6523,6525,6527,6529,6531,6533,6535,6537,6539,6541,6543,6545,6547,6549,6551,6553,6555],{"class":1984,"line":9},[1982,6514,3259],{"class":1993},[1982,6516,2004],{"class":2003},[1982,6518,5243],{"class":2007},[1982,6520,2042],{"class":2003},[1982,6522,1888],{"class":1993},[1982,6524,2004],{"class":2003},[1982,6526,1752],{"class":1993},[1982,6528,2049],{"class":2003},[1982,6530,2053],{"class":2052},[1982,6532,2042],{"class":2003},[1982,6534,2059],{"class":2058},[1982,6536,2062],{"class":2013},[1982,6538,2004],{"class":2003},[1982,6540,2067],{"class":2013},[1982,6542,2049],{"class":2003},[1982,6544,5270],{"class":2058},[1982,6546,5273],{"class":2003},[1982,6548,3259],{"class":2013},[1982,6550,2004],{"class":2003},[1982,6552,5280],{"class":2013},[1982,6554,2078],{"class":2003},[1982,6556,2093],{"class":2003},[1982,6558,6559,6562,6564,6566,6568,6570,6572,6574],{"class":1984,"line":19},[1982,6560,6561],{"class":1993},"    name",[1982,6563,1997],{"class":1993},[1982,6565,5308],{"class":2007},[1982,6567,2042],{"class":2003},[1982,6569,5313],{"class":1993},[1982,6571,2049],{"class":2003},[1982,6573,5318],{"class":2045},[1982,6575,2142],{"class":2003},[1982,6577,6578,6581,6583,6585,6587,6589,6591,6593],{"class":1984,"line":30},[1982,6579,6580],{"class":1993},"    oldVersion",[1982,6582,1997],{"class":1993},[1982,6584,5308],{"class":2007},[1982,6586,2042],{"class":2003},[1982,6588,5313],{"class":1993},[1982,6590,2049],{"class":2003},[1982,6592,5433],{"class":2045},[1982,6594,2142],{"class":2003},[1982,6596,6597,6600,6602,6604,6606,6608,6610,6612],{"class":1984,"line":2031},[1982,6598,6599],{"class":1993},"    newVersion",[1982,6601,1997],{"class":1993},[1982,6603,5308],{"class":2007},[1982,6605,2042],{"class":2003},[1982,6607,5313],{"class":1993},[1982,6609,2049],{"class":2003},[1982,6611,5448],{"class":2045},[1982,6613,2142],{"class":2003},[1982,6615,6616],{"class":1984,"line":2096},[1982,6617,2361],{"emptyLinePlaceholder":2360},[1982,6619,6620,6622,6625,6627,6630,6632,6635,6637],{"class":1984,"line":2119},[1982,6621,2969],{"class":2099},[1982,6623,6624],{"class":2007}," isMajorVersionChange",[1982,6626,2042],{"class":2003},[1982,6628,6629],{"class":1993},"oldVersion",[1982,6631,2049],{"class":2003},[1982,6633,6634],{"class":1993}," newVersion",[1982,6636,2078],{"class":2003},[1982,6638,2093],{"class":2003},[1982,6640,6641,6644,6646,6649,6651,6654,6656,6659,6661,6663,6665,6668],{"class":1984,"line":2145},[1982,6642,6643],{"class":1993},"        alerting",[1982,6645,2004],{"class":2003},[1982,6647,6648],{"class":2007},"SendAlert",[1982,6650,2042],{"class":2003},[1982,6652,6653],{"class":1993},"alerting",[1982,6655,2004],{"class":2003},[1982,6657,6658],{"class":1993},"Warning",[1982,6660,2049],{"class":2003},[1982,6662,2129],{"class":1993},[1982,6664,2004],{"class":2003},[1982,6666,6667],{"class":2007},"Sprintf",[1982,6669,2028],{"class":2003},[1982,6671,6672,6675,6677,6680,6682,6685,6687,6689],{"class":1984,"line":2151},[1982,6673,6674],{"class":2045},"            \"Major schema version change: ",[1982,6676,5301],{"class":3082},[1982,6678,6679],{"class":2045}," from ",[1982,6681,5301],{"class":3082},[1982,6683,6684],{"class":2045}," to ",[1982,6686,5301],{"class":3082},[1982,6688,3096],{"class":2045},[1982,6690,2295],{"class":2003},[1982,6692,6693,6696,6698,6701,6703,6705],{"class":1984,"line":2164},[1982,6694,6695],{"class":1993},"            name",[1982,6697,2049],{"class":2003},[1982,6699,6700],{"class":1993}," oldVersion",[1982,6702,2049],{"class":2003},[1982,6704,6634],{"class":1993},[1982,6706,3354],{"class":2003},[1982,6708,6709],{"class":1984,"line":2170},[1982,6710,2999],{"class":2003},[1982,6712,6713],{"class":1984,"line":2218},[1982,6714,2354],{"class":2003},[3557,6716,1044],{"id":6717},"build-performance-tracking",[1973,6719,6721],{"className":1975,"code":6720,"language":1977,"meta":24,"style":24},"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})\n",[1979,6722,6723,6769,6788,6792,6815,6838,6842],{"__ignoreMap":24},[1982,6724,6725,6727,6729,6731,6733,6735,6737,6739,6741,6743,6745,6747,6749,6751,6753,6755,6757,6759,6761,6763,6765,6767],{"class":1984,"line":9},[1982,6726,3259],{"class":1993},[1982,6728,2004],{"class":2003},[1982,6730,5243],{"class":2007},[1982,6732,2042],{"class":2003},[1982,6734,1888],{"class":1993},[1982,6736,2004],{"class":2003},[1982,6738,1737],{"class":1993},[1982,6740,2049],{"class":2003},[1982,6742,2053],{"class":2052},[1982,6744,2042],{"class":2003},[1982,6746,2059],{"class":2058},[1982,6748,2062],{"class":2013},[1982,6750,2004],{"class":2003},[1982,6752,2067],{"class":2013},[1982,6754,2049],{"class":2003},[1982,6756,5270],{"class":2058},[1982,6758,5273],{"class":2003},[1982,6760,3259],{"class":2013},[1982,6762,2004],{"class":2003},[1982,6764,5280],{"class":2013},[1982,6766,2078],{"class":2003},[1982,6768,2093],{"class":2003},[1982,6770,6771,6774,6776,6778,6780,6782,6784,6786],{"class":1984,"line":19},[1982,6772,6773],{"class":1993},"    duration",[1982,6775,1997],{"class":1993},[1982,6777,6142],{"class":2007},[1982,6779,2042],{"class":2003},[1982,6781,5313],{"class":1993},[1982,6783,2049],{"class":2003},[1982,6785,6151],{"class":2045},[1982,6787,2142],{"class":2003},[1982,6789,6790],{"class":1984,"line":30},[1982,6791,2361],{"emptyLinePlaceholder":2360},[1982,6793,6794,6796,6799,6802,6805,6808,6810,6813],{"class":1984,"line":2031},[1982,6795,2969],{"class":2099},[1982,6797,6798],{"class":1993}," duration",[1982,6800,6801],{"class":2099}," >",[1982,6803,6804],{"class":2113}," 100",[1982,6806,6807],{"class":1993},"*time",[1982,6809,2004],{"class":2003},[1982,6811,6812],{"class":1993},"Millisecond",[1982,6814,2093],{"class":2003},[1982,6816,6817,6819,6821,6823,6825,6828,6830,6832,6834,6836],{"class":1984,"line":2096},[1982,6818,5289],{"class":1993},[1982,6820,2004],{"class":2003},[1982,6822,3074],{"class":2007},[1982,6824,2042],{"class":2003},[1982,6826,6827],{"class":2045},"\"Slow schema build: ",[1982,6829,3089],{"class":3082},[1982,6831,3096],{"class":2045},[1982,6833,2049],{"class":2003},[1982,6835,6798],{"class":1993},[1982,6837,2142],{"class":2003},[1982,6839,6840],{"class":1984,"line":2119},[1982,6841,2999],{"class":2003},[1982,6843,6844],{"class":1984,"line":2145},[1982,6845,2354],{"class":2003},[3557,6847,1049],{"id":6848},"validation-error-analysis",[1973,6850,6852],{"className":1975,"code":6851,"language":1977,"meta":24,"style":24},"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})\n",[1979,6853,6854,6900,6921,6939,6943,6964],{"__ignoreMap":24},[1982,6855,6856,6858,6860,6862,6864,6866,6868,6870,6872,6874,6876,6878,6880,6882,6884,6886,6888,6890,6892,6894,6896,6898],{"class":1984,"line":9},[1982,6857,3259],{"class":1993},[1982,6859,2004],{"class":2003},[1982,6861,5243],{"class":2007},[1982,6863,2042],{"class":2003},[1982,6865,1888],{"class":1993},[1982,6867,2004],{"class":2003},[1982,6869,1727],{"class":1993},[1982,6871,2049],{"class":2003},[1982,6873,2053],{"class":2052},[1982,6875,2042],{"class":2003},[1982,6877,2059],{"class":2058},[1982,6879,2062],{"class":2013},[1982,6881,2004],{"class":2003},[1982,6883,2067],{"class":2013},[1982,6885,2049],{"class":2003},[1982,6887,5270],{"class":2058},[1982,6889,5273],{"class":2003},[1982,6891,3259],{"class":2013},[1982,6893,2004],{"class":2003},[1982,6895,5280],{"class":2013},[1982,6897,2078],{"class":2003},[1982,6899,2093],{"class":2003},[1982,6901,6902,6905,6907,6910,6912,6914,6916,6919],{"class":1984,"line":19},[1982,6903,6904],{"class":1993},"    errorCount",[1982,6906,1997],{"class":1993},[1982,6908,6909],{"class":2007}," extractInt",[1982,6911,2042],{"class":2003},[1982,6913,5313],{"class":1993},[1982,6915,2049],{"class":2003},[1982,6917,6918],{"class":2045}," \"error_count\"",[1982,6920,2142],{"class":2003},[1982,6922,6923,6925,6927,6929,6931,6933,6935,6937],{"class":1984,"line":30},[1982,6924,6773],{"class":1993},[1982,6926,1997],{"class":1993},[1982,6928,6142],{"class":2007},[1982,6930,2042],{"class":2003},[1982,6932,5313],{"class":1993},[1982,6934,2049],{"class":2003},[1982,6936,6151],{"class":2045},[1982,6938,2142],{"class":2003},[1982,6940,6941],{"class":1984,"line":2031},[1982,6942,2361],{"emptyLinePlaceholder":2360},[1982,6944,6945,6948,6950,6953,6955,6958,6960,6962],{"class":1984,"line":2096},[1982,6946,6947],{"class":1993},"    metrics",[1982,6949,2004],{"class":2003},[1982,6951,6952],{"class":2007},"RecordValidationFailure",[1982,6954,2042],{"class":2003},[1982,6956,6957],{"class":1993},"errorCount",[1982,6959,2049],{"class":2003},[1982,6961,6798],{"class":1993},[1982,6963,2142],{"class":2003},[1982,6965,6966],{"class":1984,"line":2119},[1982,6967,2354],{"class":2003},[1968,6969,1054],{"id":6970},"debugging-with-events",[3557,6972,1058],{"id":6973},"development-logging",[1973,6975,6977],{"className":1975,"code":6976,"language":1977,"meta":24,"style":24},"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}\n",[1979,6978,6979,6990,6995,7013,7024,7034,7044,7054,7064,7069,7073,7077,7097,7107,7151,7195,7200,7204],{"__ignoreMap":24},[1982,6980,6981,6983,6986,6988],{"class":1984,"line":9},[1982,6982,2607],{"class":2052},[1982,6984,6985],{"class":2007}," setupDevLogging",[1982,6987,2622],{"class":2003},[1982,6989,2093],{"class":2003},[1982,6991,6992],{"class":1984,"line":19},[1982,6993,6994],{"class":1987},"    // Log everything in development\n",[1982,6996,6997,7000,7002,7004,7006,7008,7011],{"class":1984,"line":30},[1982,6998,6999],{"class":1993},"    signals",[1982,7001,1997],{"class":1993},[1982,7003,5273],{"class":2003},[1982,7005,3259],{"class":2013},[1982,7007,2004],{"class":2003},[1982,7009,7010],{"class":2013},"Signal",[1982,7012,5721],{"class":2003},[1982,7014,7015,7018,7020,7022],{"class":1984,"line":2031},[1982,7016,7017],{"class":1993},"        flume",[1982,7019,2004],{"class":2003},[1982,7021,1707],{"class":1993},[1982,7023,2295],{"class":2003},[1982,7025,7026,7028,7030,7032],{"class":1984,"line":2096},[1982,7027,7017],{"class":1993},[1982,7029,2004],{"class":2003},[1982,7031,1712],{"class":1993},[1982,7033,2295],{"class":2003},[1982,7035,7036,7038,7040,7042],{"class":1984,"line":2119},[1982,7037,7017],{"class":1993},[1982,7039,2004],{"class":2003},[1982,7041,1717],{"class":1993},[1982,7043,2295],{"class":2003},[1982,7045,7046,7048,7050,7052],{"class":1984,"line":2145},[1982,7047,7017],{"class":1993},[1982,7049,2004],{"class":2003},[1982,7051,1732],{"class":1993},[1982,7053,2295],{"class":2003},[1982,7055,7056,7058,7060,7062],{"class":1984,"line":2151},[1982,7057,7017],{"class":1993},[1982,7059,2004],{"class":2003},[1982,7061,1737],{"class":1993},[1982,7063,2295],{"class":2003},[1982,7065,7066],{"class":1984,"line":2164},[1982,7067,7068],{"class":1987},"        // ... all signals\n",[1982,7070,7071],{"class":1984,"line":2170},[1982,7072,2999],{"class":2003},[1982,7074,7075],{"class":1984,"line":2218},[1982,7076,2361],{"emptyLinePlaceholder":2360},[1982,7078,7079,7081,7083,7085,7088,7090,7092,7095],{"class":1984,"line":2237},[1982,7080,5585],{"class":2099},[1982,7082,2378],{"class":1993},[1982,7084,2049],{"class":2003},[1982,7086,7087],{"class":1993}," signal",[1982,7089,1997],{"class":1993},[1982,7091,5597],{"class":2099},[1982,7093,7094],{"class":1993}," signals",[1982,7096,2093],{"class":2003},[1982,7098,7099,7102,7104],{"class":1984,"line":2248},[1982,7100,7101],{"class":1993},"        s",[1982,7103,1997],{"class":1993},[1982,7105,7106],{"class":1993}," signal\n",[1982,7108,7109,7112,7114,7116,7118,7121,7123,7125,7127,7129,7131,7133,7135,7137,7139,7141,7143,7145,7147,7149],{"class":1984,"line":2253},[1982,7110,7111],{"class":1993},"        capitan",[1982,7113,2004],{"class":2003},[1982,7115,5243],{"class":2007},[1982,7117,2042],{"class":2003},[1982,7119,7120],{"class":1993},"s",[1982,7122,2049],{"class":2003},[1982,7124,2053],{"class":2052},[1982,7126,2042],{"class":2003},[1982,7128,2059],{"class":2058},[1982,7130,2062],{"class":2013},[1982,7132,2004],{"class":2003},[1982,7134,2067],{"class":2013},[1982,7136,2049],{"class":2003},[1982,7138,5270],{"class":2058},[1982,7140,5273],{"class":2003},[1982,7142,3259],{"class":2013},[1982,7144,2004],{"class":2003},[1982,7146,5280],{"class":2013},[1982,7148,2078],{"class":2003},[1982,7150,2093],{"class":2003},[1982,7152,7153,7156,7158,7160,7162,7165,7167,7170,7172,7174,7176,7179,7181,7184,7186,7189,7191,7193],{"class":1984,"line":2258},[1982,7154,7155],{"class":1993},"            log",[1982,7157,2004],{"class":2003},[1982,7159,3074],{"class":2007},[1982,7161,2042],{"class":2003},[1982,7163,7164],{"class":2045},"\"[",[1982,7166,5301],{"class":3082},[1982,7168,7169],{"class":2045},"] ",[1982,7171,3089],{"class":3082},[1982,7173,3096],{"class":2045},[1982,7175,2049],{"class":2003},[1982,7177,7178],{"class":1993}," s",[1982,7180,2004],{"class":2003},[1982,7182,7183],{"class":1993},"Name",[1982,7185,2049],{"class":2003},[1982,7187,7188],{"class":2007}," formatFields",[1982,7190,2042],{"class":2003},[1982,7192,5313],{"class":1993},[1982,7194,3354],{"class":2003},[1982,7196,7197],{"class":1984,"line":2282},[1982,7198,7199],{"class":2003},"        })\n",[1982,7201,7202],{"class":1984,"line":2298},[1982,7203,2999],{"class":2003},[1982,7205,7206],{"class":1984,"line":2351},[1982,7207,2598],{"class":2003},[3557,7209,1063],{"id":7210},"pipeline-access-tracking",[1973,7212,7214],{"className":1975,"code":7213,"language":1977,"meta":24,"style":24},"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})\n",[1979,7215,7216,7262,7280,7301,7305,7317,7341,7357,7367,7382,7386],{"__ignoreMap":24},[1982,7217,7218,7220,7222,7224,7226,7228,7230,7232,7234,7236,7238,7240,7242,7244,7246,7248,7250,7252,7254,7256,7258,7260],{"class":1984,"line":9},[1982,7219,3259],{"class":1993},[1982,7221,2004],{"class":2003},[1982,7223,5243],{"class":2007},[1982,7225,2042],{"class":2003},[1982,7227,1888],{"class":1993},[1982,7229,2004],{"class":2003},[1982,7231,1757],{"class":1993},[1982,7233,2049],{"class":2003},[1982,7235,2053],{"class":2052},[1982,7237,2042],{"class":2003},[1982,7239,2059],{"class":2058},[1982,7241,2062],{"class":2013},[1982,7243,2004],{"class":2003},[1982,7245,2067],{"class":2013},[1982,7247,2049],{"class":2003},[1982,7249,5270],{"class":2058},[1982,7251,5273],{"class":2003},[1982,7253,3259],{"class":2013},[1982,7255,2004],{"class":2003},[1982,7257,5280],{"class":2013},[1982,7259,2078],{"class":2003},[1982,7261,2093],{"class":2003},[1982,7263,7264,7266,7268,7270,7272,7274,7276,7278],{"class":1984,"line":19},[1982,7265,6561],{"class":1993},[1982,7267,1997],{"class":1993},[1982,7269,5308],{"class":2007},[1982,7271,2042],{"class":2003},[1982,7273,5313],{"class":1993},[1982,7275,2049],{"class":2003},[1982,7277,5318],{"class":2045},[1982,7279,2142],{"class":2003},[1982,7281,7282,7285,7287,7290,7292,7294,7296,7299],{"class":1984,"line":30},[1982,7283,7284],{"class":1993},"    found",[1982,7286,1997],{"class":1993},[1982,7288,7289],{"class":2007}," extractBool",[1982,7291,2042],{"class":2003},[1982,7293,5313],{"class":1993},[1982,7295,2049],{"class":2003},[1982,7297,7298],{"class":2045}," \"found\"",[1982,7300,2142],{"class":2003},[1982,7302,7303],{"class":1984,"line":2031},[1982,7304,2361],{"emptyLinePlaceholder":2360},[1982,7306,7307,7309,7312,7315],{"class":1984,"line":2096},[1982,7308,2969],{"class":2099},[1982,7310,7311],{"class":2099}," !",[1982,7313,7314],{"class":1993},"found",[1982,7316,2093],{"class":2003},[1982,7318,7319,7321,7323,7325,7327,7330,7332,7334,7336,7339],{"class":1984,"line":2119},[1982,7320,5289],{"class":1993},[1982,7322,2004],{"class":2003},[1982,7324,3074],{"class":2007},[1982,7326,2042],{"class":2003},[1982,7328,7329],{"class":2045},"\"Pipeline not found: ",[1982,7331,5301],{"class":3082},[1982,7333,3096],{"class":2045},[1982,7335,2049],{"class":2003},[1982,7337,7338],{"class":1993}," name",[1982,7340,2142],{"class":2003},[1982,7342,7343,7346,7348,7351,7353,7355],{"class":1984,"line":2145},[1982,7344,7345],{"class":1993},"        metrics",[1982,7347,2004],{"class":2003},[1982,7349,7350],{"class":2007},"PipelineMiss",[1982,7352,2042],{"class":2003},[1982,7354,6050],{"class":1993},[1982,7356,2142],{"class":2003},[1982,7358,7359,7362,7365],{"class":1984,"line":2151},[1982,7360,7361],{"class":2003},"    }",[1982,7363,7364],{"class":2099}," else",[1982,7366,2093],{"class":2003},[1982,7368,7369,7371,7373,7376,7378,7380],{"class":1984,"line":2164},[1982,7370,7345],{"class":1993},[1982,7372,2004],{"class":2003},[1982,7374,7375],{"class":2007},"PipelineHit",[1982,7377,2042],{"class":2003},[1982,7379,6050],{"class":1993},[1982,7381,2142],{"class":2003},[1982,7383,7384],{"class":1984,"line":2170},[1982,7385,2999],{"class":2003},[1982,7387,7388],{"class":1984,"line":2218},[1982,7389,2354],{"class":2003},[1968,7391,1068],{"id":7392},"production-recommendations",[3557,7394,1072],{"id":7395},"_1-monitor-build-failures",[1891,7397,7398],{},"Build failures indicate configuration issues:",[1973,7400,7402],{"className":1975,"code":7401,"language":1977,"meta":24,"style":24},"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})\n",[1979,7403,7404,7450,7469,7503],{"__ignoreMap":24},[1982,7405,7406,7408,7410,7412,7414,7416,7418,7420,7422,7424,7426,7428,7430,7432,7434,7436,7438,7440,7442,7444,7446,7448],{"class":1984,"line":9},[1982,7407,3259],{"class":1993},[1982,7409,2004],{"class":2003},[1982,7411,5243],{"class":2007},[1982,7413,2042],{"class":2003},[1982,7415,1888],{"class":1993},[1982,7417,2004],{"class":2003},[1982,7419,1742],{"class":1993},[1982,7421,2049],{"class":2003},[1982,7423,2053],{"class":2052},[1982,7425,2042],{"class":2003},[1982,7427,2059],{"class":2058},[1982,7429,2062],{"class":2013},[1982,7431,2004],{"class":2003},[1982,7433,2067],{"class":2013},[1982,7435,2049],{"class":2003},[1982,7437,5270],{"class":2058},[1982,7439,5273],{"class":2003},[1982,7441,3259],{"class":2013},[1982,7443,2004],{"class":2003},[1982,7445,5280],{"class":2013},[1982,7447,2078],{"class":2003},[1982,7449,2093],{"class":2003},[1982,7451,7452,7455,7457,7459,7461,7463,7465,7467],{"class":1984,"line":19},[1982,7453,7454],{"class":2013},"    error",[1982,7456,1997],{"class":1993},[1982,7458,5308],{"class":2007},[1982,7460,2042],{"class":2003},[1982,7462,5313],{"class":1993},[1982,7464,2049],{"class":2003},[1982,7466,5534],{"class":2045},[1982,7468,2142],{"class":2003},[1982,7470,7471,7474,7476,7479,7481,7484,7486,7488,7490,7493,7495,7497,7499,7501],{"class":1984,"line":30},[1982,7472,7473],{"class":1993},"    alerting",[1982,7475,2004],{"class":2003},[1982,7477,7478],{"class":2007},"Page",[1982,7480,2042],{"class":2003},[1982,7482,7483],{"class":1993},"fmt",[1982,7485,2004],{"class":2003},[1982,7487,6667],{"class":2007},[1982,7489,2042],{"class":2003},[1982,7491,7492],{"class":2045},"\"Flume build failed: ",[1982,7494,5301],{"class":3082},[1982,7496,3096],{"class":2045},[1982,7498,2049],{"class":2003},[1982,7500,2088],{"class":2013},[1982,7502,3354],{"class":2003},[1982,7504,7505],{"class":1984,"line":2031},[1982,7506,2354],{"class":2003},[3557,7508,1077],{"id":7509},"_2-track-schema-versions",[1891,7511,7512],{},"Maintain audit trail:",[1973,7514,7516],{"className":1975,"code":7515,"language":1977,"meta":24,"style":24},"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})\n",[1979,7517,7518,7564,7586,7598,7618,7637,7656,7674,7678],{"__ignoreMap":24},[1982,7519,7520,7522,7524,7526,7528,7530,7532,7534,7536,7538,7540,7542,7544,7546,7548,7550,7552,7554,7556,7558,7560,7562],{"class":1984,"line":9},[1982,7521,3259],{"class":1993},[1982,7523,2004],{"class":2003},[1982,7525,5243],{"class":2007},[1982,7527,2042],{"class":2003},[1982,7529,1888],{"class":1993},[1982,7531,2004],{"class":2003},[1982,7533,1752],{"class":1993},[1982,7535,2049],{"class":2003},[1982,7537,2053],{"class":2052},[1982,7539,2042],{"class":2003},[1982,7541,2059],{"class":2058},[1982,7543,2062],{"class":2013},[1982,7545,2004],{"class":2003},[1982,7547,2067],{"class":2013},[1982,7549,2049],{"class":2003},[1982,7551,5270],{"class":2058},[1982,7553,5273],{"class":2003},[1982,7555,3259],{"class":2013},[1982,7557,2004],{"class":2003},[1982,7559,5280],{"class":2013},[1982,7561,2078],{"class":2003},[1982,7563,2093],{"class":2003},[1982,7565,7566,7569,7571,7574,7576,7579,7581,7584],{"class":1984,"line":19},[1982,7567,7568],{"class":1993},"    audit",[1982,7570,2004],{"class":2003},[1982,7572,7573],{"class":2007},"Log",[1982,7575,2042],{"class":2003},[1982,7577,7578],{"class":2013},"audit",[1982,7580,2004],{"class":2003},[1982,7582,7583],{"class":2013},"Entry",[1982,7585,5721],{"class":2003},[1982,7587,7588,7591,7593,7596],{"class":1984,"line":30},[1982,7589,7590],{"class":2285},"        Action",[1982,7592,2289],{"class":2003},[1982,7594,7595],{"class":2045},"     \"schema_update\"",[1982,7597,2295],{"class":2003},[1982,7599,7600,7603,7605,7608,7610,7612,7614,7616],{"class":1984,"line":2031},[1982,7601,7602],{"class":2285},"        Name",[1982,7604,2289],{"class":2003},[1982,7606,7607],{"class":2007},"       extractString",[1982,7609,2042],{"class":2003},[1982,7611,5313],{"class":1993},[1982,7613,2049],{"class":2003},[1982,7615,5318],{"class":2045},[1982,7617,5420],{"class":2003},[1982,7619,7620,7623,7625,7627,7629,7631,7633,7635],{"class":1984,"line":2096},[1982,7621,7622],{"class":2285},"        OldVersion",[1982,7624,2289],{"class":2003},[1982,7626,5308],{"class":2007},[1982,7628,2042],{"class":2003},[1982,7630,5313],{"class":1993},[1982,7632,2049],{"class":2003},[1982,7634,5433],{"class":2045},[1982,7636,5420],{"class":2003},[1982,7638,7639,7642,7644,7646,7648,7650,7652,7654],{"class":1984,"line":2119},[1982,7640,7641],{"class":2285},"        NewVersion",[1982,7643,2289],{"class":2003},[1982,7645,5308],{"class":2007},[1982,7647,2042],{"class":2003},[1982,7649,5313],{"class":1993},[1982,7651,2049],{"class":2003},[1982,7653,5448],{"class":2045},[1982,7655,5420],{"class":2003},[1982,7657,7658,7661,7663,7666,7668,7671],{"class":1984,"line":2145},[1982,7659,7660],{"class":2285},"        Timestamp",[1982,7662,2289],{"class":2003},[1982,7664,7665],{"class":1993},"  time",[1982,7667,2004],{"class":2003},[1982,7669,7670],{"class":2007},"Now",[1982,7672,7673],{"class":2003},"(),\n",[1982,7675,7676],{"class":1984,"line":2151},[1982,7677,5325],{"class":2003},[1982,7679,7680],{"class":1984,"line":2164},[1982,7681,2354],{"class":2003},[3557,7683,1082],{"id":7684},"_3-set-up-dashboards",[1891,7686,7687],{},"Key metrics to display:",[3221,7689,7690,7693,7696,7699,7702],{},[3224,7691,7692],{},"Schema update frequency",[3224,7694,7695],{},"Build success/failure rate",[3224,7697,7698],{},"Build duration percentiles",[3224,7700,7701],{},"Pipeline retrieval hit rate",[3224,7703,7704],{},"Validation error trends",[3557,7706,1087],{"id":7707},"_4-alert-on-anomalies",[3221,7709,7710,7713,7716,7719],{},[3224,7711,7712],{},"Sudden increase in build failures",[3224,7714,7715],{},"Unusually long build times",[3224,7717,7718],{},"High pipeline miss rate",[3224,7720,7721],{},"Validation errors after deployment",[1968,7723,150],{"id":7724},"next-steps",[3221,7726,7727,7734],{},[3224,7728,7729,7733],{},[1894,7730,7732],{"href":7731},"../reference/events","Events Reference"," - Complete event list",[3224,7735,7736,7740],{},[1894,7737,7739],{"href":3257,"rel":7738},[1898],"Capitan Documentation"," - Event system details",[3677,7742,7743],{},"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)}",{"title":24,"searchDepth":19,"depth":19,"links":7745},[7746,7747,7753,7754,7759,7764,7768,7774],{"id":4749,"depth":19,"text":6},{"id":4769,"depth":19,"text":987,"children":7748},[7749,7750,7751,7752],{"id":4772,"depth":30,"text":991},{"id":4862,"depth":30,"text":996},{"id":4936,"depth":30,"text":1001},{"id":4989,"depth":30,"text":1006},{"id":5055,"depth":19,"text":1011},{"id":5198,"depth":19,"text":1016,"children":7755},[7756,7757,7758],{"id":5201,"depth":30,"text":1020},{"id":5655,"depth":30,"text":1025},{"id":6261,"depth":30,"text":1030},{"id":6502,"depth":19,"text":1035,"children":7760},[7761,7762,7763],{"id":6505,"depth":30,"text":1039},{"id":6717,"depth":30,"text":1044},{"id":6848,"depth":30,"text":1049},{"id":6970,"depth":19,"text":1054,"children":7765},[7766,7767],{"id":6973,"depth":30,"text":1058},{"id":7210,"depth":30,"text":1063},{"id":7392,"depth":19,"text":1068,"children":7769},[7770,7771,7772,7773],{"id":7395,"depth":30,"text":1072},{"id":7509,"depth":30,"text":1077},{"id":7684,"depth":30,"text":1082},{"id":7707,"depth":30,"text":1087},{"id":7724,"depth":19,"text":150},{},"2025-12-03T00:00:00.000Z",null,{"title":666,"description":976},[7780,666,7781,4745],"Guide","Monitoring","2025-12-12T00:00:00.000Z","ORfDzArcPxnlKpREkJ6PV_0olb0jNm4nHpl-abcloL8",[7785,7786],{"title":879,"path":878,"stem":1830,"description":881,"children":-1},{"title":1096,"path":1095,"stem":1839,"description":1098,"children":-1},1776189694725]