upda/server/repository_event.go

233 lines
5.3 KiB
Go

package server
import (
"encoding/json"
"git.myservermanager.com/varakh/upda/api"
"gorm.io/gorm"
"time"
)
type eventRepository interface {
find(id string) (*Event, error)
window(size int, skip int, orderBy string, order string) ([]*Event, error)
windowHasNext(size int, skip int, orderBy string, order string) (bool, error)
count(state ...api.EventState) (int64, error)
findAllByState(limit int, state ...api.EventState) ([]*Event, error)
create(name api.EventName, state api.EventState, payload interface{}) (*Event, error)
updateState(id string, state api.EventState) (*Event, error)
delete(id string) (int64, error)
deleteByUpdatedAtBeforeAndStates(time time.Time, state ...api.EventState) (int64, error)
}
type eventDbRepo struct {
db *gorm.DB
}
func newEventDbRepo(db *gorm.DB) *eventDbRepo {
return &eventDbRepo{
db: db,
}
}
func (r *eventDbRepo) find(id string) (*Event, error) {
if id == "" {
return nil, errorValidationNotBlank
}
var e Event
var res *gorm.DB
if res = r.db.Find(&e, "id = ?", id); res.Error != nil {
return nil, newServiceDatabaseError(res.Error)
}
if res.RowsAffected == 0 {
return nil, errorResourceNotFound
}
return &e, nil
}
func (r *eventDbRepo) create(name api.EventName, state api.EventState, payload interface{}) (*Event, error) {
if name == "" || state == "" {
return nil, errorValidationNotBlank
}
var e *Event
unmarshalledPayload := JSONMap{}
if payload != nil {
marshalledMetadata, err := json.Marshal(payload)
if err != nil {
return nil, err
}
err = unmarshalledPayload.UnmarshalJSON(marshalledMetadata)
if err != nil {
return nil, err
}
}
e = &Event{
Name: name.Value(),
State: state.Value(),
Payload: unmarshalledPayload,
}
var res *gorm.DB
if res = r.db.Create(&e); res.Error != nil {
return nil, newServiceDatabaseError(res.Error)
}
if res.RowsAffected == 0 {
return nil, errorDatabaseRowsExpected
}
return e, nil
}
func (r *eventDbRepo) updateState(id string, state api.EventState) (*Event, error) {
if id == "" || state == "" {
return nil, errorValidationNotBlank
}
var err error
var e *Event
if e, err = r.find(id); err != nil {
return nil, err
}
e.State = state.Value()
var res *gorm.DB
if res = r.db.Save(&e); res.Error != nil {
return nil, res.Error
}
if res.RowsAffected == 0 {
return e, errorDatabaseRowsExpected
}
return e, nil
}
func (r *eventDbRepo) delete(id string) (int64, error) {
if id == "" {
return 0, errorValidationNotBlank
}
var res *gorm.DB
if res = r.db.Delete(&Event{}, "id = ?", id); res.Error != nil {
return 0, newServiceDatabaseError(res.Error)
}
return res.RowsAffected, nil
}
func (r *eventDbRepo) deleteByUpdatedAtBeforeAndStates(time time.Time, state ...api.EventState) (int64, error) {
if len(state) == 0 {
return 0, errorValidationNotEmpty
}
states := make([]string, 0, len(state))
for _, i := range state {
states = append(states, i.Value())
}
var res *gorm.DB
if res = r.db.Where("state IN ?", states).Where("updated_at < ?", time).Delete(&Event{}); res.Error != nil {
return 0, newServiceDatabaseError(res.Error)
}
return res.RowsAffected, nil
}
func (r *eventDbRepo) window(size int, skip int, orderBy string, order string) ([]*Event, error) {
if size <= 0 {
return nil, errorValidationSizeGreaterZero
}
if orderBy == "" {
orderBy = "created_at"
}
if order == "" {
order = "asc"
}
var e []*Event
if res := r.db.Order(orderBy + " " + order).Offset(skip).Limit(size).Find(&e); res.Error != nil {
return nil, newServiceDatabaseError(res.Error)
}
return e, nil
}
func (r *eventDbRepo) windowHasNext(size int, skip int, orderBy string, order string) (bool, error) {
if orderBy == "" {
orderBy = "created_at"
}
if order == "" {
order = "asc"
}
var e []*Event
if res := r.db.Order(orderBy + " " + order).Offset(skip + size).Find(&e); res.Error != nil {
return false, newServiceDatabaseError(res.Error)
}
return len(e) > 0, nil
}
func (r *eventDbRepo) findAllByState(limit int, state ...api.EventState) ([]*Event, error) {
if len(state) == 0 {
return nil, errorValidationNotEmpty
}
if limit <= 0 {
return nil, errorValidationLimitGreaterZero
}
var e []*Event
states := translateEventState(state...)
if res := r.db.Model(&Event{}).Scopes(allGetEventCriterion(states)).Order("created_at asc").Limit(limit).Find(&e); res.Error != nil {
return nil, newServiceDatabaseError(res.Error)
}
return e, nil
}
func (r *eventDbRepo) count(state ...api.EventState) (int64, error) {
var c int64
states := translateEventState(state...)
if res := r.db.Model(&Event{}).Scopes(allGetEventCriterion(states)).Count(&c); res.Error != nil {
return 0, newServiceDatabaseError(res.Error)
}
return c, nil
}
func translateEventState(state ...api.EventState) []string {
states := make([]string, 0)
if len(state) > 0 {
for _, s := range state {
states = append(states, s.Value())
}
}
return states
}
func criterionEventState(states []string) func(db *gorm.DB) *gorm.DB {
if states != nil && len(states) > 0 {
return func(db *gorm.DB) *gorm.DB {
return db.Where("state IN (?)", states)
}
}
return func(db *gorm.DB) *gorm.DB {
return db
}
}
func allGetEventCriterion(states []string) func(db *gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
return db.Scopes(criterionEventState(states))
}
}