Pure-Go SDK vs. cgo Go SDK: customer-facing differences & should we make them source-compatible? #665
zlata-stefanovic-db
started this conversation in
General
Replies: 1 comment
|
@teodordelibasic-db Discussion about Pure-Go vs. cgo Go SDK |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
We now have two Go SDKs in the repo — the original cgo SDK (
go/, imports the Rust core over cgo + FFI) and the new pure-Go SDK (purego/zerobus, native gRPC, no cgo). They talk to the same Zerobus service and share the same performance model (ingest in a loop,Flush()once), but the public APIs are not source-compatible: every type and most method signatures differ.I wrote up the customer-facing differences and want to open a discussion on one question in particular: should we make the two source-compatible, and if so, how? Summary below — feedback welcome.
Where they differ (what a user actually notices)
Build & runtime
Naming / entry points (nothing is a drop-in swap)
SDK/New/Close() errorZerobusSdk/NewZerobusSdk/Free()StreamZerobusStreamErrorZerobusErrorWithJSON(),WithRecovery(...))StreamConfigurationOptionsstructzerobus-sdk-go-purego/<ver>zerobus-sdk-go/<ver>API shape
[]byte/[][]byte; cgo isinterface{}(stringfor JSON,[]bytefor proto).context.ContextonCreateStreamand offers...Contextvariants on ingest/flush/wait; cgo has none.time.Duration; cgo struct fields in milliseconduint64.*ErrorwithOp+Unwrap+ package-levelRetryable(err); cgo*ZerobusError{Message, IsRetryable}via type assertion.HeadersProviderdiffers — pure-GoGetHeaders(ctx, tableName)+Invalidate(...); cgoGetHeaders().Feature gaps (either direction)
WithAckCallback), async open +WithWaitForReady, custom TLS (WithTLSConfig), byte-based backpressure caps,Stream.ID()/ServerID()/IsClosed(),NewStaticHeadersProvider, and dynamic-proto with UC schema fetch (CreateDynamicProtoStream/IngestJSONStringOffset).IngestRecord/RecordAck/*Nowaitsurface.Should we make them source-compatible?
My take: don't rename the pure-Go API to match cgo. The pure-Go surface is deliberately cleaner (context, byte payloads, functional options,
errors.Is/As, no deprecated methods). Matching cgo would drag its legacy warts in permanently.Instead, if we want to cut migration cost, add an opt-in
compatsubpackage (e.g..../purego/zerobus/compat) that re-exposes the cgo names and delegates to the pure-Go core. Existing users change one import path; new users get the idiomatic API.What a shim would translate
Free()Close(), discards the errorCreateStream(TableProperties, ...)(no ctx)context.Background();DescriptorProto→WithProto(...)StreamConfigurationOptionsWithXoptions;*Ms uint64→time.DurationRecordTypefieldWithJSON()/WithProto(desc)interface{}/stringpayloads[]byte*ZerobusErrorMessage: err.Error(),IsRetryable: zerobus.Retryable(err)HeadersProvider.GetHeaders()GetHeaders(ctx, tableName); no-opInvalidateIngestRecord/RecordAck/*NowaitIngestRecordOffset/IngestRecordsOffsetHard blockers a shim can't fix
Flush/WaitForOffset) andMaxInflightcounting ingest calls vs requests mean identical-looking code can behave differently.*Erroras*ZerobusErrorpreservesRetryable()but changes the concrete type forerrors.As.Questions for discussion
compatsubpackage worth maintaining, or should cgo→pure-Go just be a documented one-time migration?compatlive — permanent, or a deprecation bridge?All reactions