feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
## C-compatible FFI wrapper around the SDS ReliabilityManager.
|
|
|
|
|
##
|
|
|
|
|
## Built on the `nim-ffi` 0.2 package's high-level macros: `declareLibrary`
|
|
|
|
|
## emits the bootstrap plus the per-event listener registry
|
|
|
|
|
## (`sds_add_event_listener` / `sds_remove_event_listener`);
|
|
|
|
|
## `{.ffiCtor.}`/`{.ffi.}`/`{.ffiDtor.}` generate the C entry points,
|
|
|
|
|
## marshalling parameters and return values as CBOR; `{.ffiEvent.}` declares
|
|
|
|
|
## the library-initiated events (also CBOR). Exported C names are snake_case
|
|
|
|
|
## (`sds_wrap_outgoing_message`, …); see `library/libsds.h`. The Go bindings
|
|
|
|
|
## (sds-go-bindings) must match this API.
|
|
|
|
|
##
|
|
|
|
|
## The one exception is `sds_set_retrieval_hint_provider`: it takes a C
|
|
|
|
|
## function pointer, which has no sensible CBOR representation, so it is
|
|
|
|
|
## hand-written and dispatched to the worker thread (the pointers travel as
|
|
|
|
|
## uint64 through the request channel) to store the provider in a thread-local.
|
|
|
|
|
|
|
|
|
|
import system/ansi_c
|
2026-06-03 09:46:52 +02:00
|
|
|
import ffi
|
|
|
|
|
import sds
|
|
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
# Bootstrap (pragmas, linker flags, libsdsNimMain, initializeLibrary) plus the
|
|
|
|
|
# `sds_add_event_listener` / `sds_remove_event_listener` C exports and the
|
|
|
|
|
# per-type `ReliabilityManagerFFIPool` used by the hand-written entry point
|
|
|
|
|
# below (the ffiCtor/ffiDtor macros declare it too, guarded by `when not
|
|
|
|
|
# declared`).
|
|
|
|
|
declareLibrary("sds", ReliabilityManager)
|
2026-06-03 09:46:52 +02:00
|
|
|
|
|
|
|
|
type SdsRetrievalHintProvider* = proc(
|
|
|
|
|
messageId: cstring, hint: ptr cstring, hintLen: ptr csize_t, userData: pointer
|
|
|
|
|
) {.cdecl, gcsafe, raises: [].}
|
|
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
# The active retrieval-hint provider, stored per worker thread (one thread per
|
|
|
|
|
# context). Set by sds_set_retrieval_hint_provider via a dispatched request so
|
|
|
|
|
# the write lands on the worker thread, where the manager's hint closure reads
|
|
|
|
|
# it during message processing.
|
|
|
|
|
var sdsRetrievalHintCb {.threadvar.}: pointer
|
|
|
|
|
var sdsRetrievalHintUserData {.threadvar.}: pointer
|
2025-05-29 16:48:53 +05:30
|
|
|
|
2026-06-03 09:46:52 +02:00
|
|
|
################################################################################
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
### CBOR-marshalled request/response types
|
2026-01-29 15:22:40 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
type SdsConfig* {.ffi.} = object
|
|
|
|
|
participantId: string ## empty disables SDS-R (see newReliabilityManager)
|
feat: make Persistence interface async (#69)
* feat: make Persistence interface async
The 14 Persistence proc fields now return Future[...] with
{.async: (raises: []), gcsafe.}, allowing real I/O backends (SQLite,
encrypted file, network) to suspend rather than block the Chronos event
loop the manager runs on.
Propagates through:
- ReliabilityManager.lock: system.Lock -> chronos.AsyncLock. Acquired
across awaits cleanly; matches the single-threaded Chronos worker the
FFI uses. Multi-OS-thread use is now explicitly the caller's
responsibility.
- sds_utils + sds.nim public API procs (wrapOutgoingMessage,
unwrapReceivedMessage, markDependenciesMet, setCallbacks,
resetReliabilityManager, cleanup, ensureChannel, removeChannel, the
getter snapshots, etc.) are now async.
- FFI request handlers in library/sds_thread/... await the new API.
- Tests converted via an asyncTest template that wraps each test body
in an async proc; setup/teardown use waitFor for their single async
call (ensureChannel / cleanup).
Lock scope is preserved exactly: the same call sites that held the
kernel Lock today hold AsyncLock now -- no new locking added.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* refactor: drop asyncSpawn, add asyncSetup/asyncTeardown
Three asyncSpawn usages removed:
- sds.nim startPeriodicTasks: stored the periodic-task futures on
ReliabilityManager (new field `periodicTasks: seq[FutureBase]`) so
cleanup can cancel them on shutdown instead of leaking the loops
against a cleared manager.
- library/sds_thread/sds_thread.nim: fireSync moved BEFORE processing,
then `await SdsThreadRequest.process(...)` instead of asyncSpawn'ing
it. Aligns the worker with the SP-channel + lock assumption that
there are no concurrent requests; caller throughput is unchanged
because the caller only waits for receipt (fireSync), not processing.
- tests TestBus repair callback: replaced asyncSpawn(deliverExcept...)
with an explicit pending-delivery queue drained by `bus.drain()`.
Integration tests no longer rely on `sleepAsync(10ms)` to let
spawned deliveries finish — they await drain instead.
Tests also pick up an asyncSetup/asyncTeardown pair (tests/async_unittest.nim)
so suite fixtures can `await` directly. All `waitFor` in setup/teardown
blocks is gone; only the top-level asyncTest wrapper still uses waitFor
(once, to drive the async proc to completion).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Correctly propagate error hidden by new async move
* Correctly handle future cancellation exceptions, +some housekeeping
* Apply suggestion from @Ivansete-status
Co-authored-by: Ivan FB <128452529+Ivansete-status@users.noreply.github.com>
* Stylistics, async default implication addressed, nph style run
* Remove leaking CancelledFuture from public facing + as a consequence it is tuneled into handling CatchableError everywhere
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Ivan FB <128452529+Ivansete-status@users.noreply.github.com>
2026-05-25 22:30:15 +02:00
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
type SdsWrapRequest* {.ffi.} = object
|
|
|
|
|
message: seq[byte]
|
|
|
|
|
messageId: string
|
|
|
|
|
channelId: string
|
2026-01-29 15:22:40 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
type SdsWrapResponse* {.ffi.} = object
|
|
|
|
|
message: seq[byte]
|
2026-06-03 09:46:52 +02:00
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
type SdsUnwrapRequest* {.ffi.} = object
|
|
|
|
|
message: seq[byte]
|
2026-06-03 09:46:52 +02:00
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
# One missing dependency: the message id plus an optional retrieval hint. The
|
|
|
|
|
# hint is a raw byte string on the CBOR wire (no base64, unlike the old JSON).
|
|
|
|
|
type SdsMissingDep* {.ffi.} = object
|
|
|
|
|
messageId: string
|
|
|
|
|
retrievalHint: seq[byte]
|
2026-06-03 09:46:52 +02:00
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
type SdsUnwrapResponse* {.ffi.} = object
|
|
|
|
|
message: seq[byte]
|
|
|
|
|
channelId: string
|
|
|
|
|
missingDeps: seq[SdsMissingDep]
|
2026-06-03 09:46:52 +02:00
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
type SdsMarkDependenciesRequest* {.ffi.} = object
|
|
|
|
|
messageIds: seq[string]
|
|
|
|
|
channelId: string
|
2025-05-29 16:48:53 +05:30
|
|
|
|
|
|
|
|
################################################################################
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
### Library-initiated events (CBOR EventEnvelope via {.ffiEvent.})
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
type SdsMessageReadyEvent* {.ffi.} = object
|
|
|
|
|
messageId: string
|
|
|
|
|
channelId: string
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
type SdsMessageSentEvent* {.ffi.} = object
|
|
|
|
|
messageId: string
|
|
|
|
|
channelId: string
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
type SdsMissingDependenciesEvent* {.ffi.} = object
|
|
|
|
|
messageId: string
|
|
|
|
|
missingDeps: seq[SdsMissingDep]
|
|
|
|
|
channelId: string
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
type SdsPeriodicSyncEvent* {.ffi.} = object
|
|
|
|
|
ok: bool ## carries no data; a field keeps the CBOR map non-degenerate
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
type SdsRepairReadyEvent* {.ffi.} = object
|
|
|
|
|
message: seq[byte]
|
|
|
|
|
channelId: string
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
proc onMessageReady*(evt: SdsMessageReadyEvent) {.ffiEvent: "message_ready".}
|
|
|
|
|
proc onMessageSent*(evt: SdsMessageSentEvent) {.ffiEvent: "message_sent".}
|
|
|
|
|
proc onMissingDependencies*(
|
|
|
|
|
evt: SdsMissingDependenciesEvent
|
|
|
|
|
) {.ffiEvent: "missing_dependencies".}
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
proc onPeriodicSync*(evt: SdsPeriodicSyncEvent) {.ffiEvent: "periodic_sync".}
|
|
|
|
|
proc onRepairReady*(evt: SdsRepairReadyEvent) {.ffiEvent: "repair_ready".}
|
2026-01-29 15:22:40 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
proc toMissingDeps(entries: seq[HistoryEntry]): seq[SdsMissingDep] =
|
|
|
|
|
var deps = newSeq[SdsMissingDep](entries.len)
|
|
|
|
|
for i, entry in entries:
|
|
|
|
|
deps[i] =
|
|
|
|
|
SdsMissingDep(messageId: entry.messageId, retrievalHint: entry.retrievalHint)
|
|
|
|
|
return deps
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
################################################################################
|
|
|
|
|
### Constructor — creates the FFI context and the ReliabilityManager.
|
|
|
|
|
###
|
|
|
|
|
### The event closures run on the worker thread and forward CBOR payloads to
|
|
|
|
|
### the listeners registered via sds_add_event_listener (the {.ffiEvent.} procs
|
|
|
|
|
### read the per-thread event queue, so no context handle is needed here).
|
|
|
|
|
|
|
|
|
|
proc sdsCreate*(
|
|
|
|
|
config: SdsConfig
|
|
|
|
|
): Future[Result[ReliabilityManager, string]] {.ffiCtor.} =
|
|
|
|
|
# The ctor body runs on the (possibly recycled) worker thread. Drop any
|
|
|
|
|
# retrieval-hint provider left over from a previous owner of this thread so a
|
|
|
|
|
# stale C function pointer is never invoked.
|
|
|
|
|
sdsRetrievalHintCb = nil
|
|
|
|
|
sdsRetrievalHintUserData = nil
|
|
|
|
|
|
|
|
|
|
let rm = newReliabilityManager(
|
|
|
|
|
participantId = config.participantId.SdsParticipantID
|
|
|
|
|
).valueOr:
|
|
|
|
|
error "Failed creating reliability manager", error = error
|
|
|
|
|
return err("Failed creating reliability manager: " & $error)
|
|
|
|
|
|
|
|
|
|
let messageReadyCb = proc(
|
|
|
|
|
messageId: SdsMessageID, channelId: SdsChannelID
|
|
|
|
|
) {.gcsafe.} =
|
|
|
|
|
onMessageReady(SdsMessageReadyEvent(messageId: messageId, channelId: channelId))
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
let messageSentCb = proc(
|
|
|
|
|
messageId: SdsMessageID, channelId: SdsChannelID
|
|
|
|
|
) {.gcsafe.} =
|
|
|
|
|
onMessageSent(SdsMessageSentEvent(messageId: messageId, channelId: channelId))
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
let missingDependenciesCb = proc(
|
|
|
|
|
messageId: SdsMessageID, missingDeps: seq[HistoryEntry], channelId: SdsChannelID
|
|
|
|
|
) {.gcsafe.} =
|
|
|
|
|
onMissingDependencies(
|
|
|
|
|
SdsMissingDependenciesEvent(
|
|
|
|
|
messageId: messageId,
|
|
|
|
|
missingDeps: toMissingDeps(missingDeps),
|
|
|
|
|
channelId: channelId,
|
|
|
|
|
)
|
|
|
|
|
)
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
let periodicSyncCb = proc() {.gcsafe.} =
|
|
|
|
|
onPeriodicSync(SdsPeriodicSyncEvent(ok: true))
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
let repairReadyCb = proc(message: seq[byte], channelId: SdsChannelID) {.gcsafe.} =
|
|
|
|
|
onRepairReady(SdsRepairReadyEvent(message: message, channelId: channelId))
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
let retrievalHintProvider = proc(messageId: SdsMessageID): seq[byte] {.gcsafe.} =
|
|
|
|
|
if sdsRetrievalHintCb.isNil():
|
|
|
|
|
return @[]
|
|
|
|
|
var hint: cstring
|
|
|
|
|
var hintLen: csize_t
|
|
|
|
|
cast[SdsRetrievalHintProvider](sdsRetrievalHintCb)(
|
|
|
|
|
messageId.cstring, addr hint, addr hintLen, sdsRetrievalHintUserData
|
|
|
|
|
)
|
|
|
|
|
if not hint.isNil() and hintLen > 0:
|
|
|
|
|
var hintBytes = newSeq[byte](hintLen)
|
|
|
|
|
copyMem(addr hintBytes[0], hint, hintLen)
|
|
|
|
|
# The provider allocates *hint with libc malloc (Go's C.CBytes); free it
|
|
|
|
|
# with libc free, not Nim's deallocShared, to keep the allocator paired.
|
|
|
|
|
c_free(cast[pointer](hint))
|
|
|
|
|
return hintBytes
|
|
|
|
|
return @[]
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
await rm.setCallbacks(
|
|
|
|
|
messageReadyCb, messageSentCb, missingDependenciesCb, periodicSyncCb,
|
|
|
|
|
retrievalHintProvider, repairReadyCb,
|
|
|
|
|
)
|
2025-07-17 14:13:21 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
return ok(rm)
|
2025-07-17 14:13:21 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
################################################################################
|
|
|
|
|
### Async methods — each runs its body on the worker thread.
|
|
|
|
|
|
|
|
|
|
proc sdsWrapOutgoingMessage*(
|
|
|
|
|
rm: ReliabilityManager, req: SdsWrapRequest
|
|
|
|
|
): Future[Result[SdsWrapResponse, string]] {.ffi.} =
|
|
|
|
|
let wrapped = (
|
|
|
|
|
await wrapOutgoingMessage(rm, req.message, req.messageId, req.channelId)
|
|
|
|
|
).valueOr:
|
|
|
|
|
error "WRAP_MESSAGE failed", error = error
|
|
|
|
|
return err("error processing wrap request: " & $error)
|
|
|
|
|
return ok(SdsWrapResponse(message: wrapped))
|
|
|
|
|
|
|
|
|
|
proc sdsUnwrapReceivedMessage*(
|
|
|
|
|
rm: ReliabilityManager, req: SdsUnwrapRequest
|
|
|
|
|
): Future[Result[SdsUnwrapResponse, string]] {.ffi.} =
|
|
|
|
|
let (unwrapped, missingDeps, channelId) = (
|
|
|
|
|
await unwrapReceivedMessage(rm, req.message)
|
|
|
|
|
).valueOr:
|
|
|
|
|
return err("error processing unwrap request: " & $error)
|
|
|
|
|
|
|
|
|
|
return ok(
|
|
|
|
|
SdsUnwrapResponse(
|
|
|
|
|
message: unwrapped, channelId: channelId, missingDeps: toMissingDeps(missingDeps)
|
|
|
|
|
)
|
2025-05-29 16:48:53 +05:30
|
|
|
)
|
|
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
proc sdsMarkDependenciesMet*(
|
|
|
|
|
rm: ReliabilityManager, req: SdsMarkDependenciesRequest
|
|
|
|
|
): Future[Result[string, string]] {.ffi.} =
|
|
|
|
|
(await markDependenciesMet(rm, req.messageIds, req.channelId)).isOkOr:
|
|
|
|
|
error "MARK_DEPENDENCIES_MET failed", error = error
|
|
|
|
|
return err("error processing mark-dependencies request: " & $error)
|
|
|
|
|
return ok("")
|
|
|
|
|
|
|
|
|
|
proc sdsReset*(rm: ReliabilityManager): Future[Result[string, string]] {.ffi.} =
|
|
|
|
|
(await resetReliabilityManager(rm)).isOkOr:
|
|
|
|
|
error "RESET failed", error = error
|
|
|
|
|
return err("error processing reset request: " & $error)
|
|
|
|
|
return ok("")
|
|
|
|
|
|
|
|
|
|
proc sdsStartPeriodicTasks*(
|
|
|
|
|
rm: ReliabilityManager
|
|
|
|
|
): Future[Result[string, string]] {.ffi.} =
|
|
|
|
|
# The empty await forces the macro down its async path so the body runs on the
|
|
|
|
|
# worker thread — startPeriodicTasks schedules futures on that thread's loop.
|
|
|
|
|
await sleepAsync(chronos.milliseconds(0))
|
|
|
|
|
rm.startPeriodicTasks()
|
|
|
|
|
return ok("")
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
################################################################################
|
|
|
|
|
### Destructor — runs library cleanup then tears down the FFI context.
|
|
|
|
|
|
|
|
|
|
proc sdsDestroy*(rm: ReliabilityManager) {.ffiDtor.} =
|
|
|
|
|
discard
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
################################################################################
|
|
|
|
|
### Retrieval-hint provider (hand-written: a C function pointer cannot be passed
|
|
|
|
|
### as CBOR). The setter dispatches a request — the provider/userData pointers
|
|
|
|
|
### travel as uint64 — so the provider is stored in the worker thread's
|
|
|
|
|
### thread-local, where sdsCreate's hint closure reads it.
|
|
|
|
|
|
|
|
|
|
proc sdsNoopCallback(
|
|
|
|
|
callerRet: cint, msg: ptr cchar, len: csize_t, userData: pointer
|
|
|
|
|
) {.cdecl, gcsafe, raises: [].} =
|
|
|
|
|
discard
|
|
|
|
|
|
|
|
|
|
registerReqFFI(SdsSetHintReq, ctx: ptr FFIContext[ReliabilityManager]):
|
|
|
|
|
proc(cbPtr: uint64, udPtr: uint64): Future[Result[string, string]] {.async.} =
|
|
|
|
|
sdsRetrievalHintCb = cast[pointer](cbPtr)
|
|
|
|
|
sdsRetrievalHintUserData = cast[pointer](udPtr)
|
|
|
|
|
return ok("")
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
proc sds_set_retrieval_hint_provider(
|
2026-06-03 09:46:52 +02:00
|
|
|
ctx: ptr FFIContext[ReliabilityManager],
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
callback: SdsRetrievalHintProvider,
|
2025-05-29 16:48:53 +05:30
|
|
|
userData: pointer,
|
2026-06-03 09:46:52 +02:00
|
|
|
): cint {.dynlib, exportc, cdecl, raises: [].} =
|
2025-05-29 16:48:53 +05:30
|
|
|
initializeLibrary()
|
2026-06-03 09:46:52 +02:00
|
|
|
if not ReliabilityManagerFFIPool.isValidCtx(cast[pointer](ctx)):
|
|
|
|
|
return RET_ERR
|
2025-05-29 16:48:53 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
let sendRes =
|
|
|
|
|
try:
|
|
|
|
|
ffi_context.sendRequestToFFIThread(
|
|
|
|
|
ctx,
|
|
|
|
|
SdsSetHintReq.ffiNewReq(
|
|
|
|
|
sdsNoopCallback, nil, cast[uint64](cast[pointer](callback)),
|
|
|
|
|
cast[uint64](userData),
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
Result[void, string].err("sendRequestToFFIThread exception: " & exc.msg)
|
|
|
|
|
if sendRes.isErr():
|
2025-07-17 14:13:21 +05:30
|
|
|
return RET_ERR
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
return RET_OK
|
2025-07-17 14:13:21 +05:30
|
|
|
|
feat: adapt libsds to nim-ffi 0.2 CBOR ABI
Rebuild the C wrapper on nim-ffi 0.2's high-level macros (declareLibrary +
{.ffiCtor.}/{.ffi.}/{.ffiEvent.}), which marshal parameters and results as
CBOR and expose snake_case sds_* entry points. Replaces the previous
hand-written positional/JSON ABI.
- request/response objects are {.ffi.} types (CBOR); the unwrap response is
a proper nested object (message, channelId, missingDeps) instead of
hand-built JSON, and retrievalHint travels as raw bytes (no base64).
- events become {.ffiEvent.} procs (message_ready, message_sent,
missing_dependencies, periodic_sync, repair_ready), delivered to the host
via sds_add_event_listener.
- the retrieval-hint provider stays hand-written (a C function pointer has
no CBOR form); its pointers travel as uint64 through the request channel,
and the provided buffer is freed with libc free to match the host's
malloc (Go's C.CBytes).
- pin nim-ffi at the fix/foreign-host-concurrency-v0.2 branch (recycle pool
+ foreign-thread GC fixes) and add the cbor_serialization dependency.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 23:36:22 +02:00
|
|
|
# Emit binding metadata (no-op unless -d:ffiGenBindings). Must follow every
|
|
|
|
|
# {.ffi.}/{.ffiCtor.}/{.ffiDtor.} annotation.
|
|
|
|
|
genBindings()
|