upda/server/service_event.go
Varakh 10bc3a59bb feat(updates,events): Streamline update state changes into one event type only (#27)
Reviewed-on: #27
Co-authored-by: Varakh <varakh@varakh.de>
Co-committed-by: Varakh <varakh@varakh.de>
2024-04-28 22:27:34 +02:00

226 lines
5.7 KiB
Go

package server
import (
"errors"
"git.myservermanager.com/varakh/upda/api"
"git.myservermanager.com/varakh/upda/util"
"go.uber.org/zap"
"time"
)
type eventService struct {
repo eventRepository
}
func newEventService(r eventRepository) *eventService {
return &eventService{
repo: r,
}
}
func (s *eventService) createUpdateCreated(e *Update) *Event {
if e == nil {
return nil
}
s.createWithWarnOnly(api.EventNameUpdateCreated, &api.EventPayloadUpdateCreatedDto{
ID: e.ID,
Application: e.Application,
Provider: e.Provider,
Host: e.Host,
Version: e.Version,
State: e.State,
})
return nil
}
func (s *eventService) createUpdateUpdated(old *Update, new *Update) *Event {
if old == nil || new == nil {
return nil
}
var eventName api.EventName
if old.State == new.State {
eventName = api.EventNameUpdateUpdated
} else {
eventName = api.EventNameUpdateUpdatedState
}
s.createWithWarnOnly(eventName, &api.EventPayloadUpdateUpdatedDto{
ID: new.ID,
Application: new.Application,
Provider: new.Provider,
Host: new.Host,
VersionPrior: old.Version,
Version: new.Version,
StatePrior: old.State,
State: new.State,
})
return nil
}
func (s *eventService) createUpdateDeleted(e *Update) *Event {
if e == nil {
return nil
}
s.createWithWarnOnly(api.EventNameUpdateDeleted, &api.EventPayloadUpdateDeletedDto{
Application: e.Application,
Provider: e.Provider,
Host: e.Host,
Version: e.Version,
State: e.State,
})
return nil
}
func (s *eventService) createWithWarnOnly(name api.EventName, payload interface{}) *Event {
var e *Event
var err error
if e, err = s.create(name, payload); err != nil {
zap.L().Sugar().Warnf("Could not create event '%s': %v", name, err)
return nil
}
return e
}
func (s *eventService) create(name api.EventName, payload interface{}) (*Event, error) {
if name == "" {
return nil, errorValidationNotBlank
}
var e *Event
var err error
if e, err = s.repo.create(name, api.EventStateCreated, payload); err != nil {
return nil, err
}
zap.L().Sugar().Infof("Created event '%v'", e.Name)
return e, err
}
func (s *eventService) get(id string) (*Event, error) {
if id == "" {
return nil, errorValidationNotBlank
}
return s.repo.find(id)
}
func (s *eventService) delete(id string) error {
if id == "" {
return errorValidationNotBlank
}
if _, err := s.get(id); err != nil {
return err
}
if _, err := s.repo.delete(id); err != nil {
return err
}
zap.L().Sugar().Infof("Deleted event '%v'", id)
return nil
}
func (s *eventService) cleanStale(time time.Time, state ...api.EventState) (int64, error) {
if len(state) == 0 {
return 0, errorValidationNotEmpty
}
return s.repo.deleteByUpdatedAtBeforeAndStates(time, state...)
}
func (s *eventService) window(size int, skip int, orderBy string, order string) ([]*Event, error) {
return s.repo.window(size, skip, orderBy, order)
}
func (s *eventService) windowHasNext(size int, skip int, orderBy string, order string) (bool, error) {
return s.repo.windowHasNext(size, skip, orderBy, order)
}
func (s *eventService) count(state ...api.EventState) (int64, error) {
return s.repo.count(state...)
}
func (s *eventService) getByState(limit int, state ...api.EventState) ([]*Event, error) {
if len(state) == 0 {
return nil, errorValidationNotEmpty
}
if limit <= 0 {
return nil, errorValidationLimitGreaterZero
}
return s.repo.findAllByState(limit, state...)
}
func (s *eventService) updateState(id string, state api.EventState) (*Event, error) {
if id == "" || state == "" {
return nil, errorValidationNotBlank
}
var e *Event
var err error
if e, err = s.get(id); err != nil {
return nil, err
}
if e, err = s.repo.updateState(id, state); err != nil {
return nil, err
}
zap.L().Sugar().Infof("Modified event '%v'", id)
return e, nil
}
func (s *eventService) extractPayloadInfo(event *Event) (*eventPayloadInformationDto, error) {
if event == nil {
return nil, errorValidationNotEmpty
}
var err error
var bytes []byte
if bytes, err = event.Payload.MarshalJSON(); err != nil {
return nil, newServiceError(General, err)
}
switch event.Name {
case api.EventNameUpdateCreated.Value():
var p api.EventPayloadUpdateCreatedDto
if p, err = util.UnmarshalGenericJSON[api.EventPayloadUpdateCreatedDto](bytes); err != nil {
return nil, newServiceError(General, err)
}
return &eventPayloadInformationDto{Host: p.Host, Application: p.Application, Provider: p.Provider, Version: p.Version, State: p.State}, nil
case api.EventNameUpdateDeleted.Value():
var p api.EventPayloadUpdateDeletedDto
if p, err = util.UnmarshalGenericJSON[api.EventPayloadUpdateDeletedDto](bytes); err != nil {
return nil, newServiceError(General, err)
}
return &eventPayloadInformationDto{Host: p.Host, Application: p.Application, Provider: p.Provider, Version: p.Version, State: p.State}, nil
case api.EventNameUpdateUpdatedState.Value():
var p api.EventPayloadUpdateUpdatedDto
if p, err = util.UnmarshalGenericJSON[api.EventPayloadUpdateUpdatedDto](bytes); err != nil {
return nil, newServiceError(General, err)
}
return &eventPayloadInformationDto{Host: p.Host, Application: p.Application, Provider: p.Provider, Version: p.Version, State: p.State}, nil
case api.EventNameUpdateUpdated.Value():
var p api.EventPayloadUpdateUpdatedDto
if p, err = util.UnmarshalGenericJSON[api.EventPayloadUpdateUpdatedDto](bytes); err != nil {
return nil, newServiceError(General, err)
}
return &eventPayloadInformationDto{Host: p.Host, Application: p.Application, Provider: p.Provider, Version: p.Version, State: p.State}, nil
}
return nil, newServiceError(General, errors.New("no matching event found"))
}