Couchbase Go SDK

repository·master·Indexed 18 days ago

https://github.com/couchbase/gocb

A pure Go library that enables Go applications to interact with Couchbase clusters using the Couchbase binary protocol via the gocbcore library. It provides functionality for connecting to clusters, managing buckets, scopes, and collections, and performing ACID transactions. The SDK includes features for authentication (Password and Certificate), circuit breaker configuration, and operation management including retries, timeouts, and OpenTelemetry tracing.

Tokens
8.8K
Snippets
28
Records
40
Agent score
61%

What's inside gocb

  1. GRPC Package Naming and Structure

    master

    The FIT GRPC uses a specific package naming convention to ensure compatibility with Go and Java, and to support hierarchical levels (Cluster, Scope, Collection).

    Naming Conventions:

    • Flat Directory Structure: Used to allow performers to pull in all protobuf files easily.
    • Filename Mapping: Filenames include the package name to replace a directory structure (e.g., sdk.kv.options.proto belongs to package protocol.sdk.kv).
    • Specificity Hierarchy: Package names follow a pattern where the right-most part identifies the broad component, and preceding parts add specificity. Example: sdk.cluster.query.index_manager identifies an IndexManager that is a Query type at the Cluster level.
    • Shared Code: The protocol.shared package is reserved for code shared between the SDK and transactions.
    • Naming Style: Use sdk.kv.Get rather than sdk.kv.SdkKvGet (Exception: transactions.TransactionResult).

    Constraints:

    • Avoid Import Cycles: Ensure protobuf imports do not create cycles that prevent Go compilation.
    • Filename/Message Uniqueness: Do not name a .proto file the same as an existing enum or message (e.g., if PerformerCaps exists, do not name the file performer_caps.proto) to avoid Java compilation errors.
  2. How the Couchbase Go Client works

    master
    The gocb library is a pure Go implementation that allows Go applications to connect to a Couchbase cluster. It leverages an internal gocbcore library to manage communication with the cluster using the Couchbase binary protocol.
  3. Rules for FIT GRPC Performers

    master

    Performers in the FIT GRPC framework are designed to be 'dumb-as-rocks passthrough agents'. They should not interpret or manipulate data, but rather act as a transparent layer between the SDK and the test environment.

    Key operational rules:

    • Direct Field Passing: Pass all fields to the SDK exactly as received. Do not modify values (e.g., do not prepend couchbase:// to connection strings) as this masks SDK bugs and causes driver issues.
    • Error Handling: If a performer receives an RPC or parameter that it or the SDK cannot recognize, it should raise UNSUPPORTED. This includes the default behavior for any oneof handling.
    • Optional Configuration: When configuration blocks are optional and not provided, the performer should call the appropriate no-option overload (e.g., cluster.query(statement) instead of cluster.query(statement, options)).
  4. Install the Couchbase Go SDK

    master

    To use the Couchbase Go SDK in your project, use the go get command. You can choose between the latest stable release or the latest developer version from the master branch.

    # Install the latest stable version
    go get github.com/couchbase/gocb/v2@latest
    
    # Install the latest developer version
    go get github.com/couchbase/gocb/v2@master
  5. Configure query scan consistency

    master

    When executing a query, you can specify the level of data consistency required using QueryOptions.ScanConsistency.

    Important: You must use either ScanConsistency OR ConsistentWith, but not both. If both are provided, the operation will return an error.

    Available consistency levels:

    • QueryScanConsistencyNotBounded: No data consistency is required (fastest).
    • QueryScanConsistencyRequestPlus: Requires request-level data consistency.
    • ConsistentWith: Uses a MutationState to ensure the query is consistent with a specific set of mutations (uses at_plus consistency internally).
    import "github.com/couchbase/gocb/v2"
    
    // Example: Request-level consistency
    opts := gocb.QueryOptions{
        ScanConsistency: gocb.QueryScanConsistencyRequestPlus,
    }
    
    // Example: Consistency with a specific mutation state
    opts := gocb.QueryOptions{
        ConsistentWith: &mutationState,
    }
  6. Use RangeScan for key-range queries

    master

    A RangeScan allows you to scan a specific range of keys using ScanTerm boundaries.

    ScanTerm

    A ScanTerm defines a boundary in the scan.

    • Term: The string value of the boundary.
    • Exclusive: If true, the boundary value itself is excluded from the scan results.

    Helper Functions

    • ScanTermMinimum(): Returns a ScanTerm with the value "\x00" (the lowest possible value).
    • ScanTermMaximum(): Returns a ScanTerm with the value of utf8.MaxRune (the highest possible value).

    Creating a Prefix Scan

    You can use NewRangeScanForPrefix(prefix string) to quickly create a RangeScan that starts at the given prefix and ends at the prefix plus the maximum possible value.

    // Create a range scan from 'user_' to 'user_z'
    rangeScan := gocb.NewRangeScanForPrefix("user_")
    
    // Or manually define terms
    manualScan := gocb.RangeScan{
        From: &gocb.ScanTerm{Term: "a", Exclusive: false},
        To:   &gocb.ScanTerm{Term: "z", Exclusive: true},
    }
    
    // Execute the scan
    result, err := collection.Scan(rangeScan, nil)
  7. Configure Observability and Semantic Conventions

    master

    The ObservabilityConfig controls how spans and metrics are emitted to the Tracer and Meter.

    By default, the SDK emits legacy semantic conventions for backward compatibility. You can use SemanticConventionOptIn to transition to stable conventions.

    Available ObservabilitySemanticConvention values:

    • ObservabilitySemanticConventionDatabase: Emit only stable database semantic conventions; stop emitting legacy ones.
    • ObservabilitySemanticConventionDatabaseDup: Emit both stable and legacy conventions (useful for phased transitions).
  8. How operation management and retries work

    master

    The client uses an psOpManager (implemented via psOpManagerDefault) to manage the lifecycle of individual operations. This manager handles several critical concerns for every request:

    • Tracing: It creates and manages OpenTelemetry spans to provide observability into request latency and success rates.
    • Retries: It tracks retry attempts and uses a RetryStrategy to determine if an operation should be retried based on the error encountered (e.g., ErrServiceNotAvailable).
    • Timeouts: It enforces operation-specific timeouts, ensuring requests do not hang indefinitely.
    • Idempotency: It tracks whether an operation is idempotent, which is a key factor in deciding if a retry is safe.
    • Context: It manages the context.Context associated with the operation.

    When an operation is executed, the client uses helper functions like wrapPSOp to wrap the underlying gRPC call with this management logic, automatically handling span creation, timeout enforcement, and retry loops.

  9. Configure streaming behavior with ConfigStreaming

    master

    The ConfigStreaming message controls how the performer streams results back to the driver. The driver maintains a 10-second buffer to handle out-of-order responses and batching flexibility; the performer should not send data older than this buffer.

    Key configuration options include:

    • batch_size: An optional hint for the performer to aim for a specific number of results per BatchedResults batch. The performer may return fewer elements than specified to avoid unnecessary waiting.
    • flow_control: A boolean to enable flow control. When enabled, the performer should only send responses when the GRPC response stream reports itself as ready. This helps the performer manage its own internal queues and metrics if it cannot keep up with the flow rate.
    • enable_metrics: A boolean to determine whether the performer should stream back metrics.
    message ConfigStreaming {
      // If present, the performer should stream back BatchedResults, aiming to contain this number of results.
      optional int32 batch_size = 1;
    
      // Whether the performer should enable flow control.
      bool flow_control = 2;
    
      // Whether the performer should stream back metrics.
      bool enable_metrics = 3;
    }
  10. Access Buckets and Management Managers

    master

    Once connected to a Cluster, you can access various resources and management interfaces:

    • Bucket(bucketName string): Returns a *Bucket instance for data operations on a specific bucket.
    • Users(): Returns a *UserManager for managing cluster users.
    • Buckets(): Returns a *BucketManager for managing buckets.
    • QueryIndexes(): Returns a *QueryIndexManager for managing query indexes.
    • SearchIndexes(): Returns a *SearchIndexManager for managing cluster-level search indexes.
    • AnalyticsIndexes(): Returns an *AnalyticsIndexManager for managing analytics indexes.
    • Transactions(): Returns a *Transactions instance for performing ACID transactions.
    bucket := cluster.Bucket("my-bucket")
    queryManager := cluster.QueryIndexes()
    userManager := cluster.Users()