dcbot/internal/bundb/monitor.go
Dawid Wysokiński e2be652a60
All checks were successful
continuous-integration/drone/push Build is passing
chore: update modules (#34)
Reviewed-on: #34
2022-10-29 06:13:02 +00:00

138 lines
3.2 KiB
Go

package bundb
import (
"context"
"database/sql"
"errors"
"fmt"
"gitea.dwysokinski.me/twhelp/dcbot/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/dcbot/internal/domain"
"github.com/google/uuid"
"github.com/jackc/pgerrcode"
"github.com/uptrace/bun"
"github.com/uptrace/bun/driver/pgdriver"
)
type Monitor struct {
db *bun.DB
}
func NewMonitor(db *bun.DB) *Monitor {
return &Monitor{db: db}
}
func (m *Monitor) Create(ctx context.Context, params domain.CreateMonitorParams) (domain.Monitor, error) {
groupID, err := uuid.Parse(params.GroupID())
if err != nil {
return domain.Monitor{}, domain.GroupDoesNotExistError{
ID: params.GroupID(),
}
}
monitor := model.Monitor{
GroupID: groupID,
TribeID: params.TribeID(),
}
if _, err = m.db.NewInsert().
Model(&monitor).
Returning("*").
Exec(ctx); err != nil {
return domain.Monitor{}, fmt.Errorf(
"something went wrong while inserting monitor into the db: %w",
mapCreateMonitorError(err, params),
)
}
return monitor.ToDomain(), nil
}
func (m *Monitor) List(ctx context.Context, groupID string) ([]domain.Monitor, error) {
if _, err := uuid.Parse(groupID); err != nil {
return nil, nil
}
var monitors []model.Monitor
if err := m.db.NewSelect().
Model(&monitors).
Order("created_at ASC").
Where("group_id = ?", groupID).
Scan(ctx); err != nil && !errors.Is(err, sql.ErrNoRows) {
return nil, fmt.Errorf("couldn't select monitors from the db: %w", err)
}
result := make([]domain.Monitor, 0, len(monitors))
for _, monitor := range monitors {
result = append(result, monitor.ToDomain())
}
return result, nil
}
func (m *Monitor) Get(ctx context.Context, id string) (domain.Monitor, error) {
if _, err := uuid.Parse(id); err != nil {
return domain.Monitor{}, domain.MonitorNotFoundError{ID: id}
}
var monitor model.Monitor
err := m.db.NewSelect().
Model(&monitor).
Where("id = ?", id).
Scan(ctx)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return domain.Monitor{}, domain.MonitorNotFoundError{ID: id}
}
return domain.Monitor{}, fmt.Errorf("couldn't select monitor from the db (id=%s): %w", id, err)
}
return monitor.ToDomain(), nil
}
func (m *Monitor) Delete(ctx context.Context, id string) error {
if _, err := uuid.Parse(id); err != nil {
return domain.MonitorNotFoundError{ID: id}
}
res, err := m.db.NewDelete().
Model(&model.Monitor{}).
Returning("NULL").
Where("id = ?", id).
Exec(ctx)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return fmt.Errorf("couldn't delete monitor (id=%s): %w", id, err)
}
if affected, _ := res.RowsAffected(); affected == 0 {
return domain.MonitorNotFoundError{ID: id}
}
return nil
}
func mapCreateMonitorError(err error, params domain.CreateMonitorParams) error {
var pgError pgdriver.Error
if !errors.As(err, &pgError) {
return err
}
code := pgError.Field('C')
constraint := pgError.Field('n')
switch {
case code == pgerrcode.ForeignKeyViolation && constraint == "monitors_group_id_fkey":
return domain.GroupDoesNotExistError{
ID: params.GroupID(),
}
case code == pgerrcode.UniqueViolation && constraint == "monitors_group_id_tribe_id_key":
return domain.MonitorAlreadyExistsError{
TribeID: params.TribeID(),
GroupID: params.GroupID(),
}
default:
return err
}
}