github.com/Jeffail/benthos/v3@v3.65.0/public/service/example_stream_builder_yaml_test.go (about) 1 package service_test 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "sync" 8 "time" 9 10 "github.com/Jeffail/benthos/v3/public/service" 11 12 // Import all standard Benthos components 13 _ "github.com/Jeffail/benthos/v3/public/components/all" 14 ) 15 16 // This example demonstrates how to use a stream builder to parse and execute a 17 // full Benthos config. 18 func Example_streamBuilderConfig() { 19 panicOnErr := func(err error) { 20 if err != nil { 21 panic(err) 22 } 23 } 24 25 builder := service.NewStreamBuilder() 26 27 // Set the full Benthos configuration of the stream. 28 err := builder.SetYAML(` 29 input: 30 generate: 31 count: 1 32 interval: 1ms 33 mapping: 'root = "hello world"' 34 35 pipeline: 36 processors: 37 - bloblang: 'root = content().uppercase()' 38 39 output: 40 stdout: {} 41 `) 42 panicOnErr(err) 43 44 // Build a stream with our configured components. 45 stream, err := builder.Build() 46 panicOnErr(err) 47 48 // And run it, blocking until it gracefully terminates once the generate 49 // input has generated a message and it has flushed through the stream. 50 err = stream.Run(context.Background()) 51 panicOnErr(err) 52 53 // Output: HELLO WORLD 54 } 55 56 // This example demonstrates how to use a stream builder to assemble a stream of 57 // Benthos components by adding snippets of configs for different component 58 // types, and then execute it. You can use the Add methods to append any number 59 // of components to the stream, following fan in and fan out patterns for inputs 60 // and outputs respectively. 61 func Example_streamBuilderConfigAddMethods() { 62 panicOnErr := func(err error) { 63 if err != nil { 64 panic(err) 65 } 66 } 67 68 builder := service.NewStreamBuilder() 69 70 err := builder.AddInputYAML(` 71 generate: 72 count: 1 73 interval: 1ms 74 mapping: 'root = "hello world"' 75 `) 76 panicOnErr(err) 77 78 err = builder.AddProcessorYAML(`bloblang: 'root = content().uppercase()'`) 79 panicOnErr(err) 80 81 err = builder.AddOutputYAML(`stdout: {}`) 82 panicOnErr(err) 83 84 // Build a stream with our configured components. 85 stream, err := builder.Build() 86 panicOnErr(err) 87 88 // And run it, blocking until it gracefully terminates once the generate 89 // input has generated a message and it has flushed through the stream. 90 err = stream.Run(context.Background()) 91 panicOnErr(err) 92 93 // Output: HELLO WORLD 94 } 95 96 // This example demonstrates how to use a stream builder to assemble a 97 // processing pipeline that you can push messages into and extract via closures. 98 func Example_streamBuilderPush() { 99 panicOnErr := func(err error) { 100 if err != nil { 101 panic(err) 102 } 103 } 104 105 builder := service.NewStreamBuilder() 106 err := builder.SetLoggerYAML(`level: NONE`) 107 panicOnErr(err) 108 109 err = builder.AddProcessorYAML(`bloblang: 'root = content().uppercase()'`) 110 panicOnErr(err) 111 112 err = builder.AddProcessorYAML(`bloblang: 'root = "check this out: " + content()'`) 113 panicOnErr(err) 114 115 // Obtain a closure func that allows us to push data into the stream, this 116 // is treated like any other input, which also means it's possible to use 117 // this along with regular configured inputs. 118 sendFn, err := builder.AddProducerFunc() 119 panicOnErr(err) 120 121 // Define a closure func that receives messages as an output of the stream. 122 // It's also possible to use this along with regular configured outputs. 123 var outputBuf bytes.Buffer 124 err = builder.AddConsumerFunc(func(c context.Context, m *service.Message) error { 125 msgBytes, err := m.AsBytes() 126 if err != nil { 127 return err 128 } 129 130 _, err = fmt.Fprintf(&outputBuf, "received: %s\n", msgBytes) 131 return err 132 }) 133 panicOnErr(err) 134 135 stream, err := builder.Build() 136 panicOnErr(err) 137 138 go func() { 139 perr := sendFn(context.Background(), service.NewMessage([]byte("hello world"))) 140 panicOnErr(perr) 141 142 perr = sendFn(context.Background(), service.NewMessage([]byte("I'm pushing data into the stream"))) 143 panicOnErr(perr) 144 145 perr = stream.StopWithin(time.Second) 146 panicOnErr(perr) 147 }() 148 149 // And run it, blocking until it gracefully terminates once the generate 150 // input has generated a message and it has flushed through the stream. 151 err = stream.Run(context.Background()) 152 panicOnErr(err) 153 154 fmt.Println(outputBuf.String()) 155 156 // Output: received: check this out: HELLO WORLD 157 // received: check this out: I'M PUSHING DATA INTO THE STREAM 158 } 159 160 // This example demonstrates using the stream builder API to create and run two 161 // independent streams. 162 func Example_streamBuilderMultipleStreams() { 163 panicOnErr := func(err error) { 164 if err != nil { 165 panic(err) 166 } 167 } 168 169 // Build the first stream pipeline. Note that we configure each pipeline 170 // with its HTTP server disabled as otherwise we would see a port collision 171 // when they both attempt to bind to the default address `0.0.0.0:4195`. 172 // 173 // Alternatively, we could choose to configure each with their own address 174 // with the field `http.address`, or we could call `SetHTTPMux` on the 175 // builder in order to explicitly override the configured server. 176 builderOne := service.NewStreamBuilder() 177 178 err := builderOne.SetYAML(` 179 http: 180 enabled: false 181 182 input: 183 generate: 184 count: 1 185 interval: 1ms 186 mapping: 'root = "hello world one"' 187 188 pipeline: 189 processors: 190 - bloblang: 'root = content().uppercase()' 191 192 output: 193 stdout: {} 194 `) 195 panicOnErr(err) 196 197 streamOne, err := builderOne.Build() 198 panicOnErr(err) 199 200 builderTwo := service.NewStreamBuilder() 201 202 err = builderTwo.SetYAML(` 203 http: 204 enabled: false 205 206 input: 207 generate: 208 count: 1 209 interval: 1ms 210 mapping: 'root = "hello world two"' 211 212 pipeline: 213 processors: 214 - sleep: 215 duration: 500ms 216 - bloblang: 'root = content().capitalize()' 217 218 output: 219 stdout: {} 220 `) 221 panicOnErr(err) 222 223 streamTwo, err := builderTwo.Build() 224 panicOnErr(err) 225 226 var wg sync.WaitGroup 227 wg.Add(2) 228 229 go func() { 230 defer wg.Done() 231 panicOnErr(streamOne.Run(context.Background())) 232 }() 233 go func() { 234 defer wg.Done() 235 panicOnErr(streamTwo.Run(context.Background())) 236 }() 237 238 wg.Wait() 239 240 // Output: HELLO WORLD ONE 241 // Hello World Two 242 }