Storm
The Storm plugin browses topics and produces / consumes messages against a Küstenlogik Storm broker. Storm's broker speaks both the native Storm wire and the Kafka wire — the plugin lets you pick which protocol it uses against the same broker, including Confluent Schema Registry decode in Kafka mode.
Package: Kuestenlogik.Bowire.Protocol.Storm (sibling repo, not bundled with the CLI)
Setup
bowire plugin install Kuestenlogik.Bowire.Protocol.Storm
Then point Bowire at a storm:// URL.
Standalone
bowire --url storm://broker.example:9092
Embedded
app.MapBowire(options =>
{
options.ServerUrls.Add("storm://broker.example:9092");
});
In-process testing has a storm://embedded URL that taps the host's broker without going through the network.
URL shapes
storm://broker.example:9092 # single broker, auto-detect protocol
storm://b1:9092,b2:9092 # bootstrap servers CSV
broker.example:9094 # bare host:port also accepted
storm://broker:9092?protocol=storm # force the native Storm wire
storm://broker:9092?protocol=kafka # force the Kafka-compatible wire
storm://broker:9092?protocol=kafka&schema-registry=http://sr:8081 # Kafka-mode + Confluent Schema Registry
storm://embedded # in-process broker tap
Protocol modes
The ?protocol= query parameter picks how StormClientBuilder configures the wire:
| Value | Effect |
|---|---|
storm / native / storm-native |
UseStormProtocol() — max performance, advanced features (SharedMemory transport, batching presets, handler dispatch) |
kafka |
UseKafkaProtocol() — interoperable wire, Confluent Schema Registry support |
auto (default when omitted) |
UseAutoDetect() — try native first, fall back to Kafka |
Unknown values fall back to auto, so a typo never breaks discovery.
Discovery
Connects via StormClient.Create(...).BuildAsync() and surfaces a Cluster service with broker metadata. Topic enumeration on the native Storm protocol is pending an admin/metadata API on the client SDK — once that lands, topics populate the sidebar the same way the Kafka plugin already does via IAdminClient.GetMetadata. Until then, type the topic name into the workbench's method dropdown.
Methods
Per topic, identical shape to Bowire.Protocol.Kafka:
| Method | Kind | Description |
|---|---|---|
consume |
ServerStreaming | Subscribe + yield one JSON envelope per message (topic, partition, offset, timestamp, key/keyBase64, value/valueBase64, bytes) |
produce |
Unary | Publish one message; optional key and partition via metadata |
The envelope shape matches Bowire.Protocol.Kafka byte-for-byte, so a recording captured against one plugin replays against the other — swap the step's protocol string from "kafka" to "storm" (or vice versa).
Schema Registry (Kafka mode)
When the URL carries ?schema-registry=… and the consumed message is framed in the Confluent wire format (0x00 magic byte + 4-byte big-endian schema id + Avro/JSON body), the plugin decodes it on the fly. The envelope's value field then carries the JSON projection and an additional encoding field tags the schema kind ("avro", …). Schemaless topics, plain UTF-8, and opaque binary keep the original fallback path.
The wire-format decoder is duplicated from Bowire.Protocol.Kafka (same KafkaSchemaRegistry + AvroValueToJson types). Two consumers don't justify a third NuGet package — if a third Kafka-wire plugin shows up, the natural refactor is to lift them into a shared library.
Security
Storm reuses the same auth markers as the Kafka plugin — see Authentication:
__bowireMtls__for client-cert + CA bundle (PEM strings, no temp files)__bowireKafkaSasl__for SASL/PLAIN, SCRAM-SHA-256/512, OAUTHBEARER
Both markers are stripped from the metadata dict before it's forwarded as message headers, so secrets never reach the wire.
Mock replay
StormMockEmitter plugs into Bowire's mock server via IBowireMockEmitter. Recordings tagged protocol: "storm" get re-published at the original cadence:
| Metadata key (first step) | Purpose | Default |
|---|---|---|
bootstrap (or bootstrap-servers) |
Broker CSV | localhost:9092 |
Per-step key / partition |
Same knobs as the live produce path | — |
Payload source: responseBinary (base64) wins so binary payloads round-trip byte-for-byte; text-only recordings fall back to UTF-8 of body.
Relationship to the Kafka plugin
Both ship side by side and register under their own protocol id (storm vs kafka). Run them together when a single environment hits both Storm and Kafka brokers; recordings stay portable between the two because the consume / produce envelopes are identical.
See also: Kafka, Authentication, Recording.