1package notify
2
3import (
4 "context"
5 "log/slog"
6 "reflect"
7 "sync"
8
9 "tangled.org/core/appview/models"
10 "tangled.org/core/log"
11)
12
13type mergedNotifier struct {
14 notifiers []Notifier
15 logger *slog.Logger
16}
17
18func NewMergedNotifier(notifiers []Notifier, logger *slog.Logger) Notifier {
19 return &mergedNotifier{notifiers, logger}
20}
21
22var _ Notifier = &mergedNotifier{}
23
24// fanout calls the same method on all notifiers concurrently
25func (m *mergedNotifier) fanout(method string, ctx context.Context, args ...any) {
26 ctx = log.IntoContext(ctx, m.logger.With("method", method))
27 var wg sync.WaitGroup
28 for _, n := range m.notifiers {
29 wg.Add(1)
30 go func(notifier Notifier) {
31 defer wg.Done()
32 v := reflect.ValueOf(notifier).MethodByName(method)
33 in := make([]reflect.Value, len(args)+1)
34 in[0] = reflect.ValueOf(ctx)
35 for i, arg := range args {
36 in[i+1] = reflect.ValueOf(arg)
37 }
38 v.Call(in)
39 }(n)
40 }
41 wg.Wait()
42}
43
44func (m *mergedNotifier) NewRepo(ctx context.Context, repo *models.Repo) {
45 m.fanout("NewRepo", ctx, repo)
46}
47
48func (m *mergedNotifier) NewStar(ctx context.Context, star *models.Star) {
49 m.fanout("NewStar", ctx, star)
50}
51
52func (m *mergedNotifier) DeleteStar(ctx context.Context, star *models.Star) {
53 m.fanout("DeleteStar", ctx, star)
54}
55
56func (m *mergedNotifier) NewIssue(ctx context.Context, issue *models.Issue) {
57 m.fanout("NewIssue", ctx, issue)
58}
59
60func (m *mergedNotifier) NewIssueComment(ctx context.Context, comment *models.IssueComment) {
61 m.fanout("NewIssueComment", ctx, comment)
62}
63
64func (m *mergedNotifier) NewIssueState(ctx context.Context, issue *models.Issue) {
65 m.fanout("NewIssueState", ctx, issue)
66}
67
68func (m *mergedNotifier) DeleteIssue(ctx context.Context, issue *models.Issue) {
69 m.fanout("DeleteIssue", ctx, issue)
70}
71
72func (m *mergedNotifier) NewFollow(ctx context.Context, follow *models.Follow) {
73 m.fanout("NewFollow", ctx, follow)
74}
75
76func (m *mergedNotifier) DeleteFollow(ctx context.Context, follow *models.Follow) {
77 m.fanout("DeleteFollow", ctx, follow)
78}
79
80func (m *mergedNotifier) NewPull(ctx context.Context, pull *models.Pull) {
81 m.fanout("NewPull", ctx, pull)
82}
83
84func (m *mergedNotifier) NewPullComment(ctx context.Context, comment *models.PullComment) {
85 m.fanout("NewPullComment", ctx, comment)
86}
87
88func (m *mergedNotifier) NewPullState(ctx context.Context, pull *models.Pull) {
89 m.fanout("NewPullState", ctx, pull)
90}
91
92func (m *mergedNotifier) UpdateProfile(ctx context.Context, profile *models.Profile) {
93 m.fanout("UpdateProfile", ctx, profile)
94}
95
96func (m *mergedNotifier) NewString(ctx context.Context, s *models.String) {
97 m.fanout("NewString", ctx, s)
98}
99
100func (m *mergedNotifier) EditString(ctx context.Context, s *models.String) {
101 m.fanout("EditString", ctx, s)
102}
103
104func (m *mergedNotifier) DeleteString(ctx context.Context, did, rkey string) {
105 m.fanout("DeleteString", ctx, did, rkey)
106}