From aecf83740774e4dbb299a01d54482994f5f567df Mon Sep 17 00:00:00 2001 From: cedricve Date: Mon, 12 Jan 2026 22:37:21 +0100 Subject: [PATCH] Add insert and disconnect methods to database interface Extended DatabaseInterface with InsertOne, InsertMany, and Disconnect methods. Implemented these methods for MongoClient and MockDatabase. Refactored DatabaseOptions to support validation and updated related code and tests for improved flexibility and functionality. --- pkg/database/database.go | 19 ++++++++++++++++--- pkg/database/mock.go | 15 +++++++++++++++ pkg/database/mongodb.go | 36 ++++++++++++++++++++++++++++++++++++ pkg/database/mongodb_test.go | 8 ++++++-- 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/pkg/database/database.go b/pkg/database/database.go index 5867241..648eeff 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -2,6 +2,7 @@ package database import ( "context" + "fmt" "github.com/go-playground/validator/v10" ) @@ -10,15 +11,22 @@ type DatabaseInterface interface { Ping(context.Context) error Find(ctx context.Context, db string, collection string, filter any, opts ...any) (any, error) FindOne(ctx context.Context, db string, collection string, filter any, opts ...any) (any, error) + Disconnect(ctx context.Context) error + InsertOne(ctx context.Context, db string, collection string, document any, opts ...any) (any, error) + InsertMany(ctx context.Context, db string, collection string, documents []any, opts ...any) (any, error) +} + +type DatabaseOptions interface { + Validate() error } // Database represents a database client instance type Database struct { - Options *MongoOptions + Options DatabaseOptions Client DatabaseInterface } -func New(opts *MongoOptions, client ...DatabaseInterface) (*Database, error) { +func New(opts DatabaseOptions, client ...DatabaseInterface) (*Database, error) { // Validate Database configuration validate := validator.New() err := validate.Struct(opts) @@ -29,7 +37,12 @@ func New(opts *MongoOptions, client ...DatabaseInterface) (*Database, error) { // If no client provided, create default production client var m DatabaseInterface if len(client) == 0 { - m, err = NewMongoClient(opts) + // Type assert to RabbitOptions for creating RabbitMQ client + if mongoOpts, ok := opts.(*MongoOptions); ok { + m, err = NewMongoClient(mongoOpts) + } else { + return nil, fmt.Errorf("unsupported queue options type") + } } else { m, err = client[0], nil } diff --git a/pkg/database/mock.go b/pkg/database/mock.go index 2a5ce11..ee158e8 100644 --- a/pkg/database/mock.go +++ b/pkg/database/mock.go @@ -106,6 +106,11 @@ func (m *MockDatabase) Ping(ctx context.Context) error { return nil } +// Disconnect implements DatabaseInterface +func (m *MockDatabase) Disconnect(ctx context.Context) error { + return nil +} + // Find implements DatabaseInterface func (m *MockDatabase) Find(ctx context.Context, db string, collection string, filter any, opts ...any) (any, error) { m.FindCalls = append(m.FindCalls, FindCall{ @@ -154,6 +159,16 @@ func (m *MockDatabase) FindOne(ctx context.Context, db string, collection string return nil, fmt.Errorf("no document found") } +// InsertOne implements DatabaseInterface +func (m *MockDatabase) InsertOne(ctx context.Context, db string, collection string, document any, opts ...any) (any, error) { + return nil, fmt.Errorf("InsertOne not implemented in MockDatabase") +} + +// InsertMany implements DatabaseInterface +func (m *MockDatabase) InsertMany(ctx context.Context, db string, collection string, documents []any, opts ...any) (any, error) { + return nil, fmt.Errorf("InsertMany not implemented in MockDatabase") +} + // Reset clears all recorded calls func (m *MockDatabase) Reset() { m.PingCalls = []PingCall{} diff --git a/pkg/database/mongodb.go b/pkg/database/mongodb.go index 9129552..ed75e75 100644 --- a/pkg/database/mongodb.go +++ b/pkg/database/mongodb.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + "github.com/go-playground/validator/v10" "go.mongodb.org/mongo-driver/mongo" moptions "go.mongodb.org/mongo-driver/mongo/options" "go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo" @@ -23,6 +24,12 @@ type MongoOptions struct { RetryWrites bool } +// Validate validates the MongoOptions configuration +func (m *MongoOptions) Validate() error { + validate := validator.New() + return validate.Struct(m) +} + // MongoOptionsBuilder provides a fluent interface for building Mongo options type MongoOptionsBuilder struct { options *MongoOptions @@ -173,6 +180,11 @@ func (m *MongoClient) Ping(ctx context.Context) error { return err } +// Disconnect disconnects the MongoDB client +func (m *MongoClient) Disconnect(ctx context.Context) error { + return m.Client.Disconnect(ctx) +} + // Find executes a find query on the specified database and collection func (m *MongoClient) Find(ctx context.Context, db string, collection string, filter any, opts ...any) (any, error) { coll := m.Client.Database(db).Collection(collection) @@ -219,3 +231,27 @@ func (m *MongoClient) FindOne(ctx context.Context, db string, collection string, return result, nil } + +// InsertOne inserts a single document into the specified database and collection +func (m *MongoClient) InsertOne(ctx context.Context, db string, collection string, document any, opts ...any) (any, error) { + coll := m.Client.Database(db).Collection(collection) + + result, err := coll.InsertOne(ctx, document) + if err != nil { + return nil, err + } + + return result.InsertedID, nil +} + +// InsertMany inserts multiple documents into the specified database and collection +func (m *MongoClient) InsertMany(ctx context.Context, db string, collection string, documents []any, opts ...any) (any, error) { + coll := m.Client.Database(db).Collection(collection) + + result, err := coll.InsertMany(ctx, documents) + if err != nil { + return nil, err + } + + return result.InsertedIDs, nil +} diff --git a/pkg/database/mongodb_test.go b/pkg/database/mongodb_test.go index 3efb29c..fb5ee17 100644 --- a/pkg/database/mongodb_test.go +++ b/pkg/database/mongodb_test.go @@ -271,7 +271,9 @@ func TestMongodbLiveIntegration(t *testing.T) { t.Fatalf("failed to create database instance: %v", err) } - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(db.Options.Timeout)*time.Millisecond) + options := db.Options.(*MongoOptions) + + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(options.Timeout)*time.Millisecond) defer cancel() err = db.Client.Ping(ctx) @@ -301,7 +303,9 @@ func TestFindIntegration(t *testing.T) { t.Fatalf("failed to create database instance: %v", err) } - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(db.Options.Timeout)*time.Millisecond) + options := db.Options.(*MongoOptions) + + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(options.Timeout)*time.Millisecond) defer cancel() // Test Find with username filter