db_client

package module
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 15, 2026 License: MIT Imports: 12 Imported by: 2

README

Compogo DB Client 💾

Compogo DB Client — это гибкий и расширяемый клиент для работы с базами данных, построенный на принципах плагинной архитектуры. Позволяет подключать различные драйверы (PostgreSQL, MySQL, SQLite и др.) через единый интерфейс, добавлять функциональность через декораторы и полностью интегрируется с жизненным циклом Compogo.

🚀 Установка

go get github.com/Compogo/db-client
📦 Быстрый старт
package main

import (
    "github.com/Compogo/compogo"
    "github.com/Compogo/db-client"
    _ "github.com/Compogo/postgres" // импортируем нужный драйвер
)

func main() {
    app := compogo.NewApp("myapp",
        compogo.WithOsSignalCloser(),
        db_client.Component, // базовый компонент БД
        compogo.WithComponents(
            userRepositoryComponent,
        ),
    )

    if err := app.Serve(); err != nil {
        panic(err)
    }
}

// Компонент, использующий БД
var userRepositoryComponent = &component.Component{
    Dependencies: component.Components{db_client.Component},
    Execute: component.StepFunc(func(c container.Container) error {
        return c.Invoke(func(db db_client.Client) {
            // db готов к работе
            rows, _ := db.Query("SELECT * FROM users")
            defer rows.Close()
            // ...
        })
    }),
}
✨ Возможности
🎯 Плагинная архитектура драйверов

Любой драйвер регистрируется одной строкой и автоматически становится доступным:

// В драйвере postgres
func init() {
    db_client.Registration(Postgres, NewPostgresClient)
}

Выбор драйвера через флаг:

./myapp --db.driver=postgres
🔌 Единый интерфейс Client
type Client interface {
    io.Closer
    Query(string, ...interface{}) (*sql.Rows, error)
    QueryRow(string, ...interface{}) *sql.Row
    Exec(string, ...interface{}) (sql.Result, error)
    QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
    QueryRowContext(context.Context, string, ...interface{}) *sql.Row
    ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
    SQL() *sql.DB
    Driver() Driver
}

Полностью совместим со стандартным database/sql.

🎨 Декораторы (паттерн Decorator)

Добавляйте функциональность, не изменяя основной код:

Логирование запросов
import "github.com/Compogo/db-client/logger"

db = &logger.Logger{Client: db, logger: logger}
// Все запросы теперь логируются на уровне DEBUG
Circuit Breaker (защита от сбоев)
import "github.com/Compogo/db-client/connection"

db = connection.NewLimiter(db, 5, 5*time.Second)
// После 5 ошибок подряд — 5 секунд "тишины"
Пример драйвера (postgres)
var Component = &component.Component{
    Init: component.StepFunc(func(c container.Container) error {
        return container.Provides(
            NewConfig,
            NewClient,
        )
    }),
    // ... другие шаги
}

func init() {
    db_client.Registration(Postgres, NewClientFromContainer)
}
Репозиторий с Circuit Breaker и логгированием
type UserRepository struct {
    db db_client.Client
}

func NewUserRepository(db db_client.Client) *UserRepository {
    // Оборачиваем клиент
    db = &logger.Logger{Client: db, logger: logger}
    db = connection.NewLimiter(db, 3, 10*time.Second)
    
    return &UserRepository{db: db}
}

func (r *UserRepository) GetUser(ctx context.Context, id int) (*User, error) {
    row := r.db.QueryRowContext(ctx, "SELECT id, name FROM users WHERE id = $1", id)
    var user User
    err := row.Scan(&user.ID, &user.Name)
    return &user, err
}
🔧 Создание своего драйвера
const Postgres db_client.Driver = "postgres"

type postgresClient struct {
    db *sql.DB
    // ...
}

func NewPostgresClient(container container.Container) (db_client.Client, error) {
    // достаём конфиг из контейнера
    var config *Config
    if err := container.Invoke(func(cfg *Config) { config = cfg }); err != nil {
        return nil, err
    }
    
    // создаём подключение
    db, err := sql.Open(Postgres.String(), config.DSN)
    if err != nil {
        return nil, err
    }
    
    return &postgresClient{db: db}, nil
}

func init() {
    db_client.Registration(Postgres, NewPostgresClient)
}

Documentation

Index

Constants

View Source
const (
	DriverFieldName = "db.driver"
)

Variables

View Source
var Component = &component.Component{
	Init: component.StepFunc(func(container container.Container) error {
		return container.Provides(
			NewConfig,
			NewClient,
			func(client client.Client) Client { return client },
		)
	}),
	BindFlags: component.BindFlags(func(flagSet flag.FlagSet, container container.Container) error {
		return container.Invoke(func(config *Config) {
			allDrivers := drivers.Keys()
			if len(allDrivers) == 1 {
				DriverDefault = allDrivers[0]
			}

			flagSet.StringVar(&config.driver, DriverFieldName, DriverDefault, fmt.Sprintf("db client driver. Available drivers: [%s]", strings.Join(allDrivers, ",")))
		})
	}),
	Configuration: component.StepFunc(func(container container.Container) error {
		return container.Invoke(Configuration)
	}),
}

Component is a ready-to-use Compogo component that provides a database client. It automatically:

  • Registers Config and client factory in the DI container
  • Adds command-line flags for driver selection
  • Discovers available drivers from the registry
  • Creates the appropriate client based on the selected driver

Usage:

compogo.WithComponents(
    db_client.Component,
    // ... driver components (postgres, mysql, etc.)
)

The actual client instance can be injected into any component that needs it:

type UserService struct {
    db db_client.Client
}
View Source
var (
	DriverDefault = ""
)

Functions

func NewClient

func NewClient(config *Config, container container.Container, logger logger.Logger) (client.Client, error)

NewClient creates a database client instance based on the configured driver. It looks up the Getter for the selected driver, invokes it with the container, and returns the created client. Returns an error if the driver or its getter is not found, or if client creation fails.

func Registration

func Registration(d driver.Driver, getter Getter)

Registration registers a new database driver and its constructor function. This function should be called during driver package initialization. Once registered, the driver becomes available for use via the --db.driver flag.

Types

type Client

type Client client.Client

type Config

type Config struct {
	Driver driver.Driver
	// contains filtered or unexported fields
}

func Configuration

func Configuration(config *Config, configurator configurator.Configurator) (*Config, error)

func NewConfig

func NewConfig() *Config

type Getter

type Getter func(container container.Container) (client.Client, error)

Getter is a function type that creates a new database client instance. It receives the DI container which may contain dependencies like config or logger, and returns a configured Client or an error.

Directories

Path Synopsis
http

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL