SurrealDB Go SDK

repository·main·Indexed 43 days ago

https://github.com/surrealdb/surrealdb.go

The official SurrealDB SDK for Go allows developers to interact with SurrealDB databases, performing queries and data operations directly from Go applications. It includes a type-safe SurrealQL query builder and utility tools such as surrealdump for CBOR format database dumps and surrealrestore for point-in-time and incremental restorations.

Tokens
21.4K
Snippets
72
Records
98
Agent score
55%

What's inside SurrealDB Go SDK

  1. Overview of SurrealNote

    main

    SurrealNote is a backend-only demonstration project designed to showcase zero-downtime database migration patterns. Specifically, it demonstrates migrating from PostgreSQL to SurrealDB using the Command Query Responsibility Segregation (CQRS) pattern within a hierarchical note-taking application context.

    Note: This is a REST API demonstration with no UI and is intended for educational/demonstration purposes regarding migration patterns, not for production use.

  2. Understand the default CBOR implementation change

    main

    Starting in v1.0 (introduced in v0.11.0), the default CBOR implementation changed from fxamacker/cbor to surrealcbor.

    surrealcbor is optimized for the SurrealDB protocol and provides:

    • Proper handling of the SurrealDB NONE tag (unmarshals to Go nil).
    • Native support for SurrealDB types like UUIDs, Record IDs, and Geometry.
    • Robust handling of custom datetime and duration formats.

    Critical Behavioral Change: When selecting a non-existent record, the implementations differ:

    • Legacy (fxamacker/cbor): Returns a struct with nil fields (e.g., user.ID == nil).
    • New Default (surrealcbor): Returns nil for the entire struct (e.g., user == nil).

    You must update your error handling logic to check for the nullability of the entire struct rather than individual fields when a record is not found.

    // Updated code for surrealcbor default:
    user, err := surrealdb.Select[User](ctx, db, recordID)
    if err != nil {
        return err
    }
    if user == nil {
        // Handle non-existent record
    }
  3. How surrealdump ensures data consistency

    main

    Because SurrealDB does not expose transaction versionstamps directly to clients and backend isolation models vary, a standard full dump taken during active transactions may be internally inconsistent (containing some records from the start of the dump and others from the end).

    surrealdump solves this by combining an inconsistent full dump with change feed data. It captures the complete change history from before the dump started (vs_0) through the end of the dump (vs_2). During restoration, it applies the inconsistent dump and then replays all changes from the change feed to bring the database to a consistent state at the EndVersionstamp (vs_2).

  4. How data types are mapped between SurrealDB and Go

    main

    The surrealdb package uses the Concise Binary Object Representation (CBOR) format for communication with the backend. While most SurrealDB types map to idiomatic Go types (like string, bool, or time.Time), the library provides custom types for specific SurrealDB models that cannot be represented by standard Go types (such as Record IDs, Table names, or Geometry types).

    When working with the SDK, use the provided surrealdb types to ensure correct serialization and deserialization of complex data structures.

  5. Configure Change Feeds for Incremental Dumps

    main

    To use incremental dumps, you must enable Change Feeds on your SurrealDB database before any data is created. This is done using the DEFINE DATABASE command with a CHANGEFEED retention period. Without this, incremental dumps will not capture changes and full dumps may be inconsistent.

    DEFINE DATABASE OVERWRITE <database_name> CHANGEFEED <retention_period>
    
    -- Example: 1 hour retention
    DEFINE DATABASE OVERWRITE mydb CHANGEFEED 1h
  6. Understand Scopes and ScopeSets

    main

    Scopes are used to control access and visibility. A memory.ScopeSets is a [][]string representing a DNF (OR-of-ANDs) selector.

    • Outer slice: Represents an OR relationship between clauses.
    • Inner slice: Represents an AND relationship between paths within a clause.
    • Path format: Hierarchical paths in canonical slash form (e.g., "team/eng" or "org/apple/product/ipad").
    • Key/Value format: Written as two segments: "key/value".

    Examples:

    • memory.ScopeSets{{"team/acme"}}: A single scope.
    • memory.ScopeSets{{"team/a"}, {"team/b"}}: team/a OR team/b.
    • memory.ScopeSets{{"team/b", "clearance/secret"}}: team/b AND clearance/secret.

    Note: Labels (in Labels fields) use key=value format, whereas scope paths use the slash / format.

    client.Remember(ctx, &memory.RememberRequest{
        Text:   "...",
        Scopes: memory.ScopeSets{{"team/acme"}},
    })
    
    client.Documents().Upload(ctx, body,
        memory.WithScopes(memory.ScopeSets{{"team/acme", "user/tobie"}}),
    )
  7. Manage dump chains and point-in-time recovery

    main

    The surrealdump system uses a chain-building mechanism to manage relationships between full and incremental dumps. This allows for reliable point-in-time recovery by scanning a directory and constructing a valid sequence of files.

    Key Chain Operations

    • ValidateChain: Ensures incremental dumps connect without gaps in versionstamps.
    • CanApplyIncremental: Verifies if an incremental dump is compatible with the current database state.
    • BuildChains: Automatically discovers and constructs valid chains from a directory.
    • ScanDirectory: Locates all dumps and their corresponding .manifest.json files.
    • GetManifestsForVersionstamp: Identifies the specific set of dumps required to restore the database to a target versionstamp.

    Safety Guards

    To prevent data corruption, the system enforces:

    • Gap Prevention: Rejects incremental dumps if there is a versionstamp gap (e.g., trying to apply a dump starting at 300 to a database at 200).
    • Wrong Start Detection: Validates that the incremental dump's expected start versionstamp matches the current database state.
    • Namespace/Database Consistency: Prevents mixing dumps from different namespaces or databases.
    • Order Enforcement: Ensures full dumps are applied first, followed by incremental dumps in strict versionstamp order.
    • Integrity Verification: Uses SHA256 hashes to ensure dump files are not corrupted.
  8. How to start a new backup chain after restoration

    main

    You cannot continue an existing dump chain after a restoration because restored databases have different versionstamps than the original. To start a new backup chain from a restored database, follow these steps:

    1. Re-enable Change Feeds: Change feeds are not preserved during restoration. You must manually re-enable them on the restored database.
      DEFINE DATABASE OVERWRITE <database_name> CHANGEFEED <retention_period>
    2. Take a new full dump: Establish a new baseline using surrealdump.
      surrealdump -endpoint ws://localhost:8001 -namespace restored -database prod -output new-full.cbor
    3. Continue with incremental dumps: Use the new full dump as the base for subsequent incremental backups.
      surrealdump -incremental -endpoint ws://localhost:8001 -namespace restored -database prod -output new-inc.cbor
  9. How to restart an incremental backup chain after restoration

    main

    Versionstamps are unique to each database instance. When you restore a database, the new instance will have different versionstamps than the original. Consequently, you cannot continue an old incremental chain on a restored database.

    To start a new incremental backup chain on a restored database:

    1. Take a new full dump of the restored database.
    2. Use this new full dump as the base for all future incremental dumps.
    # 1. Take a new full dump of the restored database
    surrealdump -endpoint ws://localhost:8001 -namespace myapp -database prod -dir backups_new -output restored-full.cbor
    
    # 2. Now you can take incremental dumps based on the restored database
    surrealdump -incremental -endpoint ws://localhost:8001 -namespace myapp -database prod -dir backups_new -output restored-inc1.cbor
  10. Migrating from `spectron` to `memory`

    main

    As of v1.7.0, the spectron package has been renamed to memory. There is no compatibility shim, so you must update your import paths and package qualifiers. All exported names remain unchanged.

    Migration steps:

    1. Replace github.com/surrealdb/surrealdb.go/spectron with github.com/surrealdb/surrealdb.go/memory in your imports.
    2. Update calls from spectron.New(...) to memory.New(...).

    If you cannot migrate immediately, pin your dependency to v1.6.0 to continue using the spectron path.

    -import "github.com/surrealdb/surrealdb.go/spectron"
    +import "github.com/surrealdb/surrealdb.go/memory"
    
    -client, err := spectron.New(ctx, endpoint, key)
    +client, err := memory.New(ctx, endpoint, key)