>_EXECUTIVE SUMMARY
stryke-kafka is one of the opt-in connector packages in the stryke ecosystem. Apache Kafka client for stryke — producer, consumer, admin, and consumer-group lag. Opt-in package backed by rdkafka (librdkafka bindings); ships as a Rust cdylib that stryke dlopens in-process on first use Kafka.
librdkafka is the canonical native Kafka client. Bundled here as an opt-in stryke package so workflows that need it don't bloat the core binary.
Counts: 56 public Kafka::* functions in lib/Kafka.stk (2 producer, 2 consumer, 4 consumer-offset, 13 admin/metadata, 1 plumbing, 34 pure no-broker helpers), exposed over 55 kafka__* extern "C" exports in src/lib.rs — version reuses kafka__pkg_version and consume_stream reuses kafka__consume, so the public surface is one wider than the export list.
~ARCHITECTURE
In-process cdylib design: the stryke side is a thin .stk wrapper that calls FFI symbols on the dlopen'd library. No subprocess, no pipe — calls return on the same thread that made them.
| Layer | Implementation |
|---|---|
stryke wrappers (lib/*.stk) | Thin .stk wrapper (Kafka); exposes typed helpers that serialize args to JSON and parse the response |
cdylib (libstryke_kafka.{dylib,so}) | Single Rust cdylib crate (statically links librdkafka via rdkafka's cmake-build); every public surface fn is an extern "C" fn kafka__<verb>(*const c_char) -> *mut c_char |
| Process model | Library is dlopen'd once per stryke session on first use Kafka; a shared tokio runtime + a FutureProducer + admin-client cache per brokers tuple held in OnceCell; lives until the runtime exits |
| Build | Cargo with [lib] crate-type = ["cdylib"]; publish = false; the package itself ships via s pkg install -g . |
| Install path | ~/.stryke/store/kafka@<version>/ after make install; use Kafka from any stryke script resolves it |
| Tests | zunit-style under t/ with live-service variants when applicable |
| CI | GitHub Actions .github/workflows/ci.yml — cargo check / fmt / clippy / test (ubuntu + macOS) / doc, a cross-target release build (linux-gnu, x86_64 + aarch64 darwin) uploading the cdylib artifact, plus docs / polish / semantic / newline / structure gate jobs |
$WHY OPT-IN (NOT BUILTIN)
librdkafka is the canonical native Kafka client. Bundled here as an opt-in stryke package so workflows that need it don't bloat the core binary.
The trade-off is intentional. The core stryke binary stays under ~40 MB precisely because each connector ships separately. Daily-driver work (one-liners, awk replacement, data scripting) doesn't need MongoDB drivers, AWS SDKs, or Spark Connect bindings linked in.
&FFI ENVELOPE
JSON in / JSON out across the FFI boundary. Each Kafka::* wrapper builds a per-call args hash, to_jsons it, and calls the matching kafka__* symbol on the dlopen'd cdylib — the operation is encoded in the symbol name (e.g. kafka__produce), not a field in the payload. The cdylib returns a JSON string; the wrapper's Kafka::_decode runs from_json, and if the result is a hash carrying an error key it dies with Kafka::<op>: <reason>, otherwise it returns the decoded value directly.
# request shape — the per-fn args hash the .stk wrapper builds,
# merged with the caller's connection opts (brokers)
{"topic": "events", "value": "hi", "key": "k1"} # e.g. kafka__produce
# response shape
{ ...per-fn result... } # success — returned to the caller as-is
{"error": "<msg>"} # failure — wrapper dies with Kafka::<op>: <reason>
Connection options are merged by Kafka::_req, which copies the caller's brokers opt into the request when present; the cdylib otherwise falls back to $KAFKA_BROKERS (default localhost:9092).
[]SURFACE BY FAMILY
The public surface in lib/Kafka.stk groups into six families. Broker-bound families issue real metadata / produce / consume / admin requests; the pure family computes Kafka semantics offline (partition prediction, rebalance planning, config validation, topic-name hygiene) with no broker round trip.
| Family | Count | Functions |
|---|---|---|
| Producer | 2 | produce, produce_many |
| Consumer | 2 | consume, consume_stream |
| Consumer offsets | 4 | lag, watermarks, offsets_for_times, committed |
| Admin / metadata | 13 | ping, cluster, topics, describe, groups, describe_group, create_topic, delete_topic, create_partitions, describe_configs, alter_configs, delete_groups, delete_records |
| Plumbing | 1 | version |
| Pure (no broker) | 34 | topic-name (valid_topic_name, sanitize_topic_name, is_internal_topic, topics_collide, topic_metric_name), brokers (parse_brokers, build_brokers, normalize_brokers), partitioners (partition_for_key, partition_for_key_crc32, partition_for_key_fnv1a, partition_distribution), coordinators (group_coordinator_partition, transaction_coordinator_partition), assignors (range_assignment, roundrobin_assignment, sticky_assignment, replica_assignment, assignment_by_broker, assignment_diff), offsets / config (format_offset, parse_topic_partition, format_topic_partition, compression_codec, cleanup_policy, acks_value, parse_duration_ms, humanize_duration_ms, isr_health, offset_lag, security_protocol, auto_offset_reset, isolation_level, timestamp_type) |
+DEPENDENCIES
The cdylib is self-contained: rdkafka's cmake-build feature compiles librdkafka from source rather than linking a system .so, adding ~3-5 minutes to a first build (subsequent builds reuse the cached static archive).
| Crate | Version | Role |
|---|---|---|
rdkafka | 0.39 (cmake-build, libz, tokio) | librdkafka binding — producer, consumer, admin client |
tokio | 1 (multi-thread rt) | shared async runtime held in OnceCell |
serde / serde_json | 1 (preserve_order) | JSON envelope (de)serialization |
indexmap | 2 | order-preserving maps for JSON output |
futures | 0.3 | async combinators for batched produce |
once_cell / parking_lot | 1 / 0.12 | runtime + per-brokers client cache |
anyhow | 1 | error context inside the cdylib |
Release profile: opt-level = 3, lto = "thin", codegen-units = 1, strip = true, panic = "abort".
/SCOPE
See the README's "Why this is a package" + "API reference" sections for the authoritative scope. The package is intentionally narrower than its underlying SDK / driver — the goal is "useful from a shell pipeline", not "complete API coverage". Shipped: produce with keys/headers/partitions/timestamps + binary framing, consume with headers/binary/offset-commit, consumer-group lag, watermarks, time-based offset lookup, topic config on create, create_partitions, describe/alter configs, delete_groups, describe_group, committed offsets, and delete_records (truncate to offset). Deferred: SASL / SSL connection options, a long-running consumer daemon (callback streaming), consumer seek / position, Schema Registry value modes, a Streams DSL, and a transactional producer (EOS).
#PROJECT METADATA
| Item | Value |
|---|---|
| License | MIT |
| Author | MenkeTechnologies |
| Repository | github.com/MenkeTechnologies/stryke-kafka |
| Parent language | strykelang |
| Meta umbrella | MenkeTechnologiesMeta |
| Issues | github.com/MenkeTechnologies/stryke-kafka/issues |