Documentation
¶
Overview ¶
Package client implements the FDB client transaction lifecycle. This is the Go equivalent of NativeAPI.actor.cpp.
Index ¶
- Constants
- Variables
- func LookupClusterFileName(filename string) (string, error)
- 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) ConnectionLinger() (minDelay, maxDelay, adaptive time.Duration, waits bool)
- 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) SetTransactionReportConflictingKeys()
- 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 KeySelector
- type KeyValue
- type LatencyStats
- type LocationResult
- type MappedGetRange
- type MappedGetValue
- type MappedKeyValue
- type MappedResultKind
- type Mutation
- type MutationType
- type Option
- func WithAPIVersion(v int) Option
- func WithAdaptiveLinger(d time.Duration) Option
- func WithCoalesceDelay(minDelay, maxDelay time.Duration) Option
- func WithDialFunc(fn DialFunc) Option
- func WithLogger(logger *slog.Logger) Option
- func WithRangeByteCeiling(n int64) Option
- func WithTLSConfig(cfg *tls.Config) Option
- func WithTracer(t oteltrace.Tracer) Option
- func WithTracingSampleRate(rate float64) Option
- type PendingCommit
- type PendingGet
- type PendingKey
- type PendingMappedRange
- type PendingRange
- type PendingValue
- type PendingVersionstamp
- 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) GetRangeOwnedSelectors(ctx context.Context, begin, end KeySelector, limit, byteTarget int, ...) ([]KeyValue, bool, error)
- func (s *Snapshot) GetRangeReverse(ctx context.Context, begin, end []byte, limit int) ([]KeyValue, bool, error)
- func (s *Snapshot) GetRangeSelectors(ctx context.Context, begin, end KeySelector, limit, byteTarget int, ...) ([]KeyValue, bool, error)
- func (s *Snapshot) GetRangeWithByteTarget(ctx context.Context, begin, end []byte, limit, byteTarget int, reverse bool) ([]KeyValue, bool, error)
- func (s *Snapshot) GetReadVersion(ctx context.Context) (int64, error)
- func (s *Snapshot) StartGet(ctx context.Context, key []byte) *PendingValue
- func (s *Snapshot) StartGetKey(ctx context.Context, sel KeySelector) *PendingKey
- func (s *Snapshot) StartGetRange(ctx context.Context, begin, end []byte, limit, byteTarget int, reverse bool) *PendingRange
- func (s *Snapshot) StartGetRangeOwnedSelectors(ctx context.Context, begin, end KeySelector, limit, byteTarget int, ...) *PendingRange
- func (s *Snapshot) StartGetRangeSelectors(ctx context.Context, begin, end KeySelector, limit, byteTarget int, ...) *PendingRange
- type TLSConfigError
- 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) GetMappedRange(ctx context.Context, begin, end, mapper []byte, limit int, reverse bool) ([]MappedKeyValue, bool, error)
- func (tx *Transaction) GetMappedRangeWithByteTarget(ctx context.Context, begin, end, mapper []byte, limit, byteTarget int, ...) ([]MappedKeyValue, bool, error)
- func (tx *Transaction) GetMappedRangeWithByteTargetAndSkip(ctx context.Context, begin, end, mapper []byte, limit, byteTarget int, ...) ([]MappedKeyValue, bool, 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) GetRangeOwnedSelectors(ctx context.Context, begin, end KeySelector, limit, byteTarget int, ...) ([]KeyValue, bool, error)
- func (tx *Transaction) GetRangeReverse(ctx context.Context, begin, end []byte, limit int) ([]KeyValue, bool, error)
- func (tx *Transaction) GetRangeSelectors(ctx context.Context, begin, end KeySelector, limit, byteTarget int, ...) ([]KeyValue, bool, error)
- func (tx *Transaction) GetRangeSplitPoints(parentCtx context.Context, begin, end []byte, chunkSize int64) ([][]byte, error)
- func (tx *Transaction) GetRangeWithByteTarget(ctx context.Context, begin, end []byte, limit, byteTarget int, reverse bool) ([]KeyValue, bool, error)
- func (tx *Transaction) GetReadVersion(ctx context.Context) (int64, error)
- func (tx *Transaction) GetTagThrottledDuration() float64
- func (tx *Transaction) GetVersionstamp() ([]byte, error)
- func (tx *Transaction) GetVersionstampPending(parent context.Context) ([]byte, *PendingVersionstamp, error)
- func (tx *Transaction) LockAware() bool
- func (tx *Transaction) OnError(ctx context.Context, err error) (rerr error)
- func (tx *Transaction) PrepareCommit(parent context.Context) *PendingCommit
- func (tx *Transaction) ReadLockAware() bool
- func (tx *Transaction) ReadTags() []string
- func (tx *Transaction) ReadVersionInstant() (time.Time, bool)
- func (tx *Transaction) ReleaseWatch()
- func (tx *Transaction) Reset()
- func (tx *Transaction) Set(key, value []byte)
- func (tx *Transaction) SetAccessSystemKeys()
- func (tx *Transaction) SetAutoThrottleTag(tag string) error
- func (tx *Transaction) SetBypassUnreadable(v bool)
- func (tx *Transaction) SetCausalReadRisky(v bool)
- func (tx *Transaction) SetLockAware()
- func (tx *Transaction) SetMaxRetryDelay(ms int64)
- func (tx *Transaction) SetNextWriteNoWriteConflictRange()
- func (tx *Transaction) SetPriority(p TransactionPriority)
- func (tx *Transaction) SetReadLockAware()
- func (tx *Transaction) SetReadSystemKeys()
- func (tx *Transaction) SetReadVersion(version int64)
- func (tx *Transaction) SetReadYourWritesDisable()
- func (tx *Transaction) SetReportConflictingKeys()
- 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) SetSpecialKeySpaceRelaxed()
- func (tx *Transaction) SetTag(tag string) error
- 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) StartGet(ctx context.Context, key []byte) *PendingValue
- func (tx *Transaction) StartGetKey(ctx context.Context, sel KeySelector) *PendingKey
- func (tx *Transaction) StartGetMappedRange(parent context.Context, begin, end, mapper []byte, limit, byteTarget int, ...) *PendingMappedRange
- func (tx *Transaction) StartGetMappedRangeWithSkip(parent context.Context, begin, end, mapper []byte, limit, byteTarget int, ...) *PendingMappedRange
- func (tx *Transaction) StartGetRange(ctx context.Context, begin, end []byte, limit, byteTarget int, reverse bool) *PendingRange
- func (tx *Transaction) StartGetRangeOwnedSelectors(ctx context.Context, begin, end KeySelector, limit, byteTarget int, ...) *PendingRange
- func (tx *Transaction) StartGetRangeSelectors(ctx context.Context, begin, end KeySelector, limit, byteTarget int, ...) *PendingRange
- func (tx *Transaction) Tags() []string
- func (tx *Transaction) TenantId() int64
- func (tx *Transaction) Watch(ctx context.Context, key []byte) error
- func (tx *Transaction) WatchActivation() *watchActivation
- func (tx *Transaction) WatchActivationFor(ctx context.Context) *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 ( // ErrClientInvalidOperation is raised for a mapped read over the special // key space, which getMappedRange does not support. ErrClientInvalidOperation = 2000 // client_invalid_operation // ErrMapperBadIndex ... ErrMapperNotTuple are raised by the STORAGE SERVER, // never by this client — the mapper is not parsed here. They are named so a // caller can errors.As them and so the propagate-unchanged contract is // testable. ErrMapperBadIndex = 2030 // mapper_bad_index ErrMapperNoSuchKey = 2031 // mapper_no_such_key ErrMapperBadRangeDescrptor = 2032 // mapper_bad_range_decriptor (sic: the C++ spelling) // ErrKeyNotTuple / ErrValueNotTuple are raised when a {K[n]} / {V[n]} // placeholder forces the server to unpack a PRIMARY row that is not a packed // tuple (unpackKeyTuple / unpackValueTuple, storageserver.actor.cpp:4820-4844). // They are properties of the DATA, not of the mapper, so no amount of mapper // checking anywhere would pre-empt them. ErrKeyNotTuple = 2041 // key_not_tuple ErrValueNotTuple = 2042 // value_not_tuple // ErrGetMappedRangeReadsYourWrites is raised by THIS client when the mapped // read — primary range or any resolved secondary read — overlaps a key the // transaction has already written. ErrGetMappedRangeReadsYourWrites = 2039 // get_mapped_range_reads_your_writes ErrMapperNotTuple = 2043 // mapper_not_tuple // ErrUnsupportedOperation is what snapshot=true and read-your-writes-disabled // both raise. Neither is a MODE for getMappedRange; both are errors. ErrUnsupportedOperation = 2108 // unsupported_operation )
FDB error codes specific to getMappedRange. Source of truth: flow/include/flow/error_definitions.h at the 7.3.77 tag.
const ( MinAPIVersion = 510 MaxAPIVersion = 730 )
The API version range this client accepts. MaxAPIVersion is libfdb_c 7.3's FDB_API_VERSION; below MinAPIVersion would need semantics this client does not model. 510-699 run with 7.x semantics apart from the 510/520 gates.
const ( ErrSpecialKeysCrossModuleRead = 2112 ErrSpecialKeysNoModuleFound = 2113 ErrIllegalTenantAccess = 2138 )
The special key space read errors and illegal_tenant_access (error_definitions.h:251-252, 273); unreached impls fail with ErrUnsupportedOperation (2108).
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) ErrTransactionCancelled = 1025 // transaction_cancelled 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 ErrServerOverloaded = 1211 // server_overloaded 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) ErrRequestMaybeDelivered = 1030 // request_maybe_delivered — an in-flight RPC's connection died (transport teardown); reads retry another alternative, commit maps it to 1021 ErrBrokenPromise = 1100 // broken_promise — the peer dropped the reply promise; same maybeDelivered class as 1030 (LoadBalance.actor.h:344) ErrInvertedRange = 2005 // inverted_range (begin > end) ErrInvalidOptionValue = 2006 // invalid_option_value (e.g. SIZE_LIMIT outside [32, 1e7]) ErrRangeLimitsInvalid = 2012 // range_limits_invalid (e.g. a row limit < -1) ErrInternalError = 4100 // internal_error ErrInvalidMutationType = 2018 // invalid_mutation_type (a non-atomic op passed to Atomic()) ErrTransactionReadOnly = 2023 // transaction_read_only (a READ_LOCK_AWARE txn committed writes) ErrTenantNotFound = 2131 // tenant_not_found )
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 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 // getMappedKeyValues is DECLARED right after getKeyValues // (StorageServerInterface.h:103) but assigned getAdjustedEndpoint(14) // (:184-185) — it was appended after getKeyValuesStream so the pre-existing // indices stayed stable. Taking the index from the declaration order would // address getShardState (3) instead. EndpointGetMappedKeyValues = 14 // StorageServerInterface::getMappedKeyValues 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
const ( // ByteLimitUnlimited mirrors GetRangeLimits::BYTE_LIMIT_UNLIMITED (FDBTypes.h). A range // read carrying it has no per-fetch byte TARGET — only the flat replyByteLimit ceiling // applies — so the soft byte limit in rangeScanImpl can never fire and the scan stays // bounded by rows alone. This is EXACT's value, per mode_bytes_array[EXACT] (fdb_c.cpp:1002). ByteLimitUnlimited = -1 )
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 ¶
func LookupClusterFileName ¶
LookupClusterFileName matches C++ ClusterConnectionFile::lookupClusterFileName: explicit path, present FDB_CLUSTER_FILE, local fdb.cluster, platform default. A configured path that cannot be read never falls back to another file.
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 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)
GRVInBandMaybeDelivered int64 // GRV replies whose in-band error took the next-alternative arm
TransactionRetries int64
TransactionGetRangeRequests int64 // range reads that reached storage (C++ GetRangeRequests)
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
// Epoch is the cluster epoch these proxies belong to. It rides the SNAPSHOT
// rather than living beside it, so a caller that loads the proxies gets the
// epoch of the very set it is about to talk to — the epoch a request binds
// to cannot describe a proxy set the request did not use, because there is
// no second load in which the two could disagree.
//
// Set exclusively by installProxySet, which also owns the ordering against
// grvCache's fence word. See the coherence rule documented there.
Epoch int64
}
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) Close ¶
Close is idempotent. It joins database workers, shared dials and all connection teardown, including transports already evicted from the pool.
func (*Database) ConnectionLinger ¶
ConnectionLinger reports the active write-delay and adaptive-linger settings of a pooled or most recently dialed connection.
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 enables budget-funded speculative read requests (default on). Disabled, no read hedges; lone replies still accrue budget (RFC-281).
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) SetTransactionReportConflictingKeys ¶
func (d *Database) SetTransactionReportConflictingKeys()
SetTransactionReportConflictingKeys is the database option TRANSACTION_REPORT_CONFLICTING_KEYS (702, defaultFor 712): every transaction, and every reset or retry of one, starts with SetReportConflictingKeys (ReadYourWrites.actor.cpp:1553-1556, 2722-2723, 2751-2754).
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 KeySelector ¶
KeySelector mirrors C++ KeySelectorRef for the secondary range bounds.
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 MappedGetRange ¶
type MappedGetRange struct {
Begin KeySelector
End KeySelector
Rows []KeyValue
More bool
}
MappedGetRange is the range arm (C++ GetRangeReqAndResultRef, FDBTypes.h:873). Begin/End are the selectors the server actually resolved, so a range that matched nothing still reports what it probed.
type MappedGetValue ¶
MappedGetValue is the point-lookup arm (C++ GetValueReqAndResultRef, FDBTypes.h:855). Present distinguishes "the mapped key holds an empty value" from "the mapped key does not exist" — the C++ field is Optional<ValueRef> and collapsing the two would silently invent a record.
type MappedKeyValue ¶
type MappedKeyValue struct {
Key []byte
Value []byte
Kind MappedResultKind
GetValue MappedGetValue
GetRange MappedGetRange
}
MappedKeyValue is one row of a mapped range: the primary row (Key/Value — the index entry that was scanned) plus the secondary read the mapper resolved it to. Mirrors C++ MappedKeyValueRef (FDBTypes.h:895), whose KeyValueRef base carries the primary row.
type MappedResultKind ¶
type MappedResultKind uint8
MappedResultKind names which arm of the per-row union is populated. It mirrors the std::variant index in MappedReqAndResultRef, and the underlying values are the flatbuffers union tags (1-based, 0 = unset) so a decode is a direct read.
const ( // MappedResultNone means the row carried no secondary result at all. The // storage server does not produce this, but the tag is representable on the // wire (tag 0), so it is named rather than silently conflated with a // point-lookup miss — those are different facts. MappedResultNone MappedResultKind = 0 // MappedResultGetValue: the mapper resolved to a single key. MappedResultGetValue MappedResultKind = 1 // MappedResultGetRange: the mapper ended in a "{...}" range descriptor and // resolved to a key range. MappedResultGetRange MappedResultKind = 2 )
func (MappedResultKind) String ¶
func (k MappedResultKind) String() string
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 (2200) or one outside [MinAPIVersion, MaxAPIVersion] (api_version_not_supported, 2203), the Apple Go binding's answer. Gates version-dependent wire behaviour, e.g. the Min→MinV2/And→AndV2 atomic upgrade at >=510.
func WithAdaptiveLinger ¶
WithAdaptiveLinger configures Nagle-style adaptive linger on the D-NG writer (0 disables; the last linger/coalesce option wins; RFC-282).
func WithCoalesceDelay ¶
WithCoalesceDelay sets each connection's timer-based batch delay bounds (default 0, 0 on D-NG; 10/20 µs on WithLegacyWriter(); the last linger/coalesce option wins).
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. The config keeps Go's verification, including a host-name check against each dialed address, which libfdb_c does not make; for libfdb_c's check set InsecureSkipVerify and transport.VerifyPolicy's VerifyConnection.
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 PendingCommit ¶
type PendingCommit struct {
// contains filtered or unexported fields
}
PendingCommit is a synchronously admitted producer. Resolve executes exactly once; the facade starts it eagerly in its normal panic-protected future. No execution lease escapes preparation, even if this handle is never consumed.
func (*PendingCommit) Resolve ¶
func (p *PendingCommit) Resolve() error
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 serializes the owner of a pending read's response, timer, handle and retained context. A retired future may consume a ready reply, never retry through the replacement transaction. Repeated callers receive the memo.
func (*PendingGet) ResolveOrAbort ¶
func (p *PendingGet) ResolveOrAbort(abort <-chan struct{}) ([]byte, error, bool)
ResolveOrAbort is Resolve whose waits also end when abort closes, as a cancelled future's waiter wakes in libfdb_c; the read still completes.
type PendingKey ¶
type PendingKey struct {
// contains filtered or unexported fields
}
PendingKey is a started getKey, like the future fdb_transaction_get_key returns.
func (*PendingKey) Get ¶
func (p *PendingKey) Get() ([]byte, error)
Get waits for the read and returns the resolved key (the caller's own copy).
type PendingMappedRange ¶
type PendingMappedRange struct {
// contains filtered or unexported fields
}
PendingMappedRange is a started mapped read. Repeated Get calls return the same caller-owned result; its bytes are never recycled by a later read.
func (*PendingMappedRange) Get ¶
func (p *PendingMappedRange) Get() ([]MappedKeyValue, bool, error)
type PendingRange ¶
type PendingRange struct {
// contains filtered or unexported fields
}
PendingRange is a started range read, like the future fdb_transaction_get_range returns.
func (*PendingRange) Get ¶
func (p *PendingRange) Get() ([]KeyValue, bool, error)
Get waits for the read and returns its rows (the caller's own copy, as each Get of a libfdb_c future copies), whether more remain, and its error. A caller that asks before the background goroutine has started runs the read itself, saving the handoff.
type PendingValue ¶
type PendingValue struct {
// contains filtered or unexported fields
}
PendingValue is a Get issued in the call; Get waits for its value.
func (*PendingValue) Get ¶
func (p *PendingValue) Get() ([]byte, error)
Get returns the value; every call returns the same result.
func (*PendingValue) Ready ¶
func (p *PendingValue) Ready() bool
Ready reports a value already decided: Get does not wait.
type PendingVersionstamp ¶
type PendingVersionstamp struct {
// contains filtered or unexported fields
}
PendingVersionstamp retains its admission and completion owner across Reset. It holds no execution lease while waiting, so an unconsumed future cannot block turnover. Caller interruption is memoized per handle, not in the shared promise.
func (*PendingVersionstamp) Resolve ¶
func (p *PendingVersionstamp) Resolve() ([]byte, error)
type QueueModel ¶
type QueueModel struct {
// contains filtered or unexported fields
}
QueueModel tracks per-server outstanding depth, latency, penalty and backoff, plus C++'s database-wide second-request budget and adaptive delay (RFC-281). No number depends on two servers or a server and the pair, so per-server and pair locks keep each one serial, as C++'s single network thread does.
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 retain the storage cache; pending writes are included 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 retain the storage cache; pending writes are included unless snapshot RYW is net-disabled (snapshotRYWDisableCount > 0).
func (*Snapshot) GetRangeOwnedSelectors ¶
func (s *Snapshot) GetRangeOwnedSelectors(ctx context.Context, begin, end KeySelector, limit, byteTarget int, reverse bool) ([]KeyValue, bool, error)
GetRangeOwnedSelectors is the snapshot form of Transaction.GetRangeOwnedSelectors.
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 retain the storage cache; pending writes are included unless snapshot RYW is net-disabled (snapshotRYWDisableCount > 0).
func (*Snapshot) GetRangeSelectors ¶
func (s *Snapshot) GetRangeSelectors(ctx context.Context, begin, end KeySelector, limit, byteTarget int, reverse bool) ([]KeyValue, bool, error)
GetRangeSelectors is the snapshot form of Transaction.GetRangeSelectors.
func (*Snapshot) GetRangeWithByteTarget ¶
func (s *Snapshot) GetRangeWithByteTarget(ctx context.Context, begin, end []byte, limit, byteTarget int, reverse bool) ([]KeyValue, bool, error)
GetRangeWithByteTarget is GetRange carrying a per-fetch BYTE target, the dimension libfdb_c derives from the streaming mode (fdb_c.cpp:1002/1006). ByteLimitUnlimited means "no target", which is what the plain GetRange passes and what EXACT resolves to.
func (*Snapshot) GetReadVersion ¶
GetReadVersion returns the read version for this transaction via its snapshot view.
func (*Snapshot) StartGet ¶
func (s *Snapshot) StartGet(ctx context.Context, key []byte) *PendingValue
StartGet is the snapshot form of Transaction.StartGet.
func (*Snapshot) StartGetKey ¶
func (s *Snapshot) StartGetKey(ctx context.Context, sel KeySelector) *PendingKey
StartGetKey is the snapshot form of Transaction.StartGetKey.
func (*Snapshot) StartGetRange ¶
func (s *Snapshot) StartGetRange(ctx context.Context, begin, end []byte, limit, byteTarget int, reverse bool) *PendingRange
StartGetRange is the snapshot form of Transaction.StartGetRange.
func (*Snapshot) StartGetRangeOwnedSelectors ¶
func (s *Snapshot) StartGetRangeOwnedSelectors(ctx context.Context, begin, end KeySelector, limit, byteTarget int, reverse bool) *PendingRange
StartGetRangeOwnedSelectors is the snapshot form of Transaction.StartGetRangeOwnedSelectors.
func (*Snapshot) StartGetRangeSelectors ¶
func (s *Snapshot) StartGetRangeSelectors(ctx context.Context, begin, end KeySelector, limit, byteTarget int, reverse bool) *PendingRange
StartGetRangeSelectors is the snapshot form of Transaction.StartGetRangeSelectors.
type TLSConfigError ¶
TLSConfigError reports a TLS setting that cannot be used. It is tls_error (2107): errors.As finds a *wire.FDBError with that code, and the cause.
func (*TLSConfigError) Error ¶
func (e *TLSConfigError) Error() string
func (*TLSConfigError) Unwrap ¶
func (e *TLSConfigError) Unwrap() []error
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). An illegal key defers 2004 (RFC-268).
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 only inverted_range (2005); key_outside_legal_range is deferred, as in libfdb_c (RFC-268).
func (*Transaction) AddWriteConflictKey ¶
func (tx *Transaction) AddWriteConflictKey(key []byte)
AddWriteConflictKey adds a write conflict on a single key. A key past the maximum write key defers key_outside_legal_range (2004) as AddWriteConflictRange does.
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. As in libfdb_c, an endpoint past the maximum write key is not returned here: key_outside_legal_range (2004) becomes the deferred error that the next operation and Commit return.
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) ClearRange ¶
func (tx *Transaction) ClearRange(begin, end []byte) error
ClearRange deletes all keys in [begin, end). Returns inverted_range (2005) if begin > end; C++ ThreadSafeTransaction::clear raises it as the transaction's deferred error (ThreadSafeTransaction.cpp:626-640). A zero-width range inside the legal range is ignored; outside it, it defers key_outside_legal_range (2004) as C++ does (ReadYourWrites.actor.cpp:2370-2372, 2396).
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 preserves Go's auto-reuse extension; C++ RYW API >=410 does not reset after commit (ReadYourWrites.actor.cpp:1383-1387,1405-1410).
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 sizeof(KeyRangeRef) + 2*len(key) + 1 for the auto-generated write conflict range (ReadYourWrites.actor.cpp:2289-2290, :2337-2338).
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: C++ RYW getKey (ReadYourWrites.actor.cpp:1695-1709), which walks the pending writes and the snapshot cache and reads storage only for what they do not answer (RFC-262 D6).
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) GetMappedRange ¶
func (tx *Transaction) GetMappedRange(ctx context.Context, begin, end, mapper []byte, limit int, reverse bool) ([]MappedKeyValue, bool, error)
GetMappedRange reads the primary range [begin, end) and, for each row, the secondary read the `mapper` tuple resolves it to — C++ ReadYourWritesTransaction::getMappedRange (ReadYourWrites.actor.cpp:1779).
The guard sequence below is C++'s, in C++'s order, and the order is load-bearing: the special-key, legal-range and limit checks all run BEFORE the snapshot / RYW-disabled guard, so a mapped read that is invalid for two reasons reports the FIRST one C++ would report.
`limit` follows the C API, not the internal GetRangeLimits: fdb_c's validate_and_update_parameters maps 0 to ROW_LIMIT_UNLIMITED before RYW ever sees it (fdb_c.cpp:990-992), and fdb_transaction_get_mapped_range runs that same validator (:1080). So 0 here means UNLIMITED, and GetRangeLimits::isReached()'s "limit 0 returns an empty result" branch (NativeAPI.actor.cpp:2856) is unreachable from any C-API caller. A limit < -1 is range_limits_invalid, matching GetRangeLimits::isValid (FDBTypes.h:753).
Isolation: this ALWAYS issues at Snapshot::True and then re-adds read conflict ranges by hand — for the primary range AND for every secondary read the server resolved (ReadYourWrites.actor.cpp:1163-1192). That is not an optimization; it is what makes a serializable mapped read correct, because the secondary keys are not known until the reply comes back and so cannot be conflict-ranged up front. Any caller building a remote-fetch cursor on top of this inherits the same obligation.
func (*Transaction) GetMappedRangeWithByteTarget ¶
func (tx *Transaction) GetMappedRangeWithByteTarget(ctx context.Context, begin, end, mapper []byte, limit, byteTarget int, reverse bool) ([]MappedKeyValue, bool, error)
GetMappedRangeWithByteTarget carries the streaming mode's per-fetch byte target, as fdb_transaction_get_mapped_range does. Zero and ByteLimitUnlimited mean unlimited.
func (*Transaction) GetMappedRangeWithByteTargetAndSkip ¶
func (tx *Transaction) GetMappedRangeWithByteTargetAndSkip(ctx context.Context, begin, end, mapper []byte, limit, byteTarget int, skip int32, reverse bool) ([]MappedKeyValue, bool, error)
GetMappedRangeWithByteTargetAndSkip resolves the initial Skip with ordinary reads, without issuing secondary reads for the skipped primary rows. Nonpositive Skip retains GetMappedRangeWithByteTarget's existing exact path.
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) GetRangeOwnedSelectors ¶
func (tx *Transaction) GetRangeOwnedSelectors(ctx context.Context, begin, end KeySelector, limit, byteTarget int, reverse bool) ([]KeyValue, bool, error)
GetRangeOwnedSelectors is StartGetRangeOwnedSelectors waited for in the call.
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) GetRangeSelectors ¶
func (tx *Transaction) GetRangeSelectors(ctx context.Context, begin, end KeySelector, limit, byteTarget int, reverse bool) ([]KeyValue, bool, error)
GetRangeSelectors is StartGetRangeSelectors waited for in the call.
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) GetRangeWithByteTarget ¶
func (tx *Transaction) GetRangeWithByteTarget(ctx context.Context, begin, end []byte, limit, byteTarget int, reverse bool) ([]KeyValue, bool, error)
GetRangeWithByteTarget is GetRange carrying a per-fetch BYTE target — the dimension libfdb_c derives from the streaming mode and puts on the request, where the storage server truncates against it. That truncation, not any client-side accounting, is what divides a scan into batches; see rangeScanImpl's soft byte limit for the half that ends the call. ByteLimitUnlimited means "no target", which is what plain GetRange passes and what EXACT resolves to.
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) GetVersionstampPending ¶
func (tx *Transaction) GetVersionstampPending(parent context.Context) ([]byte, *PendingVersionstamp, error)
GetVersionstampPending captures entry synchronously. A nil pending handle denotes an already-selected value/error; otherwise Resolve waits for this incarnation's native versionstamp outcome or its captured retirement signal.
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. Retry log handlers receive the original caller context, not this operation's cancellation context.
func (*Transaction) PrepareCommit ¶
func (tx *Transaction) PrepareCommit(parent context.Context) *PendingCommit
PrepareCommit binds the producer before the facade starts asynchronous work. The synchronous Commit path uses the same admission without a future goroutine.
func (*Transaction) ReadLockAware ¶
func (tx *Transaction) ReadLockAware() bool
ReadLockAware reports whether reads bypass the locked-database check. Mirrors SetReadLockAware.
func (*Transaction) ReadTags ¶
func (tx *Transaction) ReadTags() []string
ReadTags returns the auto-throttle (read) tag subset in insertion order.
func (*Transaction) ReadVersionInstant ¶
func (tx *Transaction) ReadVersionInstant() (time.Time, bool)
ReadVersionInstant reports when this transaction's current read version was obtained from the cluster, i.e. when FDB's 5-second MVCC window opened for it. ok is false when no read version is held, or when the version was supplied by SetReadVersion (whose window opened at an instant this client never observed).
It exists so a layer above can budget against the window that actually applies. Anchoring such a budget on "when I started working" is wrong in both directions: a transaction that idles before its first read has not yet opened a window, and a retried transaction opened a fresh one. Only the GRV instant tracks it.
Callers MUST honour ok rather than treating a zero time as an anchor.
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 retry state and restores options to database defaults, matching C++ ReadYourWritesTransaction::reset(). The last committed version is preserved. Updates creationTime so the timeout budget restarts (matches C++ reset() behavior).
Uncommitted Watch() calls are cancelled by Reset(); committed watches survive. Cancelled watches 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) SetAutoThrottleTag ¶
func (tx *Transaction) SetAutoThrottleTag(tag string) error
SetAutoThrottleTag adds a tag that is additionally eligible for ratekeeper auto-throttling, matching FDBTransactionOptions::AUTO_THROTTLE_TAG (NativeAPI.actor.cpp:7120-7124): the tag goes into BOTH the transaction tag set and the read tag set. The transaction set drives the GRV request and the commit tagSet; the read set is what C++ samples onto per-storage-server read requests.
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()
SetLockAware makes reads and the commit lock-aware, and lifts a read-only state left by SetReadLockAware (C++ LOCK_AWARE, NativeAPI.actor.cpp:7071-7079).
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()
SetReadLockAware makes reads lock-aware and, unless SetLockAware came first, makes the transaction read-only: a commit with writes fails 2023 (C++ READ_LOCK_AWARE, NativeAPI.actor.cpp:7082-7091; checked at :6810).
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); this client behaves the same. A clean (pre-op) disable applies normally.
func (*Transaction) SetReportConflictingKeys ¶
func (tx *Transaction) SetReportConflictingKeys()
SetReportConflictingKeys is REPORT_CONFLICTING_KEYS (712): the next commit asks the proxy for the read conflict ranges that conflicted (NAPI:7135-7137, 6887-6889), which a not_committed then leaves readable under \xff\xff/transaction/conflicting_keys/. Not persistent (fdb.options:327): reset and OnError restore the database default.
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; a larger commit fails 2101. Outside [32, 10_000_000] the limit is not applied and 2006 becomes the deferred error every later op returns until reset, as libfdb_c's extractIntOption throw lands in deferredError (NativeAPI.actor.cpp:7067-7069).
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) SetSpecialKeySpaceRelaxed ¶
func (tx *Transaction) SetSpecialKeySpaceRelaxed()
SetSpecialKeySpaceRelaxed is SPECIAL_KEY_SPACE_RELAXED (RYW:2603-2605): a special key range read may span modules or none (SKS:331-352). Not persistent.
func (*Transaction) SetTag ¶
func (tx *Transaction) SetTag(tag string) error
SetTag adds a tag to this transaction for tag-based throttling, matching FDBTransactionOptions::TAG (NativeAPI.actor.cpp:7115-7118).
Check order follows TagSet::addTag (TagThrottle.actor.cpp:35-39) exactly: length is validated first, then the count — and the count is checked BEFORE the duplicate test, so adding a duplicate to an already-full set still fails with too_many_tags rather than silently succeeding.
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) StartGet ¶
func (tx *Transaction) StartGet(ctx context.Context, key []byte) *PendingValue
StartGet issues a Get in the call, as fdb_transaction_get does (ThreadSafeTransaction.cpp:426-434); Commit waits for its server read whether or not Get is called (RYW:1690-1691, 1359-1360).
func (*Transaction) StartGetKey ¶
func (tx *Transaction) StartGetKey(ctx context.Context, sel KeySelector) *PendingKey
StartGetKey starts a getKey and returns at once. The selector is resolved against the write map as of this call; GRV, location lookup and requests run in the background, and Commit waits for the read whether or not Get is called (RYW:1706).
func (*Transaction) StartGetMappedRange ¶
func (tx *Transaction) StartGetMappedRange(parent context.Context, begin, end, mapper []byte, limit, byteTarget int, reverse bool) *PendingMappedRange
StartGetMappedRange captures the transaction incarnation and arguments before starting I/O, so Reset cannot move the pending read into the new transaction.
func (*Transaction) StartGetMappedRangeWithSkip ¶
func (tx *Transaction) StartGetMappedRangeWithSkip(parent context.Context, begin, end, mapper []byte, limit, byteTarget int, skip int32, reverse bool) *PendingMappedRange
StartGetMappedRangeWithSkip captures Skip with the original incarnation and arguments. The pending read does not introduce an issued-read Commit barrier.
func (*Transaction) StartGetRange ¶
func (tx *Transaction) StartGetRange(ctx context.Context, begin, end []byte, limit, byteTarget int, reverse bool) *PendingRange
StartGetRange starts a range read and returns at once; GRV, location lookup and request run in the background, and Commit waits for the read whether or not Get is called (:1767).
func (*Transaction) StartGetRangeOwnedSelectors ¶
func (tx *Transaction) StartGetRangeOwnedSelectors(ctx context.Context, begin, end KeySelector, limit, byteTarget int, reverse bool) *PendingRange
StartGetRangeOwnedSelectors is StartGetRangeSelectors for selectors whose keys the caller hands over: it never modifies them afterwards, so the read keeps them instead of copying them.
func (*Transaction) StartGetRangeSelectors ¶
func (tx *Transaction) StartGetRangeSelectors(ctx context.Context, begin, end KeySelector, limit, byteTarget int, reverse bool) *PendingRange
StartGetRangeSelectors starts a range read between two key selectors and returns at once, like fdb_transaction_get_range: the selectors are resolved within the range read, against the transaction's writes and snapshot cache and by the storage server (RYW:592-813, 896-1123). limit 0 and -1 are unlimited rows; byteTarget 0 is no byte limit. Commit waits for the read whether or not Get is called (RYW:1767).
func (*Transaction) Tags ¶
func (tx *Transaction) Tags() []string
Tags returns the transaction tag set in insertion order. Insertion order is the wire order for the commit tagSet, so tests can assert it directly.
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) WatchActivationFor ¶
func (tx *Transaction) WatchActivationFor(ctx context.Context) *watchActivation
WatchActivationFor returns the activation captured by WatchSetup. Keeping activation and read version in one setup incarnation prevents Reset between setup and future construction from binding the watch to its successor.
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.
Its requests carry the read tags as of the commit that activated the watch (setupWatches, NativeAPI.actor.cpp:6418-6432), or those captured at setup when no commit activated it.
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
// ReportConflictingKeys is FDB_DB_OPTION_TRANSACTION_REPORT_CONFLICTING_KEYS (702).
ReportConflictingKeys bool
}
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
- clusterfile_default_unix.go
- clusterfile_lookup.go
- commit_input.go
- commitpath.go
- conflict_map.go
- coordinator.go
- database.go
- ddsketch.go
- endpoint.go
- failure_monitor.go
- grv.go
- grv_window.go
- hedge.go
- inband_reply_error.go
- key_issue.go
- key_selector.go
- loadbalance.go
- locality.go
- mappedrange.go
- mappedrange_pending.go
- mappedrange_selectors.go
- mappedrange_skip.go
- metrics.go
- native_commit.go
- native_range.go
- options.go
- panicbackstop.go
- peer_send.go
- pending_get.go
- range_issue.go
- range_limits.go
- range_selector_issue.go
- read_incarnation.go
- read_send.go
- read_tags.go
- read_version_state.go
- readpath.go
- reply_guard.go
- rpc.go
- ryw.go
- ryw_getkey.go
- ryw_nodes.go
- ryw_pseq.go
- ryw_snapshot_cache.go
- ryw_walk.go
- ryw_walk_iter.go
- ryw_writes.go
- sizelimits.go
- span.go
- specialkeys.go
- tag_throttle.go
- timeout_design.go
- timeout_queue.go
- tls.go
- tls_key.go
- topology.go
- transaction.go
- transaction_lifetime.go
- transaction_state_entry.go
- versionstamp.go