diff --git a/eventhandler/projector/eventhandler.go b/eventhandler/projector/eventhandler.go index dd0f373b..9d2dfbcd 100644 --- a/eventhandler/projector/eventhandler.go +++ b/eventhandler/projector/eventhandler.go @@ -46,6 +46,8 @@ func (t Type) String() string { var ( // ErrModelNotSet is when a model factory is not set on the EventHandler. ErrModelNotSet = errors.New("model not set") + // ErrModelRemoved is when a model has been removed. + ErrModelRemoved = errors.New("model removed") // Returned if the model has not incremented its version as predicted. ErrIncorrectProjectedEntityVersion = errors.New("incorrect projected entity version") ) @@ -251,6 +253,16 @@ retryOnce: goto retryOnce } + if entityVersion == 0 && event.Version() > 1 { + return &Error{ + Err: ErrModelRemoved, + Projector: h.projector.ProjectorType().String(), + Event: event, + EntityID: id, + EntityVersion: entityVersion, + } + } + return &Error{ Err: eh.ErrIncorrectEntityVersion, Projector: h.projector.ProjectorType().String(), diff --git a/eventhandler/projector/eventhandler_test.go b/eventhandler/projector/eventhandler_test.go index 7c39d89c..c911ec61 100644 --- a/eventhandler/projector/eventhandler_test.go +++ b/eventhandler/projector/eventhandler_test.go @@ -359,6 +359,33 @@ func TestEventHandler_DeleteModel(t *testing.T) { } } +func TestEventHandler_UpdateModelAfterDelete(t *testing.T) { + repo := &mocks.Repo{} + projector := &TestProjector{} + handler := NewEventHandler(projector, repo) + handler.SetEntityFactory(func() eh.Entity { + return &mocks.Model{} + }) + + // Entity must be versionable, but empty. + repo.Entity = &mocks.Model{} + + ctx := context.Background() + + id := uuid.New() + eventData := &mocks.EventData{Content: "event1"} + timestamp := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) + updateEvent := eh.NewEvent(mocks.EventType, eventData, timestamp, + eh.ForAggregate(mocks.AggregateType, id, 3)) + + err := handler.HandleEvent(ctx, updateEvent) + + errType := &Error{} + if !errors.As(err, &errType) || !errors.Is(err, ErrModelRemoved) { + t.Error("there should be an error:", err) + } +} + func TestEventHandler_LoadError(t *testing.T) { repo := &mocks.Repo{} projector := &TestProjector{}