Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SurrealDB datasource support #1361

Open
wants to merge 41 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
8e41e54
surrealDB implementation
vaidehiadhi Jan 2, 2025
edb4080
added surrealDB support
vaidehiadhi Jan 3, 2025
56ce727
Merge branch 'development' into surrealdb
Umang01-hash Jan 6, 2025
0419cd4
resolved review suggestions
vaidehiadhi Jan 6, 2025
58cd998
Merge branch 'surrealdb' of github.com:vaidehiadhi/gofr into surrealdb
vaidehiadhi Jan 6, 2025
544d83f
Merge branch 'development' into surrealdb
Umang01-hash Jan 7, 2025
ebbc196
changed code to write tests using mocks instead of suits
vaidehiadhi Jan 7, 2025
f1d7257
Merge branch 'surrealdb' of github.com:vaidehiadhi/gofr into surrealdb
vaidehiadhi Jan 7, 2025
52dd1d9
Merge branch 'development' into surrealdb
Umang01-hash Jan 8, 2025
474ad37
changed code according to the review suggestions
vaidehiadhi Jan 8, 2025
eaae9bb
Merge branch 'surrealdb' of github.com:vaidehiadhi/gofr into surrealdb
vaidehiadhi Jan 8, 2025
892e811
resolved linters
vaidehiadhi Jan 8, 2025
dbf2e52
fixed linters
vaidehiadhi Jan 8, 2025
2978005
Merge branch 'development' into surrealdb
Umang01-hash Jan 13, 2025
44318e8
resolved pr conflicts
vaidehiadhi Jan 13, 2025
ee1cadb
Merge branch 'surrealdb' of github.com:vaidehiadhi/gofr into surrealdb
vaidehiadhi Jan 13, 2025
44911ef
fixed documentation
vaidehiadhi Jan 15, 2025
7e4775e
Merge branch 'development' into surrealdb
Umang01-hash Jan 16, 2025
753373f
resolved pr comments
vaidehiadhi Jan 16, 2025
d44e7aa
Merge branch 'surrealdb' of github.com:vaidehiadhi/gofr into surrealdb
vaidehiadhi Jan 16, 2025
e2aac2e
added traces support
vaidehiadhi Jan 16, 2025
bc5032c
resoved pr comments
vaidehiadhi Jan 17, 2025
109325d
add id parameter in update method
vaidehiadhi Jan 17, 2025
67b6350
Merge branch 'development' into surrealdb
Umang01-hash Jan 17, 2025
d141722
resolve pr comments
vaidehiadhi Jan 20, 2025
0e8d7b1
Merge branch 'surrealdb' of github.com:vaidehiadhi/gofr into surrealdb
vaidehiadhi Jan 20, 2025
8f2eb6d
added docker command in contribution
vaidehiadhi Jan 20, 2025
f577c5c
fixed merge conflict
vaidehiadhi Jan 20, 2025
ee577c9
added docs and mod improvements
vaidehiadhi Jan 21, 2025
61510f5
added missing files
vaidehiadhi Jan 21, 2025
811ff1a
Merge branch 'development' into surrealdb
Umang01-hash Jan 21, 2025
051ff35
docker command
vaidehiadhi Jan 21, 2025
78eb773
Merge branch 'surrealdb' of github.com:vaidehiadhi/gofr into surrealdb
vaidehiadhi Jan 21, 2025
7e99bcd
docker command
vaidehiadhi Jan 21, 2025
7bdc615
Merge branch 'development' into surrealdb
Umang01-hash Jan 21, 2025
1279fe2
review suggestions
vaidehiadhi Jan 21, 2025
5225086
Merge branch 'surrealdb' of github.com:vaidehiadhi/gofr into surrealdb
vaidehiadhi Jan 21, 2025
0e4cb34
review comments and linters
vaidehiadhi Jan 21, 2025
4c20be9
removed metrics
vaidehiadhi Jan 21, 2025
b8ea649
resolved review comments
vaidehiadhi Jan 21, 2025
3e2441f
Merge branch 'development' into surrealdb
Umang01-hash Jan 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ docker run --name kafka-1 -p 9092:9092 \
bitnami/kafka:3.4
docker pull scylladb/scylla
docker run --name scylla -d -p 2025:9042 scylladb/scylla
docker pull surrealdb/surrealdb:latest
docker run --name surrealdb -d -p 8000:8000 surrealdb/surrealdb:latest start --bind 0.0.0.0:8000



Expand Down
123 changes: 123 additions & 0 deletions docs/advanced-guide/injecting-databases-drivers/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -828,3 +828,126 @@ func getUser(c *gofr.Context) (any, error) {
return user, nil
}
```
## SurrealDB

GoFr supports injecting SurrealDB database that supports the following interface. Any driver that implements the interface can be added
using `app.AddSurrealDB()` method, and user's can use Surreal DB across application with `gofr.Context`.

```go
// SurrealDB defines an interface representing a SurrealDB client with common database operations.
type SurrealDB interface {
// Query executes a Surreal query with the provided variables and returns the query results as a slice of interfaces.
// It returns an error if the query execution fails.
Query(ctx context.Context, query string, vars map[string]interface{}) ([]interface{}, error)

// Create inserts a new record into the specified table and returns the created record as a map.
// It returns an error if the operation fails.
Create(ctx context.Context, table string, data interface{}) (map[interface{}]interface{}, error)

// Update modifies an existing record in the specified table by its ID with the provided data.
// It returns the updated record as an interface and an error if the operation fails.
Update(ctx context.Context, table string, id string, data interface{}) (interface{}, error)

// Delete removes a record from the specified table by its ID.
// It returns the result of the delete operation as an interface and an error if the operation fails.
Delete(ctx context.Context, table string, id string) (any, error)

// Select retrieves all records from the specified table.
// It returns a slice of maps representing the records and an error if the operation fails.
Select(ctx context.Context, table string) ([]map[string]interface{}, error)
}
```
Import the gofr's external driver for SurrealDB:
vaidehiadhi marked this conversation as resolved.
Show resolved Hide resolved
```shell
go get gofr.dev/pkg/gofr/datasource/surrealdb
```
The following example demonstrates injecting an SurrealDB instance into a GoFr application.

```go
package main

import (
"fmt"
"gofr.dev/pkg/gofr"
"gofr.dev/pkg/gofr/datasource/surrealdb"
)

type Person struct {
ID string `json:"id,omitempty"`
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email,omitempty"`
}

type ErrorResponse struct {
Message string `json:"message"`
}

func main() {
app := gofr.New()

client := surrealdb.New(&surrealdb.Config{
Host: "localhost",
Port: 8000,
Username: "root",
Password: "root",
Namespace: "test_namespace",
Database: "test_database",
TLSEnabled: false,
})

app.AddSurrealDB(client)

// GET request to fetch person by ID
app.GET("/person/{id}", func(ctx *gofr.Context) (interface{}, error) {
id := ctx.PathParam("id")

query := "SELECT * FROM type::thing('person', $id)"
vars := map[string]interface{}{
"id": id,
}

result, err := ctx.SurrealDB.Query(ctx, query, vars)
if err != nil {
ctx.Logger.Error("Query error: ", err)
return nil, err
}

if len(result) > 0 {
return result[0], nil
}

return nil, fmt.Errorf("person not found")
})

// POST request to create a new person
app.POST("/person", func(ctx *gofr.Context) (interface{}, error) {
var person Person
if err := ctx.Bind(&person); err != nil {
ctx.Logger.Error("Binding error: ", err)
return ErrorResponse{Message: "Invalid request body"}, nil
}

result, err := ctx.SurrealDB.Create(ctx, "person", map[string]interface{}{
"name": person.Name,
"age": person.Age,
"email": person.Email,
})

if err != nil {
ctx.Logger.Errorf("Creation error: %v", err)
return ErrorResponse{Message: "Creation failed"}, nil
}

if id, ok := result["id"]; ok {
person.ID = fmt.Sprintf("%v", id)
return person, nil
}

return ErrorResponse{Message: "Unexpected result format"}, nil
})

app.Run()
}

```
1 change: 1 addition & 0 deletions pkg/gofr/container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type Container struct {
DGraph Dgraph
OpenTSDB OpenTSDB
ScyllaDB ScyllaDB
SurrealDB SurrealDB

KVStore KVStore

Expand Down
34 changes: 34 additions & 0 deletions pkg/gofr/container/datasources.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,40 @@ type MongoProvider interface {
provider
}

// SurrealDB defines an interface representing a SurrealDB client with common database operations.
type SurrealDB interface {
vaidehiadhi marked this conversation as resolved.
Show resolved Hide resolved

// Query executes a Surreal query with the provided variables and returns the query results as a slice of interfaces.
// It returns an error if the query execution fails.
Query(ctx context.Context, query string, vars map[string]any) ([]any, error)

// Create inserts a new record into the specified table and returns the created record as a map.
// It returns an error if the operation fails.
Create(ctx context.Context, table string, data any) (map[string]any, error)

// Update modifies an existing record in the specified table by its ID with the provided data.
// It returns the updated record as an interface and an error if the operation fails.
Update(ctx context.Context, table string, id string, data any) (any, error)

// Delete removes a record from the specified table by its ID.
// It returns the result of the delete operation as an interface and an error if the operation fails.
Delete(ctx context.Context, table string, id string) (any, error)

// Select retrieves all records from the specified table.
// It returns a slice of maps representing the records and an error if the operation fails.
Select(ctx context.Context, table string) ([]map[string]any, error)

HealthChecker
}

// SurrealBDProvider is an interface that extends SurrealDB with additional methods for logging, metrics, or connection management.
// It is typically used for initializing and managing SurrealDB-based data sources.
type SurrealBDProvider interface {
SurrealDB

provider
}

type provider interface {
// UseLogger sets the logger for the Cassandra client.
UseLogger(logger any)
Expand Down
21 changes: 11 additions & 10 deletions pkg/gofr/datasource/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,18 @@ Therefore, GoFr utilizes a pluggable approach for new datasources by separating

| Datasource | Health-Check | Logs | Metrics | Traces | As Driver |
|------------------|:------------:|:----:|:-------:|:------:|:---------:|
| MySQL | ✅ | ✅ | ✅ | | |
| REDIS | ✅ | ✅ | ✅ | | |
| PostgreSQL | ✅ | ✅ | ✅ | | |
| MongoDB | ✅ | ✅ | ✅ | | ✅ |
| SQLite | ✅ | ✅ | ✅ | | |
| BadgerDB | ✅ | ✅ | ✅ | | ✅ |
| Cassandra | ✅ | ✅ | ✅ | | ✅ |
| MySQL | ✅ | ✅ | ✅ | | |
| REDIS | ✅ | ✅ | ✅ | | |
| PostgreSQL | ✅ | ✅ | ✅ | | |
| MongoDB | ✅ | ✅ | ✅ | | ✅ |
| SQLite | ✅ | ✅ | ✅ | | |
| BadgerDB | ✅ | ✅ | ✅ | | ✅ |
| Cassandra | ✅ | ✅ | ✅ | | ✅ |
| ClickHouse | | ✅ | ✅ | ✅ | ✅ |
| FTP | | ✅ | | | ✅ |
| SFTP | | ✅ | | | ✅ |
| FTP | | ✅ | | | ✅ |
| SFTP | | ✅ | | | ✅ |
| Solr | | ✅ | ✅ | ✅ | ✅ |
| DGraph | ✅ | ✅ | ✅ | ✅ | |
| Azure Event Hubs | | ✅ | ✅ | |✅ |
| Azure Event Hubs | | ✅ | ✅ | |✅ |
| OpenTSDB | ✅ | ✅ | | ✅ | ✅ |
| SurrealDB | ✅ | ✅ | | ✅ | ✅ |
23 changes: 23 additions & 0 deletions pkg/gofr/datasource/surrealdb/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module gofr.dev/pkg/gofr/datasource/surrealdb

go 1.22.0

toolchain go1.23.4

require (
github.com/stretchr/testify v1.10.0
github.com/surrealdb/surrealdb.go v0.3.2
go.opentelemetry.io/otel v1.33.0
go.opentelemetry.io/otel/trace v1.33.0
go.uber.org/mock v0.5.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/gofrs/uuid v4.4.0+incompatible // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
35 changes: 35 additions & 0 deletions pkg/gofr/datasource/surrealdb/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/surrealdb/surrealdb.go v0.3.2 h1:ynBbD0onW+M4BXhZ1+dDdVnNcaqBqFlHaHCFnk8LgmQ=
github.com/surrealdb/surrealdb.go v0.3.2/go.mod h1:A0zahuChOaJtvTm2lefQnV+6aJtgqNLm9TIdYhZbw1Q=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw=
go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I=
go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s=
go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck=
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
54 changes: 54 additions & 0 deletions pkg/gofr/datasource/surrealdb/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package surrealdb

import (
"context"
)

// Logger defines methods for logging debug, log, and error messages.
type Logger interface {
// Debugf logs a formatted debug message.
Debugf(pattern string, args ...any)
// Debug logs a debug message
Debug(args ...any)
// Logf logs a formatted log message.
Logf(pattern string, args ...any)
// Errorf logs a formatted error message
Errorf(pattern string, args ...any)
}

// Connection defines methods for interacting with a database connection.
type Connection interface {
// Connect establishes a connection to the database.
Connect() error
// Close terminates the database connection.
Close() error
// Send executes a database operation with the given method and parameters.
Send(res any, method string, params ...any) error
// Use sets the active namespace and database for the connection.
Use(namespace string, database string) error
// Let sets a session variable in the connection.
Let(key string, value any) error
// Unset removes a session variable from the connection.
Unset(key string) error
}

// Metrics provides methods to record and manage application metrics.
type Metrics interface {
// NewCounter creates a new counter metric.
NewCounter(name, desc string)
// NewUpDownCounter creates a new up-down counter metric.
NewUpDownCounter(name, desc string)
// NewHistogram creates a new histogram metric with specified buckets.
NewHistogram(name, desc string, buckets ...float64)
// NewGauge creates a new gauge metric.
NewGauge(name, desc string)

// IncrementCounter increments a counter by 1.
IncrementCounter(ctx context.Context, name string, labels ...string)
// DeltaUpDownCounter updates a delta for an up-down counter.
DeltaUpDownCounter(ctx context.Context, name string, value float64, labels ...string)
// RecordHistogram records a value in a histogram.
RecordHistogram(ctx context.Context, name string, value float64, labels ...string)
// SetGauge sets the value of a gauge.
SetGauge(name string, value float64, labels ...string)
}
Loading
Loading