-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WIP: Added interfaces for databases and implemented logger using slog
- Loading branch information
1 parent
f83c124
commit 5f4fffc
Showing
40 changed files
with
1,236 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,59 @@ | ||
# utilities | ||
|
||
This repository contains common libraries for my projects. | ||
|
||
This repository provides the following packages: | ||
|
||
- [Logger](#logger) | ||
- [Database](#database) | ||
- [Network](#network) | ||
- [Security](#security) | ||
|
||
## Logger | ||
|
||
``` | ||
type Logger interface { | ||
Info(string, ...interface{}) | ||
Warn(string, ...interface{}) | ||
Error(error, ...interface{}) | ||
Fatal(error, ...interface{}) | ||
Debug(string, ...interface{}) | ||
With(key string, args ...interface{}) | ||
} | ||
``` | ||
|
||
## Database | ||
|
||
``` | ||
type Database interface { | ||
Operations | ||
Transactions | ||
Closer | ||
Configure | ||
} | ||
type Operations interface { | ||
Create(context.Context, ...interface{}) (models.Response, error) | ||
Query(context.Context, ...interface{}) (models.Response, error) | ||
Update(context.Context, ...interface{}) (models.Response, error) | ||
Delete(context.Context, ...interface{}) (models.Response, error) | ||
} | ||
type Transactions interface { | ||
Begin(context.Context, ...interface{}) (models.Response, error) | ||
Execute(context.Context, ...interface{}) (models.Response, error) | ||
Rollback(context.Context, ...interface{}) (models.Response, error) | ||
} | ||
type Closer interface { | ||
Close() error | ||
} | ||
type Configure interface { | ||
Configure(context.Context, ...interface{}) error | ||
} | ||
``` | ||
|
||
## Network | ||
|
||
## Security |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# TODO | ||
|
||
- Database | ||
|
||
- Replace placeholder code of Database interface implementation with actual implementation | ||
- Integration tests | ||
|
||
- Logger | ||
|
||
- File logging | ||
- Log rotation | ||
- Log forwarding | ||
- Tinted logs | ||
- Integration tests | ||
|
||
- Network | ||
|
||
- Add correct segregation of Protocols, REST and RPCs | ||
- Add interfaces | ||
|
||
- Security | ||
|
||
- Add correct segregation of Basic and Bearer authentication, JWT, SAML, Cookie and Session based authentication, API keys | ||
and OAuth | ||
- Add interfaces |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package constants | ||
|
||
type Type string | ||
|
||
type Database Type | ||
|
||
const ( | ||
MONGODB Database = "mongodb" | ||
REDIS Database = "redis" | ||
MYSQLDB Database = "mysql" | ||
) | ||
|
||
type RDBMS Database | ||
|
||
type Driver RDBMS | ||
|
||
const ( | ||
MYSQL Driver = "mysql" | ||
POSTGRES Driver = "postgres" | ||
SQLITE Driver = "sqlite" | ||
VITESS Driver = "vitess" | ||
COCKROACHDB Driver = "cockroachdb" | ||
) | ||
|
||
type ORM RDBMS | ||
|
||
const ( | ||
GORM ORM = "gorm" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package constants | ||
|
||
import "errors" | ||
|
||
type Error Type | ||
|
||
func (t Error) Error() *error { | ||
err := errors.New(*t.String()) | ||
return &err | ||
} | ||
|
||
func (t Error) String() *string { | ||
str := string(t) | ||
return &str | ||
} | ||
|
||
type ErrorFormat Error | ||
|
||
var ( | ||
CANNOTBEEMTPY ErrorFormat = "%v cannot be empty" | ||
UNSUPPORTED ErrorFormat = "unsupported %v type" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package database | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/shashank-priyadarshi/utilities/database/constants" | ||
adapters "github.com/shashank-priyadarshi/utilities/database/internal" | ||
"github.com/shashank-priyadarshi/utilities/database/models" | ||
"github.com/shashank-priyadarshi/utilities/database/ports" | ||
"github.com/shashank-priyadarshi/utilities/logger" | ||
loggerPort "github.com/shashank-priyadarshi/utilities/logger/ports" | ||
) | ||
|
||
func NewDatabase(ctx context.Context, log loggerPort.Logger, config models.Config) (database ports.Database, err error) { | ||
|
||
if !isSupported(config.Type) { | ||
err = fmt.Errorf("unsupported database type: %s", config.Type) | ||
return | ||
} | ||
|
||
if log == nil { | ||
err = fmt.Errorf("uninitialized logger, initializing module logger") | ||
log.Warn("%v", err) | ||
|
||
log, err = logger.NewLogger() | ||
log.With("module", "database") | ||
|
||
if err != nil { | ||
err = fmt.Errorf("error initializing new logger: %v", err) | ||
return | ||
} | ||
} | ||
|
||
return adapters.NewDatabaseAdapter(ctx, log, &config) | ||
} | ||
|
||
func isSupported(db constants.Database) bool { | ||
|
||
var supported = make(map[constants.Database]any) | ||
supported[constants.MYSQLDB] = nil | ||
supported[constants.MONGODB] = nil | ||
supported[constants.REDIS] = nil | ||
|
||
if _, ok := supported[db]; !ok { | ||
return false | ||
} | ||
|
||
return true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package adapters | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/shashank-priyadarshi/utilities/database/constants" | ||
"github.com/shashank-priyadarshi/utilities/database/internal/connections" | ||
"github.com/shashank-priyadarshi/utilities/database/internal/mongodb" | ||
"github.com/shashank-priyadarshi/utilities/database/internal/rdbms" | ||
"github.com/shashank-priyadarshi/utilities/database/internal/redis" | ||
"github.com/shashank-priyadarshi/utilities/database/models" | ||
"github.com/shashank-priyadarshi/utilities/database/ports" | ||
ports2 "github.com/shashank-priyadarshi/utilities/logger/ports" | ||
) | ||
|
||
func NewDatabaseAdapter(ctx context.Context, log ports2.Logger, config *models.Config) (handle ports.Database, err error) { | ||
|
||
switch config.Type { | ||
case constants.MONGODB: | ||
client, err := connections.NewMongoDBClient(ctx, log, config) | ||
if err != nil { | ||
return nil, fmt.Errorf("error connecting to mongo db: %w", err) | ||
} | ||
|
||
handle = mongodb.NewMongoDBHandle(log, client) | ||
|
||
case constants.MYSQLDB: | ||
client, err := connections.NewRDBMSClient(ctx, log, config) | ||
if err != nil { | ||
return nil, fmt.Errorf("error connecting to rdbms: %w", err) | ||
} | ||
|
||
handle, err = rdbms.NewRelationalDBHandle(log, config.Options.WithORM, config.Options.ORM, client) | ||
if err != nil { | ||
return nil, fmt.Errorf("error creating relational db handle: %w", err) | ||
} | ||
|
||
case constants.REDIS: | ||
client, err := connections.NewRedisClient(ctx, log, config) | ||
if err != nil { | ||
return nil, fmt.Errorf("error connecting to redis: %w", err) | ||
} | ||
|
||
handle = redis.NewRedisHandle(log, client) | ||
|
||
default: | ||
return nil, fmt.Errorf("database type %s is not supported", config.Type) | ||
|
||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package connections | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/shashank-priyadarshi/utilities/database/models" | ||
"github.com/shashank-priyadarshi/utilities/logger/ports" | ||
"go.mongodb.org/mongo-driver/mongo" | ||
"go.mongodb.org/mongo-driver/mongo/options" | ||
_ "go.mongodb.org/mongo-driver/mongo/options" | ||
) | ||
|
||
var opts *options.ClientOptions | ||
|
||
func NewMongoDBClient(ctx context.Context, log ports.Logger, config *models.Config) (client *mongo.Client, err error) { | ||
|
||
if len(config.Options.URI) == 0 { | ||
err = fmt.Errorf("mongo db uri cannot be empty") | ||
log.Error(err) | ||
return | ||
} | ||
|
||
opts.ApplyURI(config.Options.URI) | ||
|
||
// Backoff connection logic | ||
if client, err = mongo.Connect(ctx, opts); err != nil { | ||
err = fmt.Errorf("error connecting to database: %v", err) | ||
log.Error(err) | ||
return | ||
} | ||
|
||
if err = client.Ping(ctx, nil); err != nil { | ||
err = fmt.Errorf("error pinging mongo db on established connection: %v", err) | ||
log.Error(err) | ||
// Backoff disconnection logic | ||
client.Disconnect(ctx) | ||
return | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package connections | ||
|
||
import ( | ||
"context" | ||
"database/sql" | ||
"fmt" | ||
"github.com/glebarez/sqlite" | ||
"github.com/shashank-priyadarshi/utilities/database/constants" | ||
"github.com/shashank-priyadarshi/utilities/database/models" | ||
"github.com/shashank-priyadarshi/utilities/logger/ports" | ||
"gorm.io/driver/mysql" | ||
"gorm.io/driver/postgres" | ||
"gorm.io/gorm" | ||
) | ||
|
||
func NewRDBMSClient(ctx context.Context, log ports.Logger, config *models.Config) (client interface{}, err error) { | ||
|
||
if !isSupported(config.Options.Driver) { | ||
err = fmt.Errorf("unsupported sql driver") | ||
log.Error(err) | ||
return | ||
} | ||
|
||
conn, err := sql.Open(string(config.Options.Driver), "") | ||
if err != nil { | ||
err = fmt.Errorf("error connecting to database: %v", err) | ||
log.Error(err) | ||
return | ||
} | ||
|
||
client = conn | ||
|
||
switch config.Options.WithORM { | ||
case true: | ||
switch config.Options.ORM { | ||
case constants.GORM: | ||
if gormDB, err := createGORMConnection(config.Options.Driver, conn); err != nil { | ||
err = fmt.Errorf("error creating gorm connection: %v", err) | ||
return | ||
} else { | ||
client = gormDB | ||
} | ||
return | ||
|
||
default: | ||
err = fmt.Errorf("unsupported orm type") | ||
log.Error(err) | ||
return | ||
} | ||
|
||
default: | ||
log.Info("no orm configured") | ||
return | ||
} | ||
} | ||
|
||
func isSupported(driver constants.Driver) bool { | ||
|
||
var supported = make(map[constants.Driver]any) | ||
|
||
supported[constants.VITESS] = nil | ||
supported[constants.COCKROACHDB] = nil | ||
|
||
// GORM supported | ||
supported[constants.MYSQL] = nil | ||
supported[constants.POSTGRES] = nil | ||
supported[constants.SQLITE] = nil | ||
|
||
if _, ok := supported[driver]; !ok { | ||
return false | ||
} | ||
|
||
return true | ||
} | ||
|
||
func createGORMConnection(driver constants.Driver, conn *sql.DB) (db *gorm.DB, err error) { | ||
|
||
switch driver { | ||
case constants.MYSQL: | ||
db, err = gorm.Open(mysql.New(mysql.Config{Conn: conn}), &gorm.Config{}) | ||
return | ||
|
||
case constants.POSTGRES: | ||
db, err = gorm.Open(postgres.New(postgres.Config{ | ||
Conn: conn, | ||
}), &gorm.Config{}) | ||
return | ||
|
||
case constants.SQLITE: | ||
db, err = gorm.Open(sqlite.Open("sqlite.db"), &gorm.Config{}) | ||
return | ||
|
||
default: | ||
err = fmt.Errorf("unsupported gorm connection for the driver type %s", driver) | ||
} | ||
|
||
return | ||
} |
Oops, something went wrong.