-
Notifications
You must be signed in to change notification settings - Fork 875
feat(coderd): add new dispatch logic for coder inbox #16764
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
61111c9
add new notification method
defelmnq 10276a5
add missing migration file
defelmnq 9573813
add coder inbox delivery target
defelmnq 4485b59
update golden files with targets
defelmnq 02113f6
fix missing details in test
defelmnq 1c2f5d2
fix enqueue functions
defelmnq 9134ea2
fix tests on notifications
defelmnq 9a58bf7
fix missing index
defelmnq 7e088ac
improve EnqueueWithData function to have multiple methods
defelmnq 548335b
Merge remote-tracking branch 'origin/main' into notif-inbox/inte-403
defelmnq b995d9d
rename migration
defelmnq ab1e9ed
work on tests
defelmnq 61746c8
finishing up tests
defelmnq e265ea0
fix tests
defelmnq e56c155
cleanup testing variables
defelmnq ac36085
add tests for notifications inbox
defelmnq ad59e8b
filter coder inbox from UI
defelmnq a11f505
add missing inbox tests
defelmnq fe58472
fix tests
defelmnq 15933fe
fixes from review
defelmnq aae0f98
improve testing logic
defelmnq 5a5f2d6
change tests for user id
defelmnq File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
3 changes: 3 additions & 0 deletions
3
coderd/database/migrations/000299_notifications_method_inbox.down.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
-- The migration is about an enum value change | ||
-- As we can not remove a value from an enum, we can let the down migration empty | ||
-- In order to avoid any failure, we use ADD VALUE IF NOT EXISTS to add the value |
1 change: 1 addition & 0 deletions
1
coderd/database/migrations/000299_notifications_method_inbox.up.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
ALTER TYPE notification_method ADD VALUE IF NOT EXISTS 'inbox'; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package dispatch | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"text/template" | ||
|
||
"golang.org/x/xerrors" | ||
|
||
"cdr.dev/slog" | ||
|
||
"github.com/google/uuid" | ||
|
||
"github.com/coder/coder/v2/coderd/database" | ||
"github.com/coder/coder/v2/coderd/database/dbtime" | ||
"github.com/coder/coder/v2/coderd/notifications/types" | ||
markdown "github.com/coder/coder/v2/coderd/render" | ||
) | ||
|
||
type InboxStore interface { | ||
InsertInboxNotification(ctx context.Context, arg database.InsertInboxNotificationParams) (database.InboxNotification, error) | ||
} | ||
|
||
// InboxHandler is responsible for dispatching notification messages to the Coder Inbox. | ||
type InboxHandler struct { | ||
log slog.Logger | ||
store InboxStore | ||
} | ||
|
||
func NewInboxHandler(log slog.Logger, store InboxStore) *InboxHandler { | ||
return &InboxHandler{log: log, store: store} | ||
} | ||
|
||
func (s *InboxHandler) Dispatcher(payload types.MessagePayload, titleTmpl, bodyTmpl string, _ template.FuncMap) (DeliveryFunc, error) { | ||
subject, err := markdown.PlaintextFromMarkdown(titleTmpl) | ||
if err != nil { | ||
return nil, xerrors.Errorf("render subject: %w", err) | ||
} | ||
|
||
htmlBody, err := markdown.PlaintextFromMarkdown(bodyTmpl) | ||
if err != nil { | ||
return nil, xerrors.Errorf("render html body: %w", err) | ||
} | ||
|
||
return s.dispatch(payload, subject, htmlBody), nil | ||
} | ||
|
||
func (s *InboxHandler) dispatch(payload types.MessagePayload, title, body string) DeliveryFunc { | ||
return func(ctx context.Context, msgID uuid.UUID) (bool, error) { | ||
userID, err := uuid.Parse(payload.UserID) | ||
if err != nil { | ||
return false, xerrors.Errorf("parse user ID: %w", err) | ||
} | ||
templateID, err := uuid.Parse(payload.NotificationTemplateID) | ||
if err != nil { | ||
return false, xerrors.Errorf("parse template ID: %w", err) | ||
} | ||
|
||
actions, err := json.Marshal(payload.Actions) | ||
if err != nil { | ||
return false, xerrors.Errorf("marshal actions: %w", err) | ||
} | ||
|
||
// nolint:exhaustruct | ||
_, err = s.store.InsertInboxNotification(ctx, database.InsertInboxNotificationParams{ | ||
ID: msgID, | ||
UserID: userID, | ||
TemplateID: templateID, | ||
Targets: payload.Targets, | ||
Title: title, | ||
Content: body, | ||
Actions: actions, | ||
CreatedAt: dbtime.Now(), | ||
}) | ||
if err != nil { | ||
return false, xerrors.Errorf("insert inbox notification: %w", err) | ||
} | ||
|
||
return false, nil | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package dispatch_test | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"cdr.dev/slog" | ||
"cdr.dev/slog/sloggers/slogtest" | ||
|
||
"github.com/google/uuid" | ||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/coder/coder/v2/coderd/database" | ||
"github.com/coder/coder/v2/coderd/database/dbgen" | ||
"github.com/coder/coder/v2/coderd/database/dbtestutil" | ||
"github.com/coder/coder/v2/coderd/notifications" | ||
"github.com/coder/coder/v2/coderd/notifications/dispatch" | ||
"github.com/coder/coder/v2/coderd/notifications/types" | ||
) | ||
|
||
func TestInbox(t *testing.T) { | ||
t.Parallel() | ||
|
||
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true}).Leveled(slog.LevelDebug) | ||
tests := []struct { | ||
name string | ||
msgID uuid.UUID | ||
payload types.MessagePayload | ||
expectedErr string | ||
expectedRetry bool | ||
}{ | ||
{ | ||
name: "OK", | ||
msgID: uuid.New(), | ||
payload: types.MessagePayload{ | ||
NotificationName: "test", | ||
NotificationTemplateID: notifications.TemplateWorkspaceDeleted.String(), | ||
UserID: "valid", | ||
Actions: []types.TemplateAction{ | ||
{ | ||
Label: "View my workspace", | ||
URL: "https://coder.com/workspaces/1", | ||
}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
name: "InvalidUserID", | ||
payload: types.MessagePayload{ | ||
NotificationName: "test", | ||
NotificationTemplateID: notifications.TemplateWorkspaceDeleted.String(), | ||
UserID: "invalid", | ||
Actions: []types.TemplateAction{}, | ||
}, | ||
expectedErr: "parse user ID", | ||
expectedRetry: false, | ||
}, | ||
{ | ||
name: "InvalidTemplateID", | ||
payload: types.MessagePayload{ | ||
NotificationName: "test", | ||
NotificationTemplateID: "invalid", | ||
UserID: "valid", | ||
Actions: []types.TemplateAction{}, | ||
}, | ||
expectedErr: "parse template ID", | ||
expectedRetry: false, | ||
}, | ||
} | ||
|
||
for _, tc := range tests { | ||
tc := tc | ||
t.Run(tc.name, func(t *testing.T) { | ||
t.Parallel() | ||
|
||
db, _ := dbtestutil.NewDB(t) | ||
|
||
if tc.payload.UserID == "valid" { | ||
user := dbgen.User(t, db, database.User{}) | ||
tc.payload.UserID = user.ID.String() | ||
} | ||
|
||
ctx := context.Background() | ||
|
||
handler := dispatch.NewInboxHandler(logger.Named("smtp"), db) | ||
dispatcherFunc, err := handler.Dispatcher(tc.payload, "", "", nil) | ||
require.NoError(t, err) | ||
|
||
retryable, err := dispatcherFunc(ctx, tc.msgID) | ||
|
||
if tc.expectedErr != "" { | ||
require.ErrorContains(t, err, tc.expectedErr) | ||
require.Equal(t, tc.expectedRetry, retryable) | ||
} else { | ||
require.NoError(t, err) | ||
require.False(t, retryable) | ||
uid := uuid.MustParse(tc.payload.UserID) | ||
notifs, err := db.GetInboxNotificationsByUserID(ctx, database.GetInboxNotificationsByUserIDParams{ | ||
UserID: uid, | ||
ReadStatus: database.InboxNotificationReadStatusAll, | ||
}) | ||
|
||
require.NoError(t, err) | ||
require.Len(t, notifs, 1) | ||
require.Equal(t, tc.msgID, notifs[0].ID) | ||
} | ||
}) | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is
valid
a validUserID
?