From 7e251bccaa7771bb295df3c54a775017dacd350d Mon Sep 17 00:00:00 2001 From: slaventius Date: Wed, 1 Mar 2023 08:46:28 +0300 Subject: [PATCH] * --- internal/transport/arango/client.go | 31 ++++++ internal/transport/arango/collection.go | 123 ++++++++++++++++++++++++ internal/transport/arango/connection.go | 33 +++++++ internal/transport/arango/db.go | 77 +++++++++++++++ 4 files changed, 264 insertions(+) create mode 100644 internal/transport/arango/client.go create mode 100644 internal/transport/arango/collection.go create mode 100644 internal/transport/arango/connection.go create mode 100644 internal/transport/arango/db.go diff --git a/internal/transport/arango/client.go b/internal/transport/arango/client.go new file mode 100644 index 0000000..14c0969 --- /dev/null +++ b/internal/transport/arango/client.go @@ -0,0 +1,31 @@ +package arango_db + +import ( + "context" + "log" + + driver "github.com/arangodb/go-driver" +) + +type Client struct { + ctx context.Context + conn *Connection + driver.Client +} + +func NewClient(ctx context.Context, conn *Connection, user string, password string) *Client { + client, err := driver.NewClient(driver.ClientConfig{ + Connection: conn.conn, + Authentication: driver.BasicAuthentication(user, password), + }) + + if err != nil { + log.Fatal(err) + } + + return &Client{ + ctx: ctx, + conn: conn, + Client: client, + } +} diff --git a/internal/transport/arango/collection.go b/internal/transport/arango/collection.go new file mode 100644 index 0000000..cebc136 --- /dev/null +++ b/internal/transport/arango/collection.go @@ -0,0 +1,123 @@ +package arango_db + +import ( + "context" + "fmt" + + driver "github.com/arangodb/go-driver" +) + +type Collection struct { + db driver.Database + driver.Collection + ctx context.Context +} + +// Добавление коллекции +func NewCollection(ctx context.Context, db driver.Database, name string) (*Collection, error) { + collExists, errExists := db.CollectionExists(ctx, name) + if errExists != nil { + return nil, fmt.Errorf("AddCollection: Error checking the existence of the collection: %v", errExists) + } + + // Предварительно проверим существование коллекции с таким же наименованием + if collExists { + col, err := db.Collection(ctx, name) + if err != nil { + return nil, fmt.Errorf("AddCollection: failed to open existing collection %v: %v", name, err) + } + + return &Collection{ + db, + col, + ctx, + }, nil + } + + // Создадим коллекцию + col, err := db.CreateCollection(ctx, name, nil) + if err != nil { + return nil, fmt.Errorf("AddCollection: failed to create collection %v: %v", name, err) + } + + return &Collection{ + db, + col, + ctx, + }, nil +} + +// Добавление данных коллекции +func (col *Collection) AddData(data interface{}) error { + _, errs, err := col.CreateDocuments(col.ctx, data) + if err != nil { + return fmt.Errorf("AddData: %v", err) + } else if err := errs.FirstNonNil(); err != nil { + return fmt.Errorf("AddData: first error: %v", err) + } + + return nil +} + +// Получение элементов коллекции +func (col *Collection) GetData(query string) (func() (interface{}, error), error) { + cursor, err := col.db.Query(col.ctx, query, nil) + if err != nil { + return nil, fmt.Errorf("GetData: query '%v' failed: %v", query, err) + } + + return func() (interface{}, error) { + var doc interface{} + + /*metadata*/ + _, errRead := cursor.ReadDocument(col.ctx, &doc) + if driver.IsNoMoreDocuments(errRead) { + cursor.Close() + + return nil, fmt.Errorf("empty") + } else if errRead != nil { + return nil, fmt.Errorf("GetData: read document %v error %v", query, errRead) + } + + return doc, nil + }, nil +} + +// Изменение коллекции +func (col *Collection) UpdateData(query string, patch interface{}) error { + cursor, err := col.db.Query(col.ctx, query, nil) + if err != nil { + return fmt.Errorf("GetData: query '%v' failed: %v", query, err) + } + + var doc map[string]interface{} + + /*metadata*/ + _, errRead := cursor.ReadDocument(col.ctx, &doc) + if driver.IsNoMoreDocuments(errRead) { + cursor.Close() + return fmt.Errorf("empty") + } else if errRead != nil { + return fmt.Errorf("UpdateData: read document %v error %v", query, errRead) + } + + // + k, ok := doc["_key"] + if !ok { + return fmt.Errorf("UpdateData: key not found in %v", doc) + } + + // + _, errUpdate := col.UpdateDocument(col.ctx, k.(string), patch) + if errUpdate != nil { + return fmt.Errorf("UpdateData: update error %v", errUpdate) + } + + return nil +} + +/* +patch := map[string]interface{}{ + "name": "Frank", +} +*/ diff --git a/internal/transport/arango/connection.go b/internal/transport/arango/connection.go new file mode 100644 index 0000000..17712f9 --- /dev/null +++ b/internal/transport/arango/connection.go @@ -0,0 +1,33 @@ +package arango_db + +import ( + "context" + "log" + "net" + "strconv" + + driver "github.com/arangodb/go-driver" + "github.com/arangodb/go-driver/http" +) + +type Connection struct { + conn driver.Connection + ctx context.Context +} + +func NewConnection(ctx context.Context, host string, port int) *Connection { + connString := "http://" + net.JoinHostPort(host, strconv.Itoa(port)) + conn, err := http.NewConnection(http.ConnectionConfig{ + Endpoints: []string{connString}, + }) + + // + if err != nil { + log.Fatal(err) + } + + return &Connection{ + ctx: ctx, + conn: conn, + } +} diff --git a/internal/transport/arango/db.go b/internal/transport/arango/db.go new file mode 100644 index 0000000..09577a4 --- /dev/null +++ b/internal/transport/arango/db.go @@ -0,0 +1,77 @@ +package arango_db + +import ( + "context" + "log" + + driver "github.com/arangodb/go-driver" + "github.com/pkg/errors" +) + +type DataBase struct { + DB driver.Database + ctx context.Context + collections map[string]*Collection +} + +func NewDataBase(ctx context.Context, client *Client, db_name string) *DataBase { + // Проверим существование базы данных + exists, ere := client.DatabaseExists(ctx, db_name) + if ere != nil { + log.Fatal(ere) + } else if exists { + db, eru := client.Database(ctx, db_name) + if eru != nil { + log.Fatal(eru) + } + + // + return &DataBase{ + DB: db, + ctx: ctx, + collections: make(map[string]*Collection), + } + } + + // + db, eru := client.CreateDatabase(ctx, db_name, nil) + if eru != nil { + log.Fatal(eru) + } + + // + return &DataBase{ + DB: db, + ctx: ctx, + collections: make(map[string]*Collection), + } +} + +// Получение коллекции +func (db *DataBase) GetCollection(name string) (*Collection, error) { + col, ok := db.collections[name] + if ok { + return col, nil + } + + return nil, errors.Errorf("Collection %v not exists", name) +} + +// Добавление коллекции +func (db *DataBase) AddCollection(name string) (*Collection, error) { + col, ok := db.collections[name] + if ok { + return col, nil + } + + // + col, err := NewCollection(db.ctx, db.DB, name) + if err != nil { + return nil, err + } + + // Зарегистрируем + db.collections[name] = col + + return col, nil +}