>_EXECUTIVE SUMMARY
stryke-scylla is an opt-in connector package in the stryke ecosystem — a ScyllaDB / Apache Cassandra client. It exposes CQL query, DDL, and schema introspection as the Scylla package, against any ScyllaDB or Cassandra cluster over the native CQL binary protocol.
The client is the scylla crate, ScyllaDB's official pure-Rust driver. The cdylib owns one embedded tokio runtime and presents a blocking facade, and ships once on demand rather than being linked into stryke core.
Each public Scylla::* wrapper in lib/Scylla.stk maps to one #[no_mangle] extern "C" fn scylla__* export in src/lib.rs, registered in stryke.toml under [ffi].exports — the surface test pins all 34 wrappers, and the export list, the extern functions, and the wrapper set are kept one-to-one. The 14 unit tests cover the pure logic (escaping, identifier quoting, contact-point normalization, batch construction, CqlValue→JSON, column-position sorting) and run with no cluster.
~TRANSPORT
The client speaks the CQL binary protocol via ScyllaDB's official pure-Rust driver (the scylla crate), which also targets Apache Cassandra. The driver manages a per-node connection pool and token-aware routing internally.
~SYNC OVER ASYNC
The driver is async. Rather than expose futures across the FFI boundary, the cdylib owns a single embedded multi-thread tokio runtime (OnceCell<Runtime>, 2 worker threads, enable_all) and block_ons every driver call, so the stryke-facing API stays synchronous like the other connectors.
~SESSION CACHE + CONNECTION RESOLUTION
A Session is cached in a OnceCell<Mutex<HashMap<ConnKey, Arc<Session>>>> keyed by ConnKey { nodes, username, password, keyspace } — calls sharing those four values reuse the same pooled session; differing on any field opens and caches a distinct one. The connection-free conn_from_opts resolves the opts dict to a ConnKey: a nodes array wins; otherwise node/host (combined with port) is used; an empty result defaults to 127.0.0.1:9042. A contact point without a :port gets the default CQL port appended (normalize_node). The Scylla.stk wrapper fills nodes from $SCYLLA_NODES (comma-split) when the caller passes no node. Auth is applied only when a username or password is non-empty; a non-empty keyspace is USEd on the session right after connect.
| opts key | Resolution |
|---|---|
nodes | Array of contact points; each normalized to host:port. Overrides node/host. |
node / host | Single contact point; port appended when it carries no :port. |
port | Default 9042; combined with node/host. |
username / password | PasswordAuthenticator credentials; applied only when non-empty. |
keyspace | use_keyspace after connect; part of the cache key. |
$ROWS TO JSON
SELECT-style results become an array of row objects keyed by column name (taken from the result's column specs); statements with no result set (DDL/DML) return { "ok": true }, which the row-returning wrappers surface as an empty array. Each CqlValue is mapped by cql_to_json to its natural JSON form, with a debug-string fallback for exotic types so the converter never fails.
| CqlValue | JSON form |
|---|---|
Int, BigInt, SmallInt, TinyInt | JSON number |
Float, Double | JSON number |
Text, Ascii | JSON string |
Boolean | JSON bool |
Uuid | JSON string (the UUID's string form) |
List, Set | JSON array (recursively converted) |
Map | JSON array of [key, value] pairs |
Empty / NULL column | JSON null |
| anything else | format!("{:?}", …) debug string |
&FFI CONTRACT + SAFETY
Each #[no_mangle] extern "C" fn scylla__* is a JSON-string-in / JSON-string-out wrapper. ffi_call parses the argument C-string into a serde_json::Value (null on parse failure), runs the handler inside catch_unwind (AssertUnwindSafe), serializes the result, and hands back a heap CString that stryke later frees via stryke_free_cstring. A handler error becomes { "error": … } and a panic becomes { "error": "stryke-scylla handler panicked" }; the Scylla.stk _decode step turns any error field into a stryke die. Queries are unparameterized CQL — interpolate untrusted values through escape (doubles the single quote per the CQL grammar) or the other pure helpers, which are unit-tested in-crate and validate in CI with no cluster.
+BATCH CONSTRUCTION
batch takes a statements array (errors when missing or empty) and an unlogged flag (default false). build_batch_cql wraps them in a textual BEGIN [UNLOGGED] BATCH … APPLY BATCH; block, trimming each statement and giving it exactly one trailing ; (so no ;;), then runs it as one statement and returns { "ok": true, "count": n }. Atomic within a single partition; cross-partition batches are allowed but not atomic.
| Group | Functions |
|---|---|
| Liveness | version, ping, server_version, cluster_name, peers |
| Query | query, query_row, query_value, execute, batch, raw |
| Introspection | keyspaces, tables, columns, count, indexes, views, types, partition_keys, clustering_keys |
| DDL | create_keyspace, drop_keyspace, create_table, drop_table, create_index, drop_index, truncate |
| Pure helpers | escape, quote_literal, quote_ident, valid_identifier, format_value, format_in_list, contact_points |
/DEPENDENCIES
scylla (CQL binary protocol, rustls TLS), tokio (embedded runtime), serde_json for the FFI payloads, plus anyhow (error type), once_cell (runtime + session statics), and parking_lot (the session-cache mutex). Pure-Rust throughout — no native client library, so the cdylib builds and vendors cleanly.
%BUILD + TEST
The Makefile wraps the standard flow: make debug (cargo build), make test (cargo test then s test t/), make install (s pkg install -g .). cargo test runs the 14 in-crate unit tests with no cluster. On the stryke side, t/test_stryke_scylla_surface.stk asserts all 34 public wrappers resolve and exercises the connection-free helpers; t/test_scylla.stk drives a full keyspace → table → insert → count → query → index → drop lifecycle against a live cluster and short-circuits when ping fails, so a cluster-less CI run still passes the connection-free asserts.
| Tested without a cluster | What it pins |
|---|---|
escape_string / quote_literal / quote_identifier | CQL quote-doubling and identifier quoting |
normalize_node / conn_from_opts / contact_points | Default-port append, nodes-array normalization, localhost fallback |
cql_to_json | Scalar and collection CqlValue→JSON mapping |
format_value / format_in_list | Typed CQL literals and the (NULL) empty-list sentinel |
build_batch_cql | BATCH wrapping, single trailing ;, UNLOGGED variant |
valid_identifier / pluck_column / sort_columns_by_position | Identifier rules, column extraction, key-order sorting |
#PROJECT METADATA
| Item | Value |
|---|---|
| License | MIT |
| Repository | github.com/MenkeTechnologies/stryke-scylla |
| Parent language | strykelang |
| Meta umbrella | MenkeTechnologiesMeta |
| Issues | github.com/MenkeTechnologies/stryke-scylla/issues |