Documentation
¶
Overview ¶
Package client implements the FDB client transaction lifecycle. This is the Go equivalent of NativeAPI.actor.cpp.
Index ¶
- Constants
- Variables
- func ReadEndpointFromSlot(r *wire.Reader, slot int) (types.Endpoint, error)
- type ClientMetrics
- type ClientMetricsSnapshot
- type ClusterFile
- type DBInfo
- type Database
- func (d *Database) Close() error
- func (d *Database) CreateTransaction() *Transaction
- func (d *Database) GetDBInfo() *DBInfo
- func (d *Database) HedgeEnabled() bool
- func (d *Database) InvalidateGRVCache()
- func (d *Database) Metrics() ClientMetricsSnapshot
- func (d *Database) ReadTransact(ctx context.Context, fn func(tx *Transaction) (any, error)) (any, error)
- func (d *Database) SetDefaultAccessSystemKeys()
- func (d *Database) SetDefaultReadSystemKeys()
- func (d *Database) SetDialFunc(fn transport.DialFunc)
- func (d *Database) SetHedgeEnabled(enabled bool)
- func (d *Database) SetMaxWatches(n int64) error
- func (d *Database) SetTransactionMaxRetryDelay(ms int64)
- func (d *Database) SetTransactionRetryLimit(retries int64)
- func (d *Database) SetTransactionSizeLimit(limit int64)
- func (d *Database) SetTransactionTimeout(ms int64)
- func (d *Database) Transact(ctx context.Context, fn func(tx *Transaction) (any, error)) (any, error)
- type DialFunc
- type KeyRange
- type KeyValue
- type LatencyStats
- type LocationResult
- type Mutation
- type MutationType
- type Option
- type PendingGet
- type ProxyInfo
- type QueueModel
- type RangeMaterializationLimitError
- type ServerInfo
- type Snapshot
- func (s *Snapshot) Get(ctx context.Context, key []byte) ([]byte, error)
- func (s *Snapshot) GetKey(ctx context.Context, selectorKey []byte, orEqual bool, offset int32) ([]byte, error)
- func (s *Snapshot) GetRange(ctx context.Context, begin, end []byte, limit int) ([]KeyValue, bool, error)
- func (s *Snapshot) GetRangeReverse(ctx context.Context, begin, end []byte, limit int) ([]KeyValue, bool, error)
- func (s *Snapshot) GetReadVersion(ctx context.Context) (int64, error)
- type Transaction
- func (tx *Transaction) AddReadConflictKey(key []byte)
- func (tx *Transaction) AddReadConflictRange(begin, end []byte) error
- func (tx *Transaction) AddWriteConflictKey(key []byte)
- func (tx *Transaction) AddWriteConflictRange(begin, end []byte) error
- func (tx *Transaction) Atomic(op MutationType, key, operand []byte)
- func (tx *Transaction) AwaitWatchCommit(watchCtx context.Context, act *watchActivation, readVersion int64) (int64, error)
- func (tx *Transaction) BypassUnreadable() bool
- func (tx *Transaction) Cancel()
- func (tx *Transaction) CausalReadRisky() bool
- func (tx *Transaction) Clear(key []byte)
- func (tx *Transaction) ClearRange(begin, end []byte) error
- func (tx *Transaction) Commit(ctx context.Context) error
- func (tx *Transaction) EnsureMutationCapacity(n int)
- func (tx *Transaction) Get(ctx context.Context, key []byte) ([]byte, error)
- func (tx *Transaction) GetAddressesForKey(parentCtx context.Context, key []byte) ([]string, error)
- func (tx *Transaction) GetApproximateSize() (int64, error)
- func (tx *Transaction) GetCommittedVersion() (int64, error)
- func (tx *Transaction) GetEstimatedRangeSizeBytes(parentCtx context.Context, begin, end []byte) (int64, error)
- func (tx *Transaction) GetKey(ctx context.Context, selectorKey []byte, orEqual bool, offset int32) ([]byte, error)
- func (tx *Transaction) GetLocations(parentCtx context.Context, begin, end []byte, limit int) ([]LocationResult, error)
- func (tx *Transaction) GetPipelined(ctx context.Context, key []byte) (val []byte, pending *PendingGet, err error)
- func (tx *Transaction) GetRange(ctx context.Context, begin, end []byte, limit int) ([]KeyValue, bool, error)
- func (tx *Transaction) GetRangeReverse(ctx context.Context, begin, end []byte, limit int) ([]KeyValue, bool, error)
- func (tx *Transaction) GetRangeSplitPoints(parentCtx context.Context, begin, end []byte, chunkSize int64) ([][]byte, error)
- func (tx *Transaction) GetReadVersion(ctx context.Context) (int64, error)
- func (tx *Transaction) GetTagThrottledDuration() float64
- func (tx *Transaction) GetVersionstamp() ([]byte, error)
- func (tx *Transaction) LockAware() bool
- func (tx *Transaction) OnError(ctx context.Context, err error) (rerr error)
- func (tx *Transaction) ReadLockAware() bool
- func (tx *Transaction) ReleaseWatch()
- func (tx *Transaction) Reset()
- func (tx *Transaction) Set(key, value []byte)
- func (tx *Transaction) SetAccessSystemKeys()
- func (tx *Transaction) SetBypassUnreadable(v bool)
- func (tx *Transaction) SetCausalReadRisky(v bool)
- func (tx *Transaction) SetLockAware(v bool)
- func (tx *Transaction) SetMaxRetryDelay(ms int64)
- func (tx *Transaction) SetNextWriteNoWriteConflictRange()
- func (tx *Transaction) SetPriority(p TransactionPriority)
- func (tx *Transaction) SetReadLockAware(v bool)
- func (tx *Transaction) SetReadSystemKeys()
- func (tx *Transaction) SetReadVersion(version int64)
- func (tx *Transaction) SetReadYourWritesDisable()
- func (tx *Transaction) SetRetryLimit(retries int64)
- func (tx *Transaction) SetSizeLimit(limit int64)
- func (tx *Transaction) SetSkipGrvCache()
- func (tx *Transaction) SetSnapshotRYWDisable()
- func (tx *Transaction) SetSnapshotRYWDisableCount(n int)
- func (tx *Transaction) SetSnapshotRYWEnable()
- func (tx *Transaction) SetSpanParent(b []byte) error
- func (tx *Transaction) SetTag(tag string)
- func (tx *Transaction) SetTenantId(id int64)
- func (tx *Transaction) SetTimeout(ms int64)
- func (tx *Transaction) SetUseGrvCache()
- func (tx *Transaction) SetWriteConflictsDisabled()
- func (tx *Transaction) Snapshot() *Snapshot
- func (tx *Transaction) SnapshotRYWDisableCount() int
- func (tx *Transaction) TenantId() int64
- func (tx *Transaction) Watch(ctx context.Context, key []byte) error
- func (tx *Transaction) WatchActivation() *watchActivation
- func (tx *Transaction) WatchPoll(watchCtx context.Context, watchCancel context.CancelFunc, key, value []byte, ...) error
- func (tx *Transaction) WatchSetup(ctx context.Context, key []byte) ([]byte, int64, types.SpanContext, context.Context, context.CancelFunc, error)
- type TransactionDefaults
- type TransactionPriority
Constants ¶
const ( ErrNotCommitted = 1020 // not_committed (conflict) ErrCommitUnknownResult = 1021 // commit_unknown_result ErrTransactionTooOld = 1007 // transaction_too_old ErrFutureVersion = 1009 // future_version ErrWrongShardServer = 1001 // wrong_shard_server (1062 is change_feed_cancelled — do not confuse) ErrTransactionTimedOut = 1031 // transaction_timed_out (NEVER retryable) ErrAccessedUnreadable = 1036 // accessed_unreadable — read of a pending versionstamped key (NOT retryable; RFC-098) ErrProcessBehind = 1037 // process_behind ErrWatchCancelled = 1029 // watch_cancelled — SS watch limit exceeded; client polls instead ErrTooManyWatches = 1032 // too_many_watches — outstanding-watch cap exceeded (client-side) ErrTimedOut = 1004 // timed_out — the SS occasionally times out a watch; re-arm ErrDatabaseLocked = 1038 // database_locked ErrClusterVersionChanged = 1039 // cluster_version_changed (MAYBE_COMMITTED) ErrProxyMemoryLimitExceeded = 1042 // commit_proxy_memory_limit_exceeded ErrBatchTransactionThrottled = 1051 // batch_transaction_throttled ErrGrvProxyMemoryLimit = 1078 // grv_proxy_memory_limit_exceeded ErrBlobGranuleRequestFailed = 1079 // blob_granule_request_failed (retryable, C++ NativeAPI.actor.cpp) ErrTagThrottled = 1213 // tag_throttled ErrProxyTagThrottled = 1223 // proxy_tag_throttled ErrThrottledHotShard = 1235 // transaction_throttled_hot_shard (FDB 7.4+, future-proof) ErrRangeLocked = 1242 // transaction_rejected_range_locked (FDB 7.4+, future-proof) ErrOperationFailed = 4 // operation_failed (endpoint not supported) ErrAllAlternativesFailed = 1006 // all_alternatives_failed (Layer 2 only) ErrAllProxiesUnreachable = 1200 // Go-internal: all proxies failed at Layer 2 (NOT C++ 1200=recruitment_failed) ErrInvertedRange = 2005 // inverted_range (begin > end) ErrRangeLimitsInvalid = 2012 // range_limits_invalid (e.g. a row limit < -1) ErrInvalidMutationType = 2018 // invalid_mutation_type (a non-atomic op passed to Atomic()) )
FDB error codes. Source of truth: flow/error_definitions.h + fdb_c.cpp fdb_error_predicate().
const ( NoTenantID int64 = -1 UnlimitedBytes int32 = 0x7FFFFFFF DefaultRPCTimeout = 5 * time.Second CoordinatorTimeout = 30 * time.Second // OpenDatabaseCoordRequest + GRV batch context BootstrapMaxBackoff = 5 * time.Second // bootstrap retry backoff cap MaxWrongShardRetries = 50 // C++ is unbounded (relies on tx 5s timeout); 50×10ms = 500ms, generous safety margin )
Client constants. These mirror CLIENT_KNOBS in NativeAPI.actor.cpp.
const ( LatestVersion int64 = -2 // C++ latestVersion — used in GetKeyServerLocationsRequest.MinTenantVersion InvalidVersion int64 = -1 // C++ invalidVersion — used in GetReadVersionRequest.MaxVersion )
C++ version constants from flow/flow.h.
const ( EndpointGetValue = 0 // StorageServerInterface::getValue EndpointGetKey = 1 // StorageServerInterface::getKey EndpointGetKeyValues = 2 // StorageServerInterface::getKeyValues EndpointGetShardState = 3 // StorageServerInterface::getShardState EndpointWaitMetrics = 4 // StorageServerInterface::waitMetrics EndpointSplitMetrics = 5 // StorageServerInterface::splitMetrics EndpointGetStorageMetrics = 6 // StorageServerInterface::getStorageMetrics EndpointWaitFailure = 7 // StorageServerInterface::waitFailure EndpointGetQueuingMetrics = 8 // StorageServerInterface::getQueuingMetrics EndpointGetKeyValueStoreType = 9 // StorageServerInterface::getKeyValueStoreType EndpointWatchValue = 10 // StorageServerInterface::watchValue EndpointGetReadHotRanges = 11 // StorageServerInterface::getReadHotRanges EndpointGetRangeSplitPoints = 12 // StorageServerInterface::getRangeSplitPoints EndpointGetKeyValuesStream = 13 // StorageServerInterface::getKeyValuesStream EndpointGetKeyServerLocations = 2 // CommitProxyInterface::getKeyServerLocations )
Endpoint indices from C++ interface definitions. Indices are relative to each interface's base token via getAdjustedEndpoint().
StorageServerInterface (StorageServerInterface.h):
getValue=0, getKey=1, getKeyValues=2, getShardState=3, waitMetrics=4, splitMetrics=5, getStorageMetrics=6, waitFailure=7, getQueuingMetrics=8, getKeyValueStoreType=9, watchValue=10, getReadHotRanges=11, getRangeSplitPoints=12, getKeyValuesStream=13
CommitProxyInterface (CommitProxyInterface.h):
commit=0, ..., getKeyServerLocations=2
Variables ¶
var ErrNeedFullRYW = errors.New("need full RYW path")
ErrNeedFullRYW is returned by GetPipelined when the key has pending atomics that require a server read + merge through the full ryw.get() path.
Functions ¶
Types ¶
type ClientMetrics ¶
type ClientMetrics struct {
// contains filtered or unexported fields
}
ClientMetrics holds the per-Database transaction counters — the operational subset of C++ DatabaseContext's CounterCollection (DatabaseContext.h:585-635), with the C++ names and the C++ increment sites (RFC-097):
- commit started/completed: commitMutations entry (NativeAPI.actor.cpp:6808; the empty/read-only fast path at :6800-6806 does NOT count) / tryCommit success (:6673). Started−Completed = failed or in-flight (intentional asymmetry, matching C++).
- the per-error-code retry counters: Transaction::onError's arms (:7749-:7772).
- read versions completed (+ per priority): extractReadVersion (:7428-7440) — i.e. per transaction served by a REAL GRV reply; cache hits do not count there in C++ and do not count here.
transactionRetries is a Go-only aggregate (total OnError-sanctioned retries); C++ tracks retries per-transaction only (trState->numErrors). It also counts codes C++ retries WITHOUT a counter (database_locked 1038, blob_granule_request_failed 1079 — :7743-7747, plus the Go-internal 1200 and future-proof 1235/1242).
Counters are monotonic; consumers poll Database.Metrics() and diff. There is no periodic trace emission (C++ logs TransactionMetrics on a timer; the Go analog is the consumer's scrape interval) — the only gap is no persisted history if nothing polls before process death.
func (*ClientMetrics) Snapshot ¶
func (m *ClientMetrics) Snapshot() ClientMetricsSnapshot
Snapshot returns a point-in-time copy of all counters.
type ClientMetricsSnapshot ¶
type ClientMetricsSnapshot struct {
TransactionsCommitStarted int64
TransactionsCommitCompleted int64
TransactionsNotCommitted int64
TransactionsMaybeCommitted int64
TransactionsResourceConstrained int64
TransactionsProcessBehind int64
TransactionsThrottled int64
TransactionsTooOld int64
TransactionsFutureVersions int64
TransactionReadVersionsCompleted int64
TransactionBatchReadVersionsCompleted int64
TransactionDefaultReadVersionsCompleted int64
TransactionImmediateReadVersionsCompleted int64
GRVCacheHits int64 // RFC-104: served from the GRV cache (opt-in)
TransactionRetries int64
RecoveredPanics int64 // RFC-110: panics recovered by the goroutine backstop
RecoveredPanicsConsecutiveMax int64 // RFC-110: high-water of any loop's consecutive-panic streak
ClientConnectionFailures int64 // RFC-114: connection/dial failures (Go-only observability)
CoordinatorChanges int64 // RFC-114: followed coordinator forwards (Go-only observability)
// Latency distributions (RFC-114), seconds. Instantaneous reads, not monotonic.
ReadLatency LatencyStats // GetValue round-trip
CommitLatency LatencyStats // commit round-trip
GRVLatency LatencyStats // GRV round-trip
TransactionLatency LatencyStats // total transaction latency (C++ "latencies")
}
ClientMetricsSnapshot is a point-in-time copy of the counters. Fields are monotonic; diff two snapshots for rates.
type ClusterFile ¶
type ClusterFile struct {
Description string
ID string
Coordinators []string // "host:port" addresses for TCP connection (":tls" suffix stripped)
// UseTLS is true when the coordinators carry the ":tls" suffix (FDB
// FLAG_TLS). A real cluster is uniformly TLS, so this is a single flag;
// mixed TLS/non-TLS coordinators are rejected at parse time.
UseTLS bool
}
ClusterFile represents an fdb.cluster file. Format: "<description>:<id>@<host>:<port>[,<host>:<port>...]"
func ParseClusterFile ¶
func ParseClusterFile(path string) (*ClusterFile, error)
ParseClusterFile reads and parses an fdb.cluster file.
func ParseClusterString ¶
func ParseClusterString(s string) (*ClusterFile, error)
ParseClusterString parses a cluster connection string.
func (*ClusterFile) String ¶
func (cf *ClusterFile) String() string
String renders the connection string in C++ ClusterConnectionString::toString byte-order (MonitorLeader.actor.cpp:438-453): `description:id@`, then all IP coordinators in original order, then all hostname coordinators in original order, comma-joined, each with ":tls" re-appended when UseTLS. This is the cross-tool-shared on-disk form; it must be byte-identical to what a C++/Java client would write so they can read the file back. Equality between two ClusterFiles is defined as a.String() == b.String() (matches C++ upToDate's toString() compare) — the serialization is the single source of truth.
type DBInfo ¶
type DBInfo struct {
ID transport.UID
GRVProxies []ProxyInfo
CommitProxies []ProxyInfo
ClusterID transport.UID
// Forward, when non-empty, is the serialized new ClusterConnectionString the
// coordinators handed back instead of proxies — the C++ ClientDBInfo.forward
// field (CommitProxyInterface.h:132). Set during a `coordinators auto`/`change`
// rotation; the proxies on a forward reply are ignored (RFC-111 Path A).
Forward string
}
DBInfo holds the current cluster topology. Received from coordinators via OpenDatabaseCoordRequest.
type Database ¶
type Database struct {
// contains filtered or unexported fields
}
Database is the public API entry point. C++: Database is a Reference<DatabaseContext> — a handle, not state.
Safe for concurrent use by multiple goroutines.
func OpenDatabase ¶
OpenDatabase opens a database connection using a cluster file. The provided ctx is used for the initial bootstrap (coordinator connection). Background goroutines use an internal context cancelled by Close().
func OpenDatabaseFromConfig ¶
func OpenDatabaseFromConfig(ctx context.Context, cf *ClusterFile, opts ...Option) (*Database, error)
OpenDatabaseFromConfig creates and bootstraps a Database from a ClusterFile. See WithDialFunc / WithTLSConfig for options.
func (*Database) CreateTransaction ¶
func (d *Database) CreateTransaction() *Transaction
CreateTransaction creates a new transaction. Database-level defaults (timeout, retry limit, system key access) are applied.
func (*Database) GetDBInfo ¶
GetDBInfo returns the current cluster topology (proxy lists, cluster ID). Returns nil if not yet connected.
func (*Database) HedgeEnabled ¶
HedgeEnabled returns whether speculative second requests are active.
func (*Database) InvalidateGRVCache ¶
func (d *Database) InvalidateGRVCache()
InvalidateGRVCache resets the GRV cache so the next transaction fetches a fresh read version from the GRV proxy. Use after external writes.
func (*Database) Metrics ¶
func (d *Database) Metrics() ClientMetricsSnapshot
Metrics returns a point-in-time snapshot of this handle's operational counters (RFC-097) — the C++ DatabaseContext TransactionMetrics subset. Counters are monotonic; poll and diff for rates. This is the export hook: Prometheus/OTel consumers are pull-based readers of exactly this shape (see pkg/fdbgo/fdbmetrics for a ready-made scrape handler).
func (*Database) ReadTransact ¶
func (d *Database) ReadTransact(ctx context.Context, fn func(tx *Transaction) (any, error)) (any, error)
ReadTransact runs a read-only function in a transaction with automatic retry. The transaction is never committed — only reads are performed.
func (*Database) SetDefaultAccessSystemKeys ¶
func (d *Database) SetDefaultAccessSystemKeys()
SetDefaultAccessSystemKeys makes all new transactions automatically call SetAccessSystemKeys(), allowing reads AND writes of \xff-prefixed system keys.
func (*Database) SetDefaultReadSystemKeys ¶
func (d *Database) SetDefaultReadSystemKeys()
SetDefaultReadSystemKeys makes all new transactions automatically call SetReadSystemKeys(), allowing reads of \xff-prefixed system keys.
func (*Database) SetDialFunc ¶
SetDialFunc sets a custom dialer for all new connections. Must be called before OpenDatabase or any transactions.
func (*Database) SetHedgeEnabled ¶
SetHedgeEnabled controls speculative second requests (hedge) for read RPCs. When enabled (default), slow reads are rescued by sending a backup request to a second server after max(10ms, 2×latency). Disable for debugging or benchmarking the non-hedged path.
func (*Database) SetMaxWatches ¶
SetMaxWatches sets the cap on concurrently-outstanding watches for this Database (FDB_DB_OPTION_MAX_WATCHES). Once the count would exceed it, a new watch fails with too_many_watches (1032). Matches C++ DatabaseContext maxOutstandingWatches; default 10000. 0 is a REAL cap (no watches allowed — the first fails), NOT "unlimited". An out-of-range value (< 0 or > ABSOLUTE_MAX_WATCHES) is REJECTED with invalid_option_value (2006) and the cap is left UNCHANGED — C++ extractIntOption(value, 0, ABSOLUTE_MAX_WATCHES) throws on out-of-range, it does NOT clamp (NativeAPI.actor.cpp:2092-2102 / :2139).
func (*Database) SetTransactionMaxRetryDelay ¶
SetTransactionMaxRetryDelay sets the default max retry delay (ms) for all transactions. Matches FDB_DB_OPTION_TRANSACTION_MAX_RETRY_DELAY.
func (*Database) SetTransactionRetryLimit ¶
SetTransactionRetryLimit sets the default retry limit for all transactions. Matches FDB_DB_OPTION_TRANSACTION_RETRY_LIMIT.
func (*Database) SetTransactionSizeLimit ¶
SetTransactionSizeLimit sets the default size limit for all transactions. Matches FDB_DB_OPTION_TRANSACTION_SIZE_LIMIT.
func (*Database) SetTransactionTimeout ¶
SetTransactionTimeout sets the default timeout (in milliseconds) for all transactions created from this database. Matches FDB_DB_OPTION_TRANSACTION_TIMEOUT.
func (*Database) Transact ¶
func (d *Database) Transact(ctx context.Context, fn func(tx *Transaction) (any, error)) (any, error)
Transact runs a function in a transaction with automatic retry. This is the primary API for interacting with FDB. The transaction is reused across retries — retryCount and backoff escalate.
type DialFunc ¶
DialFunc is the custom-dialer signature (alias of transport.DialFunc) so callers configuring WithDialFunc don't need to import the transport package.
type LatencyStats ¶
type LatencyStats struct {
Count int64
Sum float64 // seconds — the summary _sum (and Mean = Sum/Count)
Mean float64
Median float64 // p50
P90 float64
P99 float64
Min float64 // exact (C++ DDSketchBase::min)
Max float64 // exact (C++ DDSketchBase::max)
}
LatencyStats is a point-in-time summary of one latency distribution (RFC-114), in SECONDS. Unlike the monotonic counters, these are instantaneous distribution reads — diffing two snapshots is not meaningful. Median/P90/P99 are DDSketch quantiles (±0.5% relative error). C++ emits p90/p98 only for the aggregate transaction latency; Go exposes per-category median/p90/p99 — a local-metric superset (p99 is the conventional Prometheus tail, vs C++'s trace-only p98).
type LocationResult ¶
type LocationResult struct {
Servers []ServerInfo
ShardBegin []byte
ShardEnd []byte
}
LocationResult holds the storage servers and shard key range for a locate() result. C++ KeyRangeLocationInfo equivalent.
type Mutation ¶
type Mutation struct {
Type MutationType
Key []byte
Value []byte
}
Mutation represents a key-value mutation in a transaction.
type MutationType ¶
type MutationType uint8
MutationType is the type of mutation.
const ( MutSetValue MutationType = 0 MutClearRange MutationType = 1 MutAddValue MutationType = 2 MutAnd MutationType = 6 // C++: And (skips DebugKeyRange=3, DebugKey=4, NoOp=5) MutOr MutationType = 7 // C++: Or MutXor MutationType = 8 // C++: Xor MutAppendIfFits MutationType = 9 // C++: AppendIfFits MutMax MutationType = 12 // C++: Max (skips AvailableForReuse=10, Reserved=11) MutMin MutationType = 13 // C++: Min MutSetVersionstampedKey MutationType = 14 // C++: SetVersionstampedKey MutSetVersionstampedValue MutationType = 15 // C++: SetVersionstampedValue MutByteMin MutationType = 16 // C++: ByteMin MutByteMax MutationType = 17 // C++: ByteMax MutMinV2 MutationType = 18 // C++: MinV2 MutAndV2 MutationType = 19 // C++: AndV2 MutCompareAndClear MutationType = 20 // C++: CompareAndClear )
Mutation types — MUST match C++ MutationRef::Type enum values exactly. Wire format uses these values directly. See CommitTransaction.h.
type Option ¶
type Option func(*openOptions)
Option configures a database opened via OpenDatabase / OpenDatabaseFromConfig. Options compose and are forward-compatible — new knobs don't break callers.
func WithAPIVersion ¶
WithAPIVersion records the selected FDB API version; required — OpenDatabase rejects an unset version, mirroring fdb_select_api_version. Gates version-dependent wire behaviour, e.g. the Min→MinV2/And→AndV2 atomic upgrade at >=510.
func WithDialFunc ¶
WithDialFunc overrides the dialer used for every connection. nil (the default) uses a standard net.Dialer. Useful for fault injection, custom networking, or traffic shaping in tests.
func WithLogger ¶
WithLogger sets the per-handle logger for the client's operational events (transaction retries, commit_unknown_result — RFC-097). nil (the default) uses slog.Default(), so zero-config apps keep the standard integration point (slog.SetDefault); the per-handle option exists for multi-tenant hosts and for tests, which must never mutate process-global state.
func WithRangeByteCeiling ¶
WithRangeByteCeiling bounds how many bytes a single GetRange may materialize into memory before it fails with a *RangeMaterializationLimitError, instead of OOM-ing the process on a runaway unbounded scan. n ≤ 0 (the default) means UNLIMITED — matching libfdb_c, whose GetSliceWithError equivalent also materializes a range unbounded and never returns a "too big" error. This is a Go-only OPT-IN OOM safety valve, off by default so the default facade behavior stays oracle-matching; an operator sets a ceiling (e.g. 256<<20) as a last-resort guard. The bounded, streaming Iterator() honors StreamingMode and is the right tool for large result sets; this ceiling is the backstop for code that calls GetSliceWithError on an unexpectedly huge range. The cap bounds total materialized key+value bytes; a single read may overshoot it by at most one reply (~80 KB) before the check fires.
func WithTLSConfig ¶
WithTLSConfig connects to the cluster over TLS using the given standard *crypto/tls.Config — bring any config: in-memory certs, rotation via GetClientCertificate, custom VerifyPeerCertificate, cipher/version policy.
It takes precedence over the FDB_TLS_* environment / cluster-file ":tls" resolution and enables TLS even when the cluster string lacks ":tls". When not supplied, a ":tls" cluster string falls back to the FDB_TLS_* env convenience layer (matching the C++ client). A non-nil config is the only "use TLS" signal — there is no separate boolean, so TLS can never be silently downgraded.
WithTLSConfig(nil) is a no-op (it does NOT force plaintext): a ":tls" cluster string + FDB_TLS_* env still enables TLS. To stay plaintext, use a cluster string without ":tls".
func WithTracer ¶
WithTracer sets the OpenTelemetry tracer used to EXPORT client-side trace spans (the C++ ITracer analog — NoopTracer default, pluggable backend). The pure-Go client always GENERATES + propagates a SpanContext on the wire (RFC-115 §4 Layer 1) regardless of this; WithTracer adds the export half. Pass any go.opentelemetry.io/otel/trace.Tracer (from your OTLP/Jaeger/Datadog TracerProvider); the client emits a "Transaction" span plus per-operation child spans (getValue, getRange, commit, GRV, …), seeded with the same traceID it puts on the wire so FDB server-side spans land in the same trace. nil (the default) → an internal no-op tracer: zero telemetry, zero allocation on the hot path, no OTEL SDK pulled in. Spans are recorded only for sampled transactions (see WithTracingSampleRate).
CAVEAT (span lifetime): the per-transaction "Transaction" span ends on commit success, OnError retry, Reset, or Cancel. Database.Transact/TransactCtx always hit one of these, so they are safe. A RAW Database.CreateTransaction() handle that you read from (starting the span) and then ABANDON without committing/Reset/Cancel will LEAK that span (it is never ended) — only matters with a real tracer AND a sampled transaction. Always Reset() or Cancel() a raw handle you don't commit.
func WithTracingSampleRate ¶
WithTracingSampleRate sets the fraction (0.0–1.0) of transactions whose trace span is flagged SAMPLED. The default 0.0 matches C++ FLOW_KNOBS->TRACING_SAMPLE_RATE: every transaction still carries a real, randomly-generated SpanContext on every request (wire-faithful with C++), but flagged unsampled so collectors drop it. Raise it to emit sampled spans for a fraction of transactions. RFC-115 §4.
type PendingGet ¶
type PendingGet struct {
// contains filtered or unexported fields
}
PendingGet represents a GetValue request that has been sent but not yet resolved.
func (*PendingGet) Resolve ¶
func (p *PendingGet) Resolve() ([]byte, error)
Resolve blocks until the response arrives or timeout, then applies the SAME classify/invalidate/retry semantics as the synchronous getValue path: a wrong_shard_server or all_alternatives_failed reply (including the inline LoadBalancedReply.error, RFC-010 #1) invalidates the stale location and re-drives through the full read path; transport errors, a flush failure, or a timeout likewise fall through to the full path rather than surfacing a bare error or skipping the wrong-shard retry. Pipelining only defers the wait — it must not own a different error policy. RFC-010 #3.
Flushes the write buffer on first call to ensure the request reaches the server (batched with any other deferred frames on the same connection).
type QueueModel ¶
type QueueModel struct {
// contains filtered or unexported fields
}
QueueModel tracks estimated outstanding request depth per storage server. Used by sendGetValue/sendGetKey/sendGetRange to pick the least-loaded server from a shard's replica set.
Matches C++ QueueModel in fdbclient/QueueModel.h: - Smoother-based continuous exponential decay (eFoldingTime=2s) - Server penalty from LoadBalancedReply - failedUntil with exponential backoff for future_version errors
Selection metric: smoothOutstanding.smoothTotal() (lower = better). C++ also uses latency for speculative second requests (secondDelay), which we don't implement yet.
type RangeMaterializationLimitError ¶
type RangeMaterializationLimitError struct {
LimitBytes int64 // the configured WithRangeByteCeiling
ReachedBytes int64 // total key+value bytes materialized when the cap was exceeded
}
RangeMaterializationLimitError is returned by a GetRange that would materialize more than the opt-in WithRangeByteCeiling cap (RFC-115 §2) — an OOM safety valve, off by default. libfdb_c has no such ceiling (its GetSliceWithError equivalent also materializes unbounded and never returns a "too big" error), so this NEVER fires unless the operator opts in via WithRangeByteCeiling; the default facade behavior stays oracle-matching. Match it with errors.As. For large scans, prefer the bounded, StreamingMode-honoring Iterator() instead of raising the ceiling.
func (*RangeMaterializationLimitError) Error ¶
func (e *RangeMaterializationLimitError) Error() string
type ServerInfo ¶
type ServerInfo struct {
Address string
Token transport.UID
// TLS records whether the SS address carried the TLS flag. Address itself stays a clean
// host:port for dialing; GetAddressesForKey appends ":tls" to its output when this is set,
// matching C++ NetworkAddress::toString (flow/network.cpp:215).
TLS bool
}
ServerInfo holds a storage server's address and endpoint token.
type Snapshot ¶
type Snapshot struct {
// contains filtered or unexported fields
}
Snapshot wraps a Transaction for conflict-free reads. All reads go through the same transaction (same read version, same connection pool) but do not add read conflict ranges.
func (*Snapshot) Get ¶
Get reads a key without adding a read conflict range. Snapshot reads go through the RYW cache unless snapshot RYW is net-disabled (snapshotRYWDisableCount > 0).
func (*Snapshot) GetKey ¶
func (s *Snapshot) GetKey(ctx context.Context, selectorKey []byte, orEqual bool, offset int32) ([]byte, error)
GetKey resolves a key selector without adding a read conflict range. Snapshot reads go through the snapshot cache, and — by default — SEE the txn's own pending writes (matching Snapshot.Get/GetRange and libfdb_c, where snapshot RYW is enabled unless net-disabled via SetSnapshotRYWDisable). When net-disabled (snapshotRYWDisableCount > 0) the write map is bypassed (snapshot cache only).
func (*Snapshot) GetRange ¶
func (s *Snapshot) GetRange(ctx context.Context, begin, end []byte, limit int) ([]KeyValue, bool, error)
GetRange reads a range without adding a read conflict range. Snapshot reads go through the RYW cache unless snapshot RYW is net-disabled (snapshotRYWDisableCount > 0).
func (*Snapshot) GetRangeReverse ¶
func (s *Snapshot) GetRangeReverse(ctx context.Context, begin, end []byte, limit int) ([]KeyValue, bool, error)
GetRangeReverse reads a range in reverse without adding a read conflict range. Snapshot reads go through the RYW cache unless snapshot RYW is net-disabled (snapshotRYWDisableCount > 0).
type Transaction ¶
type Transaction struct {
// contains filtered or unexported fields
}
Transaction represents an FDB transaction. Mutations are buffered locally and sent on Commit().
func (*Transaction) AddReadConflictKey ¶
func (tx *Transaction) AddReadConflictKey(key []byte)
AddReadConflictKey adds a read conflict on a single key. Like AddReadConflictRange it is filtered through the RYW write-map (C++ addReadConflictRange over [key, keyAfter(key)) → updateConflictMap, ReadYourWrites.actor.cpp:1986): a self-written independent key adds no conflict; rywDisabled adds the full single-key conflict directly (:1979). Identical to the Get-path helper, so delegate.
func (*Transaction) AddReadConflictRange ¶
func (tx *Transaction) AddReadConflictRange(begin, end []byte) error
AddReadConflictRange adds an explicit read conflict range [begin, end). If any key in this range is modified by another transaction between this transaction's read version and commit, the commit will fail. Returns inverted_range (2005) if begin > end. Matches C++ fdb_transaction_add_conflict_range.
func (*Transaction) AddWriteConflictKey ¶
func (tx *Transaction) AddWriteConflictKey(key []byte)
AddWriteConflictKey adds a write conflict on a single key.
func (*Transaction) AddWriteConflictRange ¶
func (tx *Transaction) AddWriteConflictRange(begin, end []byte) error
AddWriteConflictRange adds an explicit write conflict range [begin, end). Returns inverted_range (2005) if begin > end. Matches C++ fdb_transaction_add_conflict_range.
func (*Transaction) Atomic ¶
func (tx *Transaction) Atomic(op MutationType, key, operand []byte)
Atomic performs an atomic mutation.
func (*Transaction) AwaitWatchCommit ¶
func (tx *Transaction) AwaitWatchCommit(watchCtx context.Context, act *watchActivation, readVersion int64) (int64, error)
AwaitWatchCommit blocks until the watch's captured incarnation resolves, returning the version to register the watch at — committedVersion, or readVersion when the txn didn't commit (C++ setupWatches' `committedVersion > 0 ? committedVersion : readVersion`, NativeAPI.actor.cpp:6420). Returns an error when the watch is abandoned (reset/Cancel → 1025) or its scoped context is cancelled, so the facade drains without registering. RFC-170 (#8): the async facade calls this BEFORE WatchPoll.
func (*Transaction) BypassUnreadable ¶
func (tx *Transaction) BypassUnreadable() bool
BypassUnreadable reports whether FDB_TR_OPTION_BYPASS_UNREADABLE is set. Read-only accessor used to verify database-level option propagation.
func (*Transaction) Cancel ¶
func (tx *Transaction) Cancel()
Cancel cancels the transaction. All subsequent operations will return an error. This is irreversible — a cancelled transaction cannot be reused.
func (*Transaction) CausalReadRisky ¶
func (tx *Transaction) CausalReadRisky() bool
CausalReadRisky reports whether the GRV causal-read-risky flag is set. Read-only accessor used to verify database-level option propagation.
func (*Transaction) Clear ¶
func (tx *Transaction) Clear(key []byte)
func (*Transaction) ClearRange ¶
func (tx *Transaction) ClearRange(begin, end []byte) error
ClearRange deletes all keys in [begin, end). Returns inverted_range (2005) if begin > end. Matches C++ fdb_transaction_clear_range_impl. Zero-width ranges (begin == end) are silently ignored, matching C++.
func (*Transaction) Commit ¶
func (tx *Transaction) Commit(ctx context.Context) error
Commit sends mutations to a commit proxy. After successful commit, the transaction is automatically reset for reuse (mutations and conflict ranges cleared, read version invalidated). This matches the C client's behavior where fdb_transaction_set() can be called after commit to start building a new transaction.
func (*Transaction) EnsureMutationCapacity ¶
func (tx *Transaction) EnsureMutationCapacity(n int)
EnsureMutationCapacity pre-sizes the mutations and writeConflicts slices to avoid growth allocations during batch writes. Call before a large batch.
func (*Transaction) GetAddressesForKey ¶
GetAddressesForKey returns the addresses of storage servers responsible for the given key. Uses the location cache (queries cluster on miss).
func (*Transaction) GetApproximateSize ¶
func (tx *Transaction) GetApproximateSize() (int64, error)
GetApproximateSize returns the approximate size of the transaction's mutations and conflict ranges in bytes. Matches C++ ReadYourWritesTransaction accounting: each mutation includes sizeof(MutationRef), each conflict range includes sizeof(KeyRangeRef). For set/atomic with write conflicts, C++ also adds the key length again for the auto-generated write conflict range.
func (*Transaction) GetCommittedVersion ¶
func (tx *Transaction) GetCommittedVersion() (int64, error)
GetCommittedVersion returns the version at which this transaction committed.
func (*Transaction) GetEstimatedRangeSizeBytes ¶
func (tx *Transaction) GetEstimatedRangeSizeBytes(parentCtx context.Context, begin, end []byte) (int64, error)
GetEstimatedRangeSizeBytes returns an estimate of the byte size of the given key range. Matches C++ getStorageMetricsLargeKeyRange in NativeAPI.actor.cpp: gets all shard locations, sends WaitMetricsRequest to each with min.bytes=0, max.bytes=-1 (reversed range = immediate response), and sums the bytes.
func (*Transaction) GetKey ¶
func (tx *Transaction) GetKey(ctx context.Context, selectorKey []byte, orEqual bool, offset int32) ([]byte, error)
GetKey resolves a key selector to the actual key in the database.
func (*Transaction) GetLocations ¶
func (tx *Transaction) GetLocations(parentCtx context.Context, begin, end []byte, limit int) ([]LocationResult, error)
GetLocations returns all shard location entries overlapping [begin, end).
func (*Transaction) GetPipelined ¶
func (tx *Transaction) GetPipelined(ctx context.Context, key []byte) (val []byte, pending *PendingGet, err error)
GetPipelined sends a GetValue request and returns a PendingGet that can be resolved later. This enables true pipelining: send N requests without waiting, then collect all N responses. Matches C++ client pipelining.
Returns (nil, nil, nil) for RYW cache hits (value is returned in val). Returns (nil, pending, nil) for server requests (call pending.Resolve() to get value). Returns (nil, nil, err) for errors during send.
func (*Transaction) GetRange ¶
func (tx *Transaction) GetRange(ctx context.Context, begin, end []byte, limit int) ([]KeyValue, bool, error)
GetRange reads a range of keys [begin, end) in forward order.
func (*Transaction) GetRangeReverse ¶
func (tx *Transaction) GetRangeReverse(ctx context.Context, begin, end []byte, limit int) ([]KeyValue, bool, error)
GetRangeReverse reads a range of keys [begin, end) in reverse order. Matches C++ where negative limit = reverse scan.
func (*Transaction) GetRangeSplitPoints ¶
func (tx *Transaction) GetRangeSplitPoints(parentCtx context.Context, begin, end []byte, chunkSize int64) ([][]byte, error)
GetRangeSplitPoints returns suggested split points for the given key range. Matches C++ Transaction::getRangeSplitPoints in NativeAPI.actor.cpp.
func (*Transaction) GetReadVersion ¶
func (tx *Transaction) GetReadVersion(ctx context.Context) (int64, error)
GetReadVersion returns the read version for this transaction, fetching it from a GRV proxy if not already set. Matches C++ fdb_transaction_get_read_version.
func (*Transaction) GetTagThrottledDuration ¶
func (tx *Transaction) GetTagThrottledDuration() float64
GetTagThrottledDuration returns the total time this transaction was delayed by proxy tag throttling across all GRV requests. Matches C++ Transaction::getTagThrottledDuration() (NativeAPI.actor.cpp:7594).
func (*Transaction) GetVersionstamp ¶
func (tx *Transaction) GetVersionstamp() ([]byte, error)
GetVersionstamp returns the 10-byte versionstamp from the committed transaction. Format: [version 8 bytes big-endian][txnBatchId 2 bytes big-endian]. Must be called after a successful Commit.
func (*Transaction) LockAware ¶
func (tx *Transaction) LockAware() bool
LockAware reports whether the commit is lock-aware (sets FLAG_IS_LOCK_AWARE, bypassing the locked-database check). Mirrors SetLockAware.
func (*Transaction) OnError ¶
func (tx *Transaction) OnError(ctx context.Context, err error) (rerr error)
OnError handles a transaction error. Returns nil if the error is retryable (the transaction has been reset for retry). Returns the error if non-retryable or ctx.Err() if ctx fires during the backoff sleep.
func (*Transaction) ReadLockAware ¶
func (tx *Transaction) ReadLockAware() bool
ReadLockAware reports whether reads bypass the locked-database check. Mirrors SetReadLockAware.
func (*Transaction) ReleaseWatch ¶
func (tx *Transaction) ReleaseWatch()
ReleaseWatch releases the outstanding-watch slot WatchSetup reserved (C++ decreaseWatchCounter). It is normally released by WatchPoll on completion, but when AwaitWatchCommit aborts a watch BEFORE it reaches WatchPoll (never-committed / reset / Cancel / ctx-expiry), WatchPoll never runs — so the async facade calls this on that abort path, else the slot leaks and later watches fail with too_many_watches under MAX_WATCHES. Idempotent-safe by construction: WatchPoll runs only on the success path, this only on the abort path — never both for one watch.
func (*Transaction) Reset ¶
func (tx *Transaction) Reset()
Reset resets the transaction to a clean state, as if newly created from Database. Unlike the internal reset() used by OnError (which preserves retryCount/backoff), this clears everything including retry state. Options set via Set*() are preserved across Reset, matching C++ ReadYourWritesTransaction::reset() + applyPersistentOptions. Updates creationTime so the timeout budget restarts (matches C++ reset() behavior).
In-flight Watch() calls ARE cancelled by Reset() (via reset()→cancelWatches(), below), but they surface as context.Canceled rather than the FDBError transaction_cancelled (1025) C++ raises via resetPromise.sendError — a known divergence (TODO "watch-path divergences" D5).
func (*Transaction) Set ¶
func (tx *Transaction) Set(key, value []byte)
Set writes a key-value pair.
func (*Transaction) SetAccessSystemKeys ¶
func (tx *Transaction) SetAccessSystemKeys()
SetAccessSystemKeys allows reading AND writing \xff prefix system keys.
func (*Transaction) SetBypassUnreadable ¶
func (tx *Transaction) SetBypassUnreadable(v bool)
SetBypassUnreadable mirrors FDB_TR_OPTION_BYPASS_UNREADABLE (ReadYourWrites.actor.cpp:2611-2613): reads of keys with pending versionstamped writes return the write-map value with the placeholder bytes as written instead of failing with accessed_unreadable (1036); SVK's unmodified-unreadable candidate range reads through to storage. RFC-098.
func (*Transaction) SetCausalReadRisky ¶
func (tx *Transaction) SetCausalReadRisky(v bool)
SetCausalReadRisky sets the causal-read-risky flag. When set, the read version may not reflect the latest committed writes.
func (*Transaction) SetLockAware ¶
func (tx *Transaction) SetLockAware(v bool)
SetLockAware sets the lock-aware flag on the commit request.
func (*Transaction) SetMaxRetryDelay ¶
func (tx *Transaction) SetMaxRetryDelay(ms int64)
SetMaxRetryDelay caps the exponential backoff between retries. Value in milliseconds. Matches C++ FDB_TR_OPTION_MAX_RETRY_DELAY.
func (*Transaction) SetNextWriteNoWriteConflictRange ¶
func (tx *Transaction) SetNextWriteNoWriteConflictRange()
SetNextWriteNoWriteConflictRange causes the next mutation to NOT add a write conflict range. Auto-resets after one mutation. Matches C++ FDB_TR_OPTION_NEXT_WRITE_NO_WRITE_CONFLICT_RANGE.
func (*Transaction) SetPriority ¶
func (tx *Transaction) SetPriority(p TransactionPriority)
SetPriority sets the transaction priority for GRV requests.
func (*Transaction) SetReadLockAware ¶
func (tx *Transaction) SetReadLockAware(v bool)
SetReadLockAware allows reads on locked databases without granting commit access. C++: options.readLockAware — only affects read path.
func (*Transaction) SetReadSystemKeys ¶
func (tx *Transaction) SetReadSystemKeys()
SetReadSystemKeys allows reading \xff prefix system keys.
func (*Transaction) SetReadVersion ¶
func (tx *Transaction) SetReadVersion(version int64)
SetReadVersion sets the read version manually.
func (*Transaction) SetReadYourWritesDisable ¶
func (tx *Transaction) SetReadYourWritesDisable()
SetReadYourWritesDisable disables RYW for regular (non-snapshot) reads. When set, Get/GetRange always read from the server, ignoring uncommitted writes. Matches FDB_TR_OPTION_READ_YOUR_WRITES_DISABLE.
libfdb_c forbids setting this option after any read or write: RYW setOptionImpl throws client_invalid_operation BEFORE assigning the option (ReadYourWrites.actor.cpp:2534-2542), so the option does NOT take effect; the throw lands in deferredError (the option call itself succeeds) and every subsequent op returns 2000 until reset (RFC-059). Match both halves: record the deferred error AND leave rywDisabled unset. A clean (pre-op) disable applies normally.
func (*Transaction) SetRetryLimit ¶
func (tx *Transaction) SetRetryLimit(retries int64)
SetRetryLimit limits the number of retries in OnError. A value of 0 means "don't retry at all" (first error escapes). A value of -1 means "unlimited" (default behavior). Matches C++ FDB_TR_OPTION_RETRY_LIMIT.
func (*Transaction) SetSizeLimit ¶
func (tx *Transaction) SetSizeLimit(limit int64)
SetSizeLimit sets the maximum transaction size in bytes. If the transaction exceeds this size, commit returns error 2101. Valid range: [32, 10_000_000]. Out-of-range values cause error 2006 at commit. A value of 0 disables the limit.
func (*Transaction) SetSkipGrvCache ¶
func (tx *Transaction) SetSkipGrvCache()
SetSkipGrvCache forces this transaction to bypass the GRV cache even if SetUseGrvCache was also set (SKIP_GRV_CACHE, 1102 — skip wins). RFC-104.
func (*Transaction) SetSnapshotRYWDisable ¶
func (tx *Transaction) SetSnapshotRYWDisable()
SetSnapshotRYWDisable decrements the snapshot-RYW enable count (stored as the disabled-oriented inverse, so it increments here). Matches FDB_TR_OPTION_SNAPSHOT_RYW_DISABLE (libfdb_c does enabledCount--). When the net count is > 0 (more disables than enables), Snapshot.Get/GetRange/GetKey read from the server, bypassing the RYW cache.
func (*Transaction) SetSnapshotRYWDisableCount ¶
func (tx *Transaction) SetSnapshotRYWDisableCount(n int)
SetSnapshotRYWDisableCount SETS the snapshot-RYW disable counter to n (vs the ++/-- of SetSnapshotRYWDisable/Enable). It seeds the per-tx counter to a database default. Setting (not incrementing) is idempotent under the retry replay of applyTxDefaults — matching libfdb_c, whose reset() re-seeds snapshotRywEnabled = db->snapshotRywEnabled each attempt rather than accumulating.
func (*Transaction) SetSnapshotRYWEnable ¶
func (tx *Transaction) SetSnapshotRYWEnable()
SetSnapshotRYWEnable re-enables RYW for snapshot reads, undoing one prior SetSnapshotRYWDisable. Matches FDB_TR_OPTION_SNAPSHOT_RYW_ENABLE (libfdb_c does enabledCount++). The option is a counter, not a toggle: two disables require two enables to re-enable, and an enable from the default pushes the count negative (still enabled).
func (*Transaction) SetSpanParent ¶
func (tx *Transaction) SetSpanParent(b []byte) error
SetSpanParent injects a parent trace context (FDBTransactionOptions::SPAN_PARENT, NativeAPI.actor.cpp:7126): a 33-byte IncludeVersion-serialized SpanContext. The transaction's span becomes a child of it (inherit traceID + flags, fresh spanID), and the linkage persists across retries (regenerateSpan honors spanParent).
func (*Transaction) SetTag ¶
func (tx *Transaction) SetTag(tag string)
SetTag adds a tag to this transaction for tag-based throttling. Tags are used for throttle backoff calculation on tag_throttled errors. Matches C++ FDB_TR_OPTION_AUTO_THROTTLE_TAG / FDB_TR_OPTION_DEBUG_TRANSACTION_IDENTIFIER usage.
func (*Transaction) SetTenantId ¶
func (tx *Transaction) SetTenantId(id int64)
SetTenantId sets the tenant for this transaction. All operations will be scoped to the tenant's key space. Use NoTenantID (-1) for no tenant.
func (*Transaction) SetTimeout ¶
func (tx *Transaction) SetTimeout(ms int64)
SetTimeout sets a timeout in milliseconds for this transaction. The timeout is an overall budget from creation time (or last user Reset), NOT per-retry. OnError retries share the same deadline. A value of 0 disables the timeout. Matches C++ FDB_TR_OPTION_TIMEOUT.
func (*Transaction) SetUseGrvCache ¶
func (tx *Transaction) SetUseGrvCache()
SetUseGrvCache opts this transaction in to serving its read version from the database's GRV cache (USE_GRV_CACHE, 1101). Off by default — a default transaction issues a fresh proxy GRV, matching libfdb_c. RFC-104.
func (*Transaction) SetWriteConflictsDisabled ¶
func (tx *Transaction) SetWriteConflictsDisabled()
SetWriteConflictsDisabled disables write conflict ranges for all subsequent mutations. Use for insert-only batch writes where keys are guaranteed unique and all atomic operations commute (ADD, MAX, MIN). Significantly reduces commit request size and eliminates conflict buffer allocations.
func (*Transaction) Snapshot ¶
func (tx *Transaction) Snapshot() *Snapshot
Snapshot returns a snapshot view of this transaction. Snapshot reads do not add read conflict ranges, so they don't cause conflicts with concurrent writers. Same read version, same connection.
func (*Transaction) SnapshotRYWDisableCount ¶
func (tx *Transaction) SnapshotRYWDisableCount() int
SnapshotRYWDisableCount reports the net snapshot-RYW-disable count (> 0 means snapshot reads bypass the RYW cache). Read-only accessor used to verify database-level option propagation.
func (*Transaction) TenantId ¶
func (tx *Transaction) TenantId() int64
TenantId returns the current tenant ID for this transaction. Returns NoTenantID (-1) if no tenant is set.
func (*Transaction) Watch ¶
func (tx *Transaction) Watch(ctx context.Context, key []byte) error
Watch watches a key for changes. The server holds the connection open until the watched key's value changes from the version observed by this transaction. Returns nil when the key has changed, or an error on failure.
Matches C++ NativeAPI.actor.cpp watchValueMap/watchValue flow: locate storage server, send WatchValueRequest with current read version, long-poll for WatchValueReply. Retries on wrong_shard_server with cache invalidation.
The watch is a long-poll: there is no short timeout. The context's deadline (if any) controls the maximum wait time. RFC-170 (#8) note: this SYNCHRONOUS client API registers the watch at the READ version — it blocks in WatchPoll until the watch fires, so it cannot wait for a commit that (by construction) can only happen AFTER it returns. The committed-version deferral (register post-commit) is done by the ASYNC fdb facade Watch (which returns a future and blocks that future's goroutine on the commit-completion signal). Callers of this sync API that need committed-version semantics must commit before/around the watch (C++ setupWatches' committedVersion>0?committedVersion:readVersion applies at the facade, not here).
func (*Transaction) WatchActivation ¶
func (tx *Transaction) WatchActivation() *watchActivation
WatchActivation returns this incarnation's activation, lazily creating it on first use (a fresh handle before any Watch/commit has nil watchAct). Race-safe via CAS so two concurrent Watch() calls share one.
func (*Transaction) WatchPoll ¶
func (tx *Transaction) WatchPoll(watchCtx context.Context, watchCancel context.CancelFunc, key, value []byte, readVersion int64, span types.SpanContext) error
WatchPoll performs the ASYNCHRONOUS long-poll part of a watch: locate the storage server and wait for the WatchValueReply that fires when key's value differs from `value` (captured by WatchSetup), registered at `readVersion` (also captured by WatchSetup — NOT re-read from the possibly-reset transaction). Retries on wrong_shard_server with cache invalidation. Intended to run in the watch future's goroutine.
func (*Transaction) WatchSetup ¶
func (tx *Transaction) WatchSetup(ctx context.Context, key []byte) ([]byte, int64, types.SpanContext, context.Context, context.CancelFunc, error)
WatchSetup performs the SYNCHRONOUS part of a watch: pin the read version, add the read conflict, and read the value to watch — all at the transaction's read version. It returns BOTH the value bytes and the read version the watch must be registered against.
This MUST run within the watching transaction's active window (e.g. directly from Transaction.Watch, not from a detached goroutine that races later mutations). Two things are captured here, both for the same reason:
- the VALUE: if read late — after some other transaction already changed the key — the storage server would be told to watch the *new* value, see the current value already equals it, and never fire (a silent 10s-timeout flake);
- the READ VERSION: the async WatchPoll's sendWatch must NOT read tx.readVersion later, because the common `w := tr.Watch(k)` inside Database.Transact pattern commits and postCommitReset()s the transaction (readVersion → 0) before the future goroutine runs — sending the watch at version 0, which can error or register incorrectly. So the read version is captured synchronously here and threaded through to sendWatch.
type TransactionDefaults ¶
type TransactionDefaults struct {
Timeout int64 // FDB_DB_OPTION_TRANSACTION_TIMEOUT (ms), 0 = disabled
RetryLimit int // FDB_DB_OPTION_TRANSACTION_RETRY_LIMIT
MaxRetryDelay int64 // FDB_DB_OPTION_TRANSACTION_MAX_RETRY_DELAY (ms), 0 = use default
SizeLimit int64 // FDB_DB_OPTION_TRANSACTION_SIZE_LIMIT; 0/unset → 10 MB default (C++ has no "disabled" state)
HasRetryLimit bool
ReadSystemKeys bool // read \xff/* keys by default
AccessSysKeys bool // read+write \xff/* keys by default
}
TransactionDefaults holds database-level defaults applied to every new transaction. Matches C++ DatabaseContext::transactionDefaults.
type TransactionPriority ¶
type TransactionPriority int
TransactionPriority controls the GRV request priority. C++ GetReadVersionRequest::Flags encoding.
const ( PriorityDefault TransactionPriority = iota PriorityBatch PrioritySystemImmediate )
Source Files
¶
- clientmetrics.go
- clusterfile.go
- commitpath.go
- coordinator.go
- database.go
- ddsketch.go
- endpoint.go
- failure_monitor.go
- grv.go
- hedge.go
- loadbalance.go
- locality.go
- metrics.go
- options.go
- panicbackstop.go
- readpath.go
- rpc.go
- ryw.go
- ryw_getkey.go
- ryw_snapshot_cache.go
- sizelimits.go
- span.go
- tag_throttle.go
- tls.go
- topology.go
- transaction.go