init
This commit is contained in:
commit
b15b95781c
108 changed files with 14802 additions and 0 deletions
131
internal/db/store.go
Normal file
131
internal/db/store.go
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type querier interface {
|
||||
ExecContext(context.Context, string, ...any) (sql.Result, error)
|
||||
QueryContext(context.Context, string, ...any) (*sql.Rows, error)
|
||||
QueryRowContext(context.Context, string, ...any) *sql.Row
|
||||
}
|
||||
|
||||
type Store struct {
|
||||
DB *sql.DB
|
||||
Users *UserRepository
|
||||
Projects *ProjectRepository
|
||||
Tags *TagRepository
|
||||
Releases *ReleaseRepository
|
||||
APIKeys *APIKeyRepository
|
||||
Sessions *SessionRepository
|
||||
AuditLogs *AuditLogRepository
|
||||
}
|
||||
|
||||
type TxStore struct {
|
||||
Tx *sql.Tx
|
||||
Users *UserRepository
|
||||
Projects *ProjectRepository
|
||||
Tags *TagRepository
|
||||
Releases *ReleaseRepository
|
||||
APIKeys *APIKeyRepository
|
||||
Sessions *SessionRepository
|
||||
AuditLogs *AuditLogRepository
|
||||
}
|
||||
|
||||
type UserRepository struct {
|
||||
q querier
|
||||
}
|
||||
|
||||
type ProjectRepository struct {
|
||||
q querier
|
||||
}
|
||||
|
||||
type TagRepository struct {
|
||||
q querier
|
||||
}
|
||||
|
||||
type ReleaseRepository struct {
|
||||
q querier
|
||||
}
|
||||
|
||||
type APIKeyRepository struct {
|
||||
q querier
|
||||
}
|
||||
|
||||
type SessionRepository struct {
|
||||
q querier
|
||||
}
|
||||
|
||||
type AuditLogRepository struct {
|
||||
q querier
|
||||
}
|
||||
|
||||
func NewStore(database *sql.DB) *Store {
|
||||
return &Store{
|
||||
DB: database,
|
||||
Users: &UserRepository{q: database},
|
||||
Projects: &ProjectRepository{q: database},
|
||||
Tags: &TagRepository{q: database},
|
||||
Releases: &ReleaseRepository{q: database},
|
||||
APIKeys: &APIKeyRepository{q: database},
|
||||
Sessions: &SessionRepository{q: database},
|
||||
AuditLogs: &AuditLogRepository{q: database},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Store) Close() error {
|
||||
if s == nil || s.DB == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return s.DB.Close()
|
||||
}
|
||||
|
||||
func (s *Store) HealthCheck(ctx context.Context) error {
|
||||
if s == nil || s.DB == nil {
|
||||
return fmt.Errorf("database store is not initialized")
|
||||
}
|
||||
|
||||
return s.DB.PingContext(ctx)
|
||||
}
|
||||
|
||||
func (s *Store) WithTx(ctx context.Context, fn func(*TxStore) error) error {
|
||||
if s == nil || s.DB == nil {
|
||||
return fmt.Errorf("database store is not initialized")
|
||||
}
|
||||
|
||||
tx, err := s.DB.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("begin transaction: %w", err)
|
||||
}
|
||||
|
||||
if err := fn(newTxStore(tx)); err != nil {
|
||||
if rollbackErr := tx.Rollback(); rollbackErr != nil && !errors.Is(rollbackErr, sql.ErrTxDone) {
|
||||
return errors.Join(err, fmt.Errorf("rollback transaction: %w", rollbackErr))
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return fmt.Errorf("commit transaction: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func newTxStore(tx *sql.Tx) *TxStore {
|
||||
return &TxStore{
|
||||
Tx: tx,
|
||||
Users: &UserRepository{q: tx},
|
||||
Projects: &ProjectRepository{q: tx},
|
||||
Tags: &TagRepository{q: tx},
|
||||
Releases: &ReleaseRepository{q: tx},
|
||||
APIKeys: &APIKeyRepository{q: tx},
|
||||
Sessions: &SessionRepository{q: tx},
|
||||
AuditLogs: &AuditLogRepository{q: tx},
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue