Skip to content

Commit

Permalink
Adding CBOR request endoing. Adding Http Connection as a connection o…
Browse files Browse the repository at this point in the history
…ption
  • Loading branch information
remade committed Sep 9, 2024
1 parent 8f4a698 commit eba7516
Show file tree
Hide file tree
Showing 22 changed files with 545 additions and 75 deletions.
32 changes: 22 additions & 10 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ package surrealdb

import (
"fmt"

"github.com/surrealdb/surrealdb.go/pkg/model"

"github.com/surrealdb/surrealdb.go/pkg/conn"
"github.com/surrealdb/surrealdb.go/internal/connection"
"github.com/surrealdb/surrealdb.go/pkg/constants"
"github.com/surrealdb/surrealdb.go/pkg/model"
)

// DB is a client for the SurrealDB database that holds the connection.
type DB struct {
conn conn.Connection
conn connection.Connection
liveHandler connection.LiveHandler
}

// Auth is a struct that holds surrealdb auth data for login.
Expand All @@ -24,12 +23,24 @@ type Auth struct {
}

// New creates a new SurrealDB client.
func New(url string, connection conn.Connection) (*DB, error) {
connection, err := connection.Connect(url)
func New(url string, engine string) (*DB, error) {
newParams := connection.NewConnectionParams{
Encoder: model.GetCborEncoder(),
Decoder: model.GetCborDecoder(),
}
var conn connection.Connection
if engine != "http" {
conn = connection.NewHttp(newParams)
} else {
conn = connection.NewWebSocket(newParams)
}

connect, err := conn.Connect(url)
if err != nil {
return nil, err
}
return &DB{connection}, nil

return &DB{conn: connect}, nil
}

// --------------------------------------------------
Expand Down Expand Up @@ -126,8 +137,8 @@ func (db *DB) Insert(what string, data interface{}) (interface{}, error) {
}

// LiveNotifications returns a channel for live query.
func (db *DB) LiveNotifications(liveQueryID string) (chan model.Notification, error) {
return db.conn.LiveNotifications(liveQueryID)
func (db *DB) LiveNotifications(liveQueryID string) (chan connection.Notification, error) {
return db.liveHandler.LiveNotifications(liveQueryID) //check if implemented
}

// --------------------------------------------------
Expand Down Expand Up @@ -155,6 +166,7 @@ func (db *DB) send(method string, params ...interface{}) (interface{}, error) {
// resp is a helper method for parsing the response from a query.
func (db *DB) resp(_ string, _ []interface{}, res interface{}) (interface{}, error) {
if res == nil {
//return nil, pkg.ErrNoRow
return nil, constants.ErrNoRow
}
return res, nil
Expand Down
27 changes: 11 additions & 16 deletions db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"bytes"
"encoding/json"
"fmt"
"github.com/surrealdb/surrealdb.go/pkg/constants"
"github.com/surrealdb/surrealdb.go/pkg/logger"
"io"
rawslog "log/slog"
"os"
Expand All @@ -12,17 +14,10 @@ import (
"time"

"github.com/stretchr/testify/assert"
"github.com/surrealdb/surrealdb.go/pkg/logger/slog"
"github.com/surrealdb/surrealdb.go/pkg/model"

"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"github.com/surrealdb/surrealdb.go"
"github.com/surrealdb/surrealdb.go/pkg/conn/gorilla"
"github.com/surrealdb/surrealdb.go/pkg/constants"

"github.com/surrealdb/surrealdb.go/pkg/conn"
"github.com/surrealdb/surrealdb.go/pkg/logger"
conn "github.com/surrealdb/surrealdb.go/internal/connection"
"github.com/surrealdb/surrealdb.go/pkg/marshal"
)

Expand Down Expand Up @@ -68,13 +63,13 @@ func TestSurrealDBSuite(t *testing.T) {
// Without options
buff := bytes.NewBufferString("")
logData := createLogger(t, buff)
SurrealDBSuite.connImplementations["gorilla"] = gorilla.Create().Logger(logData)
SurrealDBSuite.connImplementations["ws"] = conn.NewWebSocket(conn.NewConnectionParams{}).Logger(logData)
SurrealDBSuite.logBuffer = buff

// With options
buffOpt := bytes.NewBufferString("")
logDataOpt := createLogger(t, buff)
SurrealDBSuite.connImplementations["gorilla_opt"] = gorilla.Create().SetTimeOut(time.Minute).SetCompression(true).Logger(logDataOpt)
SurrealDBSuite.connImplementations["ws_opt"] = conn.NewWebSocket(conn.NewConnectionParams{}).SetTimeOut(time.Minute).SetCompression(true).Logger(logDataOpt)
SurrealDBSuite.logBuffer = buffOpt

RunWsMap(t, SurrealDBSuite)
Expand All @@ -83,7 +78,7 @@ func TestSurrealDBSuite(t *testing.T) {
func createLogger(t *testing.T, writer io.Writer) logger.Logger {
t.Helper()
handler := rawslog.NewJSONHandler(writer, &rawslog.HandlerOptions{Level: rawslog.LevelDebug})
return slog.New(handler)
return logger.New(handler)

This comment has been minimized.

Copy link
@ElecTwix

ElecTwix Sep 15, 2024

Contributor

Why move to logger from slog. Slog is better for DB like systems.
https://go.dev/blog/slog

}

func RunWsMap(t *testing.T, s *SurrealDBTestSuite) {
Expand Down Expand Up @@ -134,7 +129,7 @@ func (s *SurrealDBTestSuite) createTestDB() *surrealdb.DB {
// openConnection opens a new connection to the database
func (s *SurrealDBTestSuite) openConnection(url string, impl conn.Connection) *surrealdb.DB {
require.NotNil(s.T(), impl)
db, err := surrealdb.New(url, impl)
db, err := surrealdb.New(url, "")
s.Require().NoError(err)
return db
}
Expand Down Expand Up @@ -177,7 +172,7 @@ func (s *SurrealDBTestSuite) TestLiveViaMethod() {
})
s.Require().NoError(e)
notification := <-notifications
s.Require().Equal(model.CreateAction, notification.Action)
s.Require().Equal(conn.CreateAction, notification.Action)
s.Require().Equal(live, notification.ID)
}

Expand Down Expand Up @@ -208,7 +203,7 @@ func (s *SurrealDBTestSuite) TestLiveWithOptionsViaMethod() {
s.Require().NoError(e)

notification := <-notifications
s.Require().Equal(model.UpdateAction, notification.Action)
s.Require().Equal(conn.UpdateAction, notification.Action)
s.Require().Equal(live, notification.ID)
}

Expand Down Expand Up @@ -236,7 +231,7 @@ func (s *SurrealDBTestSuite) TestLiveViaQuery() {
})
s.Require().NoError(e)
notification := <-notifications
s.Require().Equal(model.CreateAction, notification.Action)
s.Require().Equal(conn.CreateAction, notification.Action)
s.Require().Equal(liveID, notification.ID)
}

Expand Down Expand Up @@ -781,7 +776,7 @@ func (s *SurrealDBTestSuite) TestConcurrentOperations() {
}

func (s *SurrealDBTestSuite) TestConnectionBreak() {
ws := gorilla.Create()
ws := conn.NewWebSocket(conn.NewConnectionParams{})
var url string
if currentURL == "" {
url = defaultURL
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ require (

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
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/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
Expand All @@ -18,6 +20,8 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=

This comment has been minimized.

Copy link
@ElecTwix

ElecTwix Sep 15, 2024

Contributor

Why do we need this?
Can we just write ourselves?

  1. This dependency use golang 1.17?
  2. is x448 someone in the company if it is not this dependency makes the repo open to Supply chain attack
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
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=
Expand Down
3 changes: 1 addition & 2 deletions internal/benchmark/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"testing"

"github.com/surrealdb/surrealdb.go"
"github.com/surrealdb/surrealdb.go/internal/mock"
"github.com/surrealdb/surrealdb.go/pkg/marshal"
)

Expand All @@ -18,7 +17,7 @@ type testUser struct {
}

func SetupMockDB() (*surrealdb.DB, error) {
return surrealdb.New("", mock.Create())
return surrealdb.New("", "")
}

func BenchmarkCreate(b *testing.B) {
Expand Down
27 changes: 27 additions & 0 deletions internal/connection/connection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package connection

type Connection interface {
Connect(url string) (Connection, error)
Close() error
Send(method string, params []interface{}) (interface{}, error)
}

type LiveHandler interface {
LiveNotifications(id string) (chan Notification, error)
}

type Encoder func(value interface{}) ([]byte, error)

type Decoder func(encoded []byte, value interface{}) error

type BaseConnection struct {
encode Encoder
decode Decoder
baseURL string
}

type NewConnectionParams struct {
Encoder Encoder
Decoder Decoder
BaseURL string
}
113 changes: 113 additions & 0 deletions internal/connection/http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package connection

import (
"bytes"
"fmt"
"github.com/surrealdb/surrealdb.go/internal/rand"
"io/ioutil"
"log"
"net/http"
"time"
)

type Http struct {
BaseConnection

httpClient *http.Client

namespace string
database string
}

func NewHttp(p NewConnectionParams) Connection {
con := Http{
BaseConnection: BaseConnection{
encode: p.Encoder,
decode: p.Decoder,
},
}

if con.httpClient == nil {
con.httpClient = &http.Client{
Timeout: 10 * time.Second, // Set a default timeout to avoid hanging requests
}
}

return &con
}

func (h *Http) Connect(url string) (Connection, error) {
// TODO: EXTRACT BASE url and set
h.baseURL = url

_, err := h.MakeRequest(http.MethodGet, "/health", nil)
if err != nil {
return nil, err
}

return h, nil
}

func (h *Http) Close() error {
return nil
}

func (h *Http) SetTimeout(timeout time.Duration) *Http {
h.httpClient.Timeout = timeout
return h
}

func (h *Http) SetHttpClient(client *http.Client) *Http {
h.httpClient = client
return h
}

func (h *Http) Send(method string, params []interface{}) (interface{}, error) {
if h.baseURL == "" {
return nil, fmt.Errorf("connection host not set")
}

rpcReq := &RPCRequest{
ID: rand.String(RequestIDLength),
Method: method,
Params: params,
}

reqBody, err := h.encode(rpcReq)
if err != nil {
return nil, err
}

httpReq, err := http.NewRequest(method, h.baseURL+"rpc", bytes.NewBuffer(reqBody))
httpReq.Header.Set("Accept", "application/cbor")
httpReq.Header.Set("Content-Type", "application/cbor")

resp, err := h.MakeRequest(http.MethodPost, "/rpc", reqBody)
if err != nil {
return nil, err
}

var rpcResponse RPCResponse
err = h.decode(resp, &rpcResponse)

return &rpcResponse, nil
}

func (h *Http) MakeRequest(method string, url string, body []byte) ([]byte, error) {
req, err := http.NewRequest(method, url, bytes.NewBuffer(body))
if err != nil {
log.Fatalf("Error creating request: %v", err)
}

resp, err := h.httpClient.Do(req)
if err != nil {
log.Fatalf("Error making HTTP request: %v", err)
}
defer resp.Body.Close()

if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return nil, fmt.Errorf("request failed with status code %d", resp.StatusCode)
}

return ioutil.ReadAll(resp.Body)
}
Loading

0 comments on commit eba7516

Please sign in to comment.