Skip to content

FermiHDI SDK — Mojo

BETA. Written from scratch in September 2026 and built on every change. Newest of the wrappers; expect the least mileage.

A real binding to the FermiHDI SDK, built on the C ABI in include/fermihdi_c_api.h. Every function in FermiHDISDK.mojo reaches a symbol in libfermihdi_client.so.

History, because it matters

Two files used to sit here and were deleted on 2026-08-27 because neither worked and both reported success while doing nothing -- one had its single FFI call commented out. They had a reason to cheat: the SDK exported no C symbols at all. Go worked only because its C shim (go/sdk_bridge.cpp) is compiled into the cgo package, which is no help to a language with plain FFI.

The fhd_* surface now lives in the shared library, so there is something real to bind to.

Building

mojo build your_program.mojo \
    -Xlinker -L$FERMIHDI_SDK_ROOT/lib \
    -Xlinker -lfermihdi_client \
    -Xlinker -rpath -Xlinker $FERMIHDI_SDK_ROOT/lib

Symbols resolve at link time rather than through dlopen, because dlsym in this Mojo returns a data pointer rather than a callable and there is no supported way to call through it.

For a static binary, link the archive instead and drop the rpath:

mojo build your_program.mojo \
    -Xlinker $FERMIHDI_SDK_ROOT/lib/libfermihdi_client_static.a \
    -Xlinker -lstdc++

Modes

Mojo calls the C ABI's query client directly. That ABI carries a target-setting call and no registration or ingest call, which leaves Mojo in proxy mode (or querying SCC targets it was given) and unable to register as an HD_CLIENT node or to ingest. The SDK overview has the modes and their per-binding support.

API

sdk_version() -> String                      # read from the library, not hardcoded

struct QueryClient:
    QueryClient(proxy_url, data_plane_iface="", ctrl_plane_iface="",
                return_port=6987)
    is_open()   -> Bool
    close()                                   # explicit; see the note below
    stop()
    load_schema(schema_json)     -> Bool
    set_scc_target(ip, port)
    health()                     -> String    # JSON: status (liveness), ready
    generate_query(hdquery_json) -> String    # "" if the full-scan guard refuses
    prepare_query(query_id)                   # arm the listener FIRST
    submit_to_proxy(query_json, query_id) -> String
        # JSON: {"ok":..,"empty":..,"found_batches":[..],"error":".."}
    set_timeout_ms(ms)
    set_filter_verdict(verdict_json) -> Bool    # for a query you dispatched yourself
    false_negatives()            -> String      # JSON: bloomrf_mode, false_negatives
    cancel_query(query_id)

set_filter_verdict() is for a query placed by your own route rather than submit_to_proxy(): pass the proxy's result event JSON verbatim so the SDK knows what the filter service would have excluded. Without it the false-negative check at the end of the query never runs. false_negatives() must come back with an empty list; one entry is a filter defect.

submit_to_proxy() places the query and holds the connection for the life of the query, reporting the ending itself — see §2.3. Nothing else to relay.

Use cases

A Mojo service querying HD directly, with no Python or JVM runtime in the image. Link the static archive for a single binary.

Numeric work on returned records, close to where they land, without an intermediate copy through another runtime.

Usage

from FermiHDISDK import QueryClient, sdk_version

def main():
    print(sdk_version())
    var client = QueryClient(String("https://proxy.example:443"))
    if not client.is_open():
        return
    _ = client.load_schema(schema_json)
    print(client.health())
    client.close()

Gotchas

  • close() is explicit. An external_call inside __deinit__ crashes the current Mojo compiler outright -- kgen.call_param op invalid use of parameter with no declaration callee, reproducible with a three-line struct -- so the destructor cannot be the thing that frees.
  • The full-dataset-scan guard returns "" from generate_query — see §3.2.
  • Query IDs must be distinct across every client talking to the cluster; seed at random rather than from the clock.
  • Advertise an address the storage nodes can reach, or the query returns nothing and reports no error.