fix(events): deliver repo.updated and repo.deleted to owner watchers and refresh the inbox
- commit
- 063865bc65d6c8da4a64891a292cb92e187005be
- author
- brice · · 2026-10-19 06:49 UTC
- parent
- bc6524c
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +16 -5
M internal/adapters/web/inbox.go +3 -2
| @@ -155,12 +155,13 @@ func (s *Server) inboxCount(ctx context.Context) (n int, show bool) { | |||
| 155 | 155 | return ov.Counts.MergeRequests + ov.Counts.Issues, true | |
| 156 | 156 | } | |
| 157 | 157 | ||
| 158 | - | // inbox renders the fragments an event of a merge request or an issue changes | |
| 158 | + | // inbox renders the fragments an event of a merge request, an issue or a repository changes | |
| 159 | 159 | // on the inbox page: the counters, the filter and the two lists. | |
| 160 | 160 | func (l *liveStream) inbox(ctx context.Context, we ports.WatchEvent) ([]fragment, error) { | |
| 161 | 161 | switch we.Event.(type) { | |
| 162 | 162 | case domain.MergeRequestOpened, domain.MergeRequestMerged, domain.MergeRequestClosed, domain.MergeRequestReady, domain.CommentAdded, | |
| 163 | - | domain.IssueOpened, domain.IssueClosed, domain.IssueReopened, domain.IssueCommented: | |
| 163 | + | domain.IssueOpened, domain.IssueClosed, domain.IssueReopened, domain.IssueCommented, | |
| 164 | + | domain.RepoUpdated, domain.RepoDeleted: | |
| 164 | 165 | default: | |
| 165 | 166 | return nil, nil | |
| 166 | 167 | } | |
| @@ -155,12 +155,13 @@ func (s *Server) inboxCount(ctx context.Context) (n int, show bool) { | |||||
| 155 | return ov.Counts.MergeRequests + ov.Counts.Issues, true | 155 | return ov.Counts.MergeRequests + ov.Counts.Issues, true | ||
| 156 | } | 156 | } | ||
| 157 | 157 | ||||
| 158 | - | // inbox renders the fragments an event of a merge request or an issue changes | 158 | + | // inbox renders the fragments an event of a merge request, an issue or a repository changes |
| 159 | // on the inbox page: the counters, the filter and the two lists. | 159 | // on the inbox page: the counters, the filter and the two lists. | ||
| 160 | func (l *liveStream) inbox(ctx context.Context, we ports.WatchEvent) ([]fragment, error) { | 160 | func (l *liveStream) inbox(ctx context.Context, we ports.WatchEvent) ([]fragment, error) { | ||
| 161 | switch we.Event.(type) { | 161 | switch we.Event.(type) { | ||
| 162 | case domain.MergeRequestOpened, domain.MergeRequestMerged, domain.MergeRequestClosed, domain.MergeRequestReady, domain.CommentAdded, | 162 | case domain.MergeRequestOpened, domain.MergeRequestMerged, domain.MergeRequestClosed, domain.MergeRequestReady, domain.CommentAdded, | ||
| 163 | - | domain.IssueOpened, domain.IssueClosed, domain.IssueReopened, domain.IssueCommented: | 163 | + | domain.IssueOpened, domain.IssueClosed, domain.IssueReopened, domain.IssueCommented, |
| 164 | + | domain.RepoUpdated, domain.RepoDeleted: | |||
| 164 | default: | 165 | default: | ||
| 165 | return nil, nil | 166 | return nil, nil | ||
| 166 | } | 167 | } | ||
M internal/usecase/events.go +13 -3
| @@ -270,7 +270,7 @@ func (e *Events) parseID(id string) (uint64, bool) { | |||
| 270 | 270 | type watch struct { | |
| 271 | 271 | p domain.Principal | |
| 272 | 272 | home bool | |
| 273 | - | owner bool // the owner topic: merge request and issue events of every repository | |
| 273 | + | owner bool // the owner topic: merge request, issue, repo update and deletion events of every repository | |
| 274 | 274 | repos map[domain.RepoName]bool | |
| 275 | 275 | ||
| 276 | 276 | checked time.Time // when the token store last confirmed the principal | |
| @@ -281,7 +281,7 @@ func (w *watch) wants(name domain.RepoName) bool { return w.home || w.repos[name | |||
| 281 | 281 | // wantsEvent is wants for an event: the owner topic also follows the events | |
| 282 | 282 | // about merge requests and issues of every repository. | |
| 283 | 283 | func (w *watch) wantsEvent(name domain.RepoName, ev domain.Event) bool { | |
| 284 | - | return w.wants(name) || (w.owner && isItemEvent(ev)) | |
| 284 | + | return w.wants(name) || (w.owner && (isItemEvent(ev) || isRepoLifecycleEvent(ev))) | |
| 285 | 285 | } | |
| 286 | 286 | ||
| 287 | 287 | // parseTopics validates the topics of a watch. A repository topic needs a | |
| @@ -495,7 +495,7 @@ func (e *Events) deliver(ctx context.Context, w *watch, be bufferedEvent, send f | |||
| 495 | 495 | return send(ports.WatchEvent{Gap: true}) | |
| 496 | 496 | case domain.RepoDeleted: | |
| 497 | 497 | // The repository is gone: use the visibility it had. | |
| 498 | - | if !w.wants(ev.Repo) || !canReadAs(w.p, ev.Repo, ev.Visibility) { | |
| 498 | + | if !w.wantsEvent(ev.Repo, ev) || !canReadAs(w.p, ev.Repo, ev.Visibility) { | |
| 499 | 499 | return nil | |
| 500 | 500 | } | |
| 501 | 501 | return send(out) | |
| @@ -594,6 +594,16 @@ func isIssueEvent(ev domain.Event) bool { | |||
| 594 | 594 | return false | |
| 595 | 595 | } | |
| 596 | 596 | ||
| 597 | + | // isRepoLifecycleEvent reports whether ev is a repository update or deletion: | |
| 598 | + | // the owner topic follows them, for they change what the inbox lists. | |
| 599 | + | func isRepoLifecycleEvent(ev domain.Event) bool { | |
| 600 | + | switch ev.(type) { | |
| 601 | + | case domain.RepoUpdated, domain.RepoDeleted: | |
| 602 | + | return true | |
| 603 | + | } | |
| 604 | + | return false | |
| 605 | + | } | |
| 606 | + | ||
| 597 | 607 | // isItemEvent reports whether ev is about a merge request or an issue. | |
| 598 | 608 | func isItemEvent(ev domain.Event) bool { | |
| 599 | 609 | switch ev.(type) { | |
| @@ -270,7 +270,7 @@ func (e *Events) parseID(id string) (uint64, bool) { | |||||
| 270 | type watch struct { | 270 | type watch struct { | ||
| 271 | p domain.Principal | 271 | p domain.Principal | ||
| 272 | home bool | 272 | home bool | ||
| 273 | - | owner bool // the owner topic: merge request and issue events of every repository | 273 | + | owner bool // the owner topic: merge request, issue, repo update and deletion events of every repository |
| 274 | repos map[domain.RepoName]bool | 274 | repos map[domain.RepoName]bool | ||
| 275 | 275 | ||||
| 276 | checked time.Time // when the token store last confirmed the principal | 276 | checked time.Time // when the token store last confirmed the principal | ||
| @@ -281,7 +281,7 @@ func (w *watch) wants(name domain.RepoName) bool { return w.home || w.repos[name | |||||
| 281 | // wantsEvent is wants for an event: the owner topic also follows the events | 281 | // wantsEvent is wants for an event: the owner topic also follows the events | ||
| 282 | // about merge requests and issues of every repository. | 282 | // about merge requests and issues of every repository. | ||
| 283 | func (w *watch) wantsEvent(name domain.RepoName, ev domain.Event) bool { | 283 | func (w *watch) wantsEvent(name domain.RepoName, ev domain.Event) bool { | ||
| 284 | - | return w.wants(name) || (w.owner && isItemEvent(ev)) | 284 | + | return w.wants(name) || (w.owner && (isItemEvent(ev) || isRepoLifecycleEvent(ev))) |
| 285 | } | 285 | } | ||
| 286 | 286 | ||||
| 287 | // parseTopics validates the topics of a watch. A repository topic needs a | 287 | // parseTopics validates the topics of a watch. A repository topic needs a | ||
| @@ -495,7 +495,7 @@ func (e *Events) deliver(ctx context.Context, w *watch, be bufferedEvent, send f | |||||
| 495 | return send(ports.WatchEvent{Gap: true}) | 495 | return send(ports.WatchEvent{Gap: true}) | ||
| 496 | case domain.RepoDeleted: | 496 | case domain.RepoDeleted: | ||
| 497 | // The repository is gone: use the visibility it had. | 497 | // The repository is gone: use the visibility it had. | ||
| 498 | - | if !w.wants(ev.Repo) || !canReadAs(w.p, ev.Repo, ev.Visibility) { | 498 | + | if !w.wantsEvent(ev.Repo, ev) || !canReadAs(w.p, ev.Repo, ev.Visibility) { |
| 499 | return nil | 499 | return nil | ||
| 500 | } | 500 | } | ||
| 501 | return send(out) | 501 | return send(out) | ||
| @@ -594,6 +594,16 @@ func isIssueEvent(ev domain.Event) bool { | |||||
| 594 | return false | 594 | return false | ||
| 595 | } | 595 | } | ||
| 596 | 596 | ||||
| 597 | + | // isRepoLifecycleEvent reports whether ev is a repository update or deletion: | |||
| 598 | + | // the owner topic follows them, for they change what the inbox lists. | |||
| 599 | + | func isRepoLifecycleEvent(ev domain.Event) bool { | |||
| 600 | + | switch ev.(type) { | |||
| 601 | + | case domain.RepoUpdated, domain.RepoDeleted: | |||
| 602 | + | return true | |||
| 603 | + | } | |||
| 604 | + | return false | |||
| 605 | + | } | |||
| 606 | + | ||||
| 597 | // isItemEvent reports whether ev is about a merge request or an issue. | 607 | // isItemEvent reports whether ev is about a merge request or an issue. | ||
| 598 | func isItemEvent(ev domain.Event) bool { | 608 | func isItemEvent(ev domain.Event) bool { | ||
| 599 | switch ev.(type) { | 609 | switch ev.(type) { | ||