-
Notifications
You must be signed in to change notification settings - Fork 182
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
[Database Template] Implement Singleton Pattern #209
[Database Template] Implement Singleton Pattern #209
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@H0llyW00dzZ this is a good idea, but again we'd need the change applied to all database options.
@briancbarrow how about that MongoDB I've been Implement it ? |
@H0llyW00dzZ I peaked at your action results real quick (for both #209 and #206) and github seems to be having issues right now. |
@MitchellBerend it's unstable, look this a weird failure |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
INFO
It seems that GitHub is having issues with actions. I reran manually, and more checks are passing |
this a weird |
The cache posting issue is resolved in #213 since that removes that action from ci, not sure if this issue is related to yesterday's outage but maybe it's safer to wait for that pr to be merged. |
@MitchellBerend The cache posting issue seems to be a race condition because Node.js cannot catch it. Also I don't recommend running CI/CD on Node.js, which is an interpreted language, especially for running lots of CI tasks like this. Unlike compiled languages that can run directly on the machine, such as Go, Node.js adds an extra layer of interpretation. |
By the end of the weekend, linter fix will be merged |
Ye I used their github action without actually looking at the internals but I guess when it's being ran this often node is showing it's limitations. |
Updated workflow will be used on a new commit. I can't run it manually. |
@Ujstor, @briancbarrow this singleton pattern supports Fiber storage as well and provides perfect scalability for rate limiting. For example: package database
import (
"context"
"database/sql"
"fmt"
"log"
"os"
"time"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/storage/mysql/v2"
_ "github.com/go-sql-driver/mysql"
_ "github.com/joho/godotenv/autoload"
)
type Service interface {
Health() map[string]string
// RateLimiter returns the [fiber.Storage] interface for rate limiting.
RateLimiter() fiber.Storage
}
type service struct {
db *sql.DB
ratelimiter fiber.Storage
}
var (
dbname = os.Getenv("DB_DATABASE")
password = os.Getenv("DB_PASSWORD")
username = os.Getenv("DB_USERNAME")
port = os.Getenv("DB_PORT")
host = os.Getenv("DB_HOST")
dbInstance *service
)
func New() Service {
// Reuse Connection
if dbInstance != nil {
return dbInstance
}
// Opening a driver typically will not attempt to connect to the database.
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", username, password, host, port, dbname))
if err != nil {
// This will not be a connection error, but a DSN parse error or
// another initialization error.
log.Fatal(err)
}
db.SetConnMaxLifetime(0)
db.SetMaxIdleConns(50)
db.SetMaxOpenConns(50)
dbInstance = &service{
db: db,
ratelimiter: mysql.New(mysql.Config{
Db: db,
Reset: false,
GCInterval: 10 * time.Second,
Table: "rate_limiter",
}), // Initialize the rate limiter storage
}
return dbInstance
}
func (s *service) Health() map[string]string {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
err := s.db.PingContext(ctx)
if err != nil {
log.Fatalf(fmt.Sprintf("db down: %v", err))
}
return map[string]string{
"message": "It's healthy",
}
}
// RateLimiter returns the [fiber.Storage] interface for rate limiting.
func (s *service) RateLimiter() fiber.Storage {
return s.ratelimiter
} In the database: And it returns nothing when there are no IPs or custom keys, such as API keys, being blocked: |
- [+] feat(mysql.tmpl): implement singleton pattern for dbInstance in New function
- [+] fix(mysql.tmpl): correct dbInstance assignment syntax Note: This a fix syntax for example it can be used multipe services such as dbInstance = &service{ db: db, authuser: NewServiceAuthUser(db), // Initialize the auth user service }
- [+] feat(mongo.tmpl): implement singleton pattern for MongoDB connection instance
- [+] feat(sqlite.tmpl): implement singleton pattern for database instance creation
a921ae1
to
cc1bdd1
Compare
- [+] feat(redis.tmpl): implement singleton pattern for database instance creation Note: This method same as MongoDB must use `sync.Once`
- [+] feat(postgres.tmpl): implement singleton pattern for database instance
- [+] style(mysql.tmpl): improve readability by formatting dbInstance assignment
- [+] style(sqlite.tmpl): improve readability by formatting dbInstance assignment
@briancbarrow all done, also it supported this #209 (comment) |
@briancbarrow by the way, for |
Okay. Will you remove that code from the Redis and Mongo files? |
@briancbarrow done |
Also, note that the singleton pattern is more stable and better suited for traditional SQL databases (e.g., |
By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.
Problem/Feature
This pull request implements the Singleton pattern for database connections, which is useful for reusing connections efficiently.
Description of Changes:
Note: This a fix syntax for example it can be used multipe services such as
Checklist