perf enhancement

This commit is contained in:
2025-11-16 16:21:35 +05:30
parent 29cddb6389
commit 1d9d9d9308
9 changed files with 917 additions and 35 deletions

57
pgm.go
View File

@@ -25,13 +25,15 @@ var (
ErrConnStringMissing = errors.New("connection string is empty")
)
// Errors
// Common errors returned by pgm operations
var (
ErrInitTX = errors.New("failed to init db.tx")
ErrCommitTX = errors.New("failed to commit db.tx")
ErrNoRows = errors.New("no data found")
)
// Config holds the configuration for initializing the connection pool.
// All fields except ConnString are optional and will use pgx defaults if not set.
type Config struct {
ConnString string
MaxConns int32
@@ -40,7 +42,17 @@ type Config struct {
MaxConnIdleTime time.Duration
}
// InitPool will create new pgxpool.Pool and will keep it for its working
// InitPool initializes the connection pool with the provided configuration.
// It validates the configuration and panics if invalid.
// This function should be called once at application startup.
//
// Example:
//
// pgm.InitPool(pgm.Config{
// ConnString: "postgres://user:pass@localhost/dbname",
// MaxConns: 100,
// MinConns: 5,
// })
func InitPool(conf Config) {
if conf.ConnString == "" {
panic(ErrConnStringMissing)
@@ -88,9 +100,15 @@ func InitPool(conf Config) {
poolPGX.Store(p)
}
// GetPool instance
// GetPool returns the initialized connection pool instance.
// It panics with a descriptive message if InitPool() has not been called.
// This is a fail-fast approach to catch programming errors early.
func GetPool() *pgxpool.Pool {
return poolPGX.Load()
p := poolPGX.Load()
if p == nil {
panic("pgm: connection pool not initialized, call InitPool() first")
}
return p
}
// ClosePool closes the connection pool gracefully.
@@ -102,7 +120,21 @@ func ClosePool() {
}
}
// BeginTx begins a pgx poll transaction
// BeginTx begins a new database transaction from the connection pool.
// Returns an error if the transaction cannot be started.
// Remember to commit or rollback the transaction when done.
//
// Example:
//
// tx, err := pgm.BeginTx(ctx)
// if err != nil {
// return err
// }
// defer tx.Rollback(ctx) // rollback on error
//
// // ... do work ...
//
// return tx.Commit(ctx)
func BeginTx(ctx context.Context) (pgx.Tx, error) {
tx, err := poolPGX.Load().Begin(ctx)
if err != nil {
@@ -113,32 +145,43 @@ func BeginTx(ctx context.Context) (pgx.Tx, error) {
return tx, nil
}
// IsNotFound error check
// IsNotFound checks if an error is a "no rows" error from pgx.
// Returns true if the error indicates no rows were found in a query result.
func IsNotFound(err error) bool {
return errors.Is(err, pgx.ErrNoRows)
}
// PgTime as in UTC
// PgTime converts a Go time.Time to PostgreSQL timestamptz type.
// The time is stored as-is (preserves timezone information).
func PgTime(t time.Time) pgtype.Timestamptz {
return pgtype.Timestamptz{Time: t, Valid: true}
}
// PgTimeNow returns the current time as PostgreSQL timestamptz type.
func PgTimeNow() pgtype.Timestamptz {
return pgtype.Timestamptz{Time: time.Now(), Valid: true}
}
// TsAndQuery converts a text search query to use AND operator between terms.
// Example: "hello world" becomes "hello & world"
func TsAndQuery(q string) string {
return strings.Join(strings.Fields(q), " & ")
}
// TsPrefixAndQuery converts a text search query to use AND operator with prefix matching.
// Example: "hello world" becomes "hello:* & world:*"
func TsPrefixAndQuery(q string) string {
return strings.Join(fieldsWithSufix(q, ":*"), " & ")
}
// TsOrQuery converts a text search query to use OR operator between terms.
// Example: "hello world" becomes "hello | world"
func TsOrQuery(q string) string {
return strings.Join(strings.Fields(q), " | ")
}
// TsPrefixOrQuery converts a text search query to use OR operator with prefix matching.
// Example: "hello world" becomes "hello:* | world:*"
func TsPrefixOrQuery(q string) string {
return strings.Join(fieldsWithSufix(q, ":*"), " | ")
}