diff --git a/backend/app/api/handlers/v1/controller.go b/backend/app/api/handlers/v1/controller.go index a30f977..526b8ce 100644 --- a/backend/app/api/handlers/v1/controller.go +++ b/backend/app/api/handlers/v1/controller.go @@ -1,6 +1,7 @@ package v1 import ( + "fmt" "net/http" "github.com/google/uuid" @@ -126,41 +127,31 @@ func (ctrl *V1Controller) HandleCacheWS() errchain.HandlerFunc { s.Set("gid", auth.GID) }) - ctrl.bus.Subscribe(eventbus.EventLabelMutation, func(data any) { - eventData, ok := data.(eventbus.GroupMutationEvent) - if !ok { - log.Log().Msgf("invalid event data: %v", data) - return - } - - _ = m.BroadcastFilter([]byte(`{"event": "label.mutation"}`), func(s *melody.Session) bool { - gidStr, ok := s.Get("gid") + factory := func(e string) func(data any) { + return func(data any) { + eventData, ok := data.(eventbus.GroupMutationEvent) if !ok { - return false + log.Log().Msgf("invalid event data: %v", data) + return } - gid := gidStr.(uuid.UUID) - return gid == eventData.GID - }) - }) + jsonStr := fmt.Sprintf(`{"event": "%s"}`, e) - ctrl.bus.Subscribe(eventbus.EventLocationMutation, func(data any) { - eventData, ok := data.(eventbus.GroupMutationEvent) - if !ok { - log.Log().Msgf("invalid event data: %v", data) - return + _ = m.BroadcastFilter([]byte(jsonStr), func(s *melody.Session) bool { + groupIDStr, ok := s.Get("gid") + if !ok { + return false + } + + GID := groupIDStr.(uuid.UUID) + return GID == eventData.GID + }) } + } - _ = m.BroadcastFilter([]byte(`{"event": "location.mutation"}`), func(s *melody.Session) bool { - gidStr, ok := s.Get("gid") - if !ok { - return false - } - - gid := gidStr.(uuid.UUID) - return gid == eventData.GID - }) - }) + ctrl.bus.Subscribe(eventbus.EventLabelMutation, factory("label.mutation")) + ctrl.bus.Subscribe(eventbus.EventLocationMutation, factory("location.mutation")) + ctrl.bus.Subscribe(eventbus.EventItemMutation, factory("item.mutation")) return func(w http.ResponseWriter, r *http.Request) error { return m.HandleRequest(w, r) diff --git a/backend/internal/core/services/reporting/eventbus/eventbus.go b/backend/internal/core/services/reporting/eventbus/eventbus.go index 8cd794e..508e1f0 100644 --- a/backend/internal/core/services/reporting/eventbus/eventbus.go +++ b/backend/internal/core/services/reporting/eventbus/eventbus.go @@ -12,6 +12,7 @@ type Event string const ( EventLabelMutation Event = "label.mutation" EventLocationMutation Event = "location.mutation" + EventItemMutation Event = "item.mutation" ) type GroupMutationEvent struct { @@ -37,6 +38,7 @@ func New() *EventBus { subscribers: map[Event][]func(any){ EventLabelMutation: {}, EventLocationMutation: {}, + EventItemMutation: {}, }, } } diff --git a/backend/internal/data/repo/repo_items.go b/backend/internal/data/repo/repo_items.go index 3f3c11b..2431736 100644 --- a/backend/internal/data/repo/repo_items.go +++ b/backend/internal/data/repo/repo_items.go @@ -6,6 +6,7 @@ import ( "time" "github.com/google/uuid" + "github.com/hay-kot/homebox/backend/internal/core/services/reporting/eventbus" "github.com/hay-kot/homebox/backend/internal/data/ent" "github.com/hay-kot/homebox/backend/internal/data/ent/group" "github.com/hay-kot/homebox/backend/internal/data/ent/item" @@ -17,7 +18,8 @@ import ( ) type ItemsRepository struct { - db *ent.Client + db *ent.Client + bus *eventbus.EventBus } type ( @@ -266,6 +268,12 @@ func mapItemOut(item *ent.Item) ItemOut { } } +func (r *ItemsRepository) publishMutationEvent(GID uuid.UUID) { + if r.bus != nil { + r.bus.Publish(eventbus.EventItemMutation, eventbus.GroupMutationEvent{GID: GID}) + } +} + func (e *ItemsRepository) getOne(ctx context.Context, where ...predicate.Item) (ItemOut, error) { q := e.db.Item.Query().Where(where...) @@ -520,11 +528,18 @@ func (e *ItemsRepository) Create(ctx context.Context, gid uuid.UUID, data ItemCr return ItemOut{}, err } + e.publishMutationEvent(gid) return e.GetOne(ctx, result.ID) } func (e *ItemsRepository) Delete(ctx context.Context, id uuid.UUID) error { - return e.db.Item.DeleteOneID(id).Exec(ctx) + err := e.db.Item.DeleteOneID(id).Exec(ctx) + if err != nil { + return err + } + + e.publishMutationEvent(id) + return nil } func (e *ItemsRepository) DeleteByGroup(ctx context.Context, gid, id uuid.UUID) error { @@ -534,6 +549,12 @@ func (e *ItemsRepository) DeleteByGroup(ctx context.Context, gid, id uuid.UUID) item.ID(id), item.HasGroupWith(group.ID(gid)), ).Exec(ctx) + + if err != nil { + return err + } + + e.publishMutationEvent(gid) return err } @@ -649,6 +670,7 @@ func (e *ItemsRepository) UpdateByGroup(ctx context.Context, GID uuid.UUID, data } } + e.publishMutationEvent(GID) return e.GetOne(ctx, data.ID) } @@ -687,6 +709,7 @@ func (e *ItemsRepository) Patch(ctx context.Context, GID, ID uuid.UUID, data Ite q.SetQuantity(*data.Quantity) } + e.publishMutationEvent(GID) return q.Exec(ctx) } diff --git a/backend/internal/data/repo/repos_all.go b/backend/internal/data/repo/repos_all.go index 4752e8b..f9e6197 100644 --- a/backend/internal/data/repo/repos_all.go +++ b/backend/internal/data/repo/repos_all.go @@ -26,7 +26,7 @@ func New(db *ent.Client, bus *eventbus.EventBus, root string) *AllRepos { Groups: NewGroupRepository(db), Locations: &LocationRepository{db, bus}, Labels: &LabelRepository{db, bus}, - Items: &ItemsRepository{db}, + Items: &ItemsRepository{db, bus}, Docs: &DocumentRepository{db, root}, Attachments: &AttachmentRepo{db}, MaintEntry: &MaintenanceEntryRepository{db}, diff --git a/frontend/layouts/default.vue b/frontend/layouts/default.vue index 17645f5..81a8b83 100644 --- a/frontend/layouts/default.vue +++ b/frontend/layouts/default.vue @@ -186,13 +186,18 @@ const ws = new WebSocket(`ws://${window.location.host}/api/v1/ws/events`); ws.onmessage = event => { const msg: EventMessage = JSON.parse(event.data); + console.debug("recieved event", msg); switch (msg.event) { case "label.mutation": - console.log("label.mutation"); labelStore.refresh(); break; case "location.mutation": - console.log("location.mutation"); + locationStore.refreshChildren(); + locationStore.refreshParents(); + break; + case "item.mutation": + // item mutations can affect locations counts + // so we need to refresh those as well locationStore.refreshChildren(); locationStore.refreshParents(); break;