Skip to content
Draft

temp #2023

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions lib/gcpspanner/notification_channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,79 @@ func (c *Client) GetNotificationChannel(
return spannerChannel.toPublic()
}

// ListNotificationChannelsRequest is a request to list notification channels.
type ListNotificationChannelsRequest struct {
UserID string
PageSize int
PageToken *string
}

func (r ListNotificationChannelsRequest) GetPageSize() int {
return r.PageSize
}

func (r ListNotificationChannelsRequest) GetPageToken() *string {
return r.PageToken
}

type notificationChannelCursor struct {
LastID string `json:"last_id"`
}

type listNotificationChannelsMapper struct{ notificationChannelMapper }

func (m listNotificationChannelsMapper) EncodePageToken(item spannerNotificationChannel) string {
return encodeCursor(notificationChannelCursor{
LastID: item.ID,
})
}

func (m listNotificationChannelsMapper) SelectList(req ListNotificationChannelsRequest) spanner.Statement {
var pageFilter string
params := map[string]interface{}{
"userID": req.UserID,
"pageSize": req.PageSize,
}
if req.PageToken != nil {
cursor, err := decodeCursor[notificationChannelCursor](*req.PageToken)
if err == nil {
params["lastID"] = cursor.LastID
pageFilter = " AND ID > @lastID"
}

}
query := fmt.Sprintf(`SELECT
ID, UserID, Name, Type, Config, CreatedAt, UpdatedAt
FROM NotificationChannels
WHERE UserID = @userID %s
ORDER BY UpdatedAt, ID
LIMIT @pageSize`, pageFilter)
stmt := spanner.NewStatement(query)
stmt.Params = params

return stmt
}

// ListNotificationChannels lists all notification channels for a user.
func (c *Client) ListNotificationChannels(
ctx context.Context, req ListNotificationChannelsRequest) ([]NotificationChannel, *string, error) {
items, token, err := newEntityLister[listNotificationChannelsMapper](c).list(ctx, req)
if err != nil {
return nil, nil, err
}

channels := make([]NotificationChannel, 0, len(items))
for _, item := range items {
channel, err := item.toPublic()
if err != nil {
return nil, nil, err
}
channels = append(channels, *channel)
}

return channels, token, nil
}

// UpdateNotificationChannel updates a notification channel if it belongs to the specified user.
func (c *Client) UpdateNotificationChannel(
ctx context.Context, req UpdateNotificationChannelRequest) error {
Expand Down
57 changes: 57 additions & 0 deletions lib/gcpspanner/notification_channel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,60 @@ func TestNotificationChannelRefactoredOperations(t *testing.T) {
}
})
}

func TestListNotificationChannels(t *testing.T) {
ctx := context.Background()
restartDatabaseContainer(t)

userID := uuid.NewString()

baseCreateReq := CreateNotificationChannelRequest{
UserID: userID,
Name: "Test Email",
Type: "EMAIL",
EmailConfig: &EmailConfig{
Address: "[email protected]",
IsVerified: true,
VerificationToken: nil,
},
}

// Create a few channels to list
for i := 0; i < 3; i++ {
_, err := spannerClient.CreateNotificationChannel(ctx, baseCreateReq)
if err != nil {
t.Fatalf("failed to create notification channel for list test: %v", err)
}
}

// List first page
listReq1 := ListNotificationChannelsRequest{
UserID: userID,
PageSize: 2,
PageToken: nil,
}
results1, nextPageToken1, err := spannerClient.ListNotificationChannels(ctx, listReq1)
if err != nil {
t.Fatalf("ListNotificationChannels page 1 failed: %v", err)
}
if len(results1) != 2 {
t.Errorf("expected 2 results on page 1, got %d", len(results1))
}
if nextPageToken1 == nil {
t.Fatal("expected a next page token on page 1, got nil")
}

// List second page
listReq2 := ListNotificationChannelsRequest{
UserID: userID,
PageSize: 2,
PageToken: nextPageToken1,
}
results2, _, err := spannerClient.ListNotificationChannels(ctx, listReq2)
if err != nil {
t.Fatalf("ListNotificationChannels page 2 failed: %v", err)
}
if len(results2) < 1 {
t.Errorf("expected at least 1 result on page 2, got %d", len(results2))
}
}
Loading
Loading