Skip to content

Commit b774e5b

Browse files
committed
feat(httpserver): add subscription management methods to server interface
The spanner adapter layer already implements these methods, so this change adds them to the server interface to expose them at the HTTP server level. Future work will involve adding HTTP handlers to call these methods.
1 parent 352cf2b commit b774e5b

File tree

5 files changed

+164
-28
lines changed

5 files changed

+164
-28
lines changed

backend/pkg/httpserver/server.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,15 @@ type WPTMetricsStorer interface {
153153
userID string, pageSize int, pageToken *string) (*backend.NotificationChannelPage, error)
154154
DeleteNotificationChannel(ctx context.Context,
155155
userID, channelID string) error
156+
CreateSavedSearchSubscription(ctx context.Context, userID string,
157+
subscription backend.Subscription) (*backend.SubscriptionResponse, error)
158+
DeleteSavedSearchSubscription(ctx context.Context, userID, subscriptionID string) error
159+
GetSavedSearchSubscription(ctx context.Context,
160+
userID, subscriptionID string) (*backend.SubscriptionResponse, error)
161+
ListSavedSearchSubscriptions(ctx context.Context,
162+
userID string, pageSize int, pageToken *string) (*backend.SubscriptionPage, error)
163+
UpdateSavedSearchSubscription(ctx context.Context, userID, subscriptionID string,
164+
req backend.UpdateSubscriptionRequest) (*backend.SubscriptionResponse, error)
156165
}
157166

158167
type Server struct {

backend/pkg/httpserver/server_test.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,42 @@ type MockDeleteNotificationChannelConfig struct {
245245
err error
246246
}
247247

248+
type MockCreateSavedSearchSubscriptionConfig struct {
249+
expectedUserID string
250+
expectedSubscription backend.Subscription
251+
output *backend.SubscriptionResponse
252+
err error
253+
}
254+
255+
type MockDeleteSavedSearchSubscriptionConfig struct {
256+
expectedUserID string
257+
expectedSubscriptionID string
258+
err error
259+
}
260+
261+
type MockGetSavedSearchSubscriptionConfig struct {
262+
expectedUserID string
263+
expectedSubscriptionID string
264+
output *backend.SubscriptionResponse
265+
err error
266+
}
267+
268+
type MockListSavedSearchSubscriptionsConfig struct {
269+
expectedUserID string
270+
expectedPageSize int
271+
expectedPageToken *string
272+
output *backend.SubscriptionPage
273+
err error
274+
}
275+
276+
type MockUpdateSavedSearchSubscriptionConfig struct {
277+
expectedUserID string
278+
expectedSubscriptionID string
279+
expectedUpdateRequest backend.UpdateSubscriptionRequest
280+
output *backend.SubscriptionResponse
281+
err error
282+
}
283+
248284
type basicHTTPTestCase[T any] struct {
249285
name string
250286
cfg *T
@@ -274,6 +310,11 @@ type MockWPTMetricsStorer struct {
274310
getNotificationChannelCfg *MockGetNotificationChannelConfig
275311
listNotificationChannelsCfg *MockListNotificationChannelsConfig
276312
deleteNotificationChannelCfg *MockDeleteNotificationChannelConfig
313+
createSavedSearchSubscriptionCfg *MockCreateSavedSearchSubscriptionConfig
314+
deleteSavedSearchSubscriptionCfg *MockDeleteSavedSearchSubscriptionConfig
315+
getSavedSearchSubscriptionCfg *MockGetSavedSearchSubscriptionConfig
316+
listSavedSearchSubscriptionsCfg *MockListSavedSearchSubscriptionsConfig
317+
updateSavedSearchSubscriptionCfg *MockUpdateSavedSearchSubscriptionConfig
277318
t *testing.T
278319
callCountListMissingOneImplCounts int
279320
callCountListMissingOneImplFeatures int
@@ -295,6 +336,11 @@ type MockWPTMetricsStorer struct {
295336
callCountGetNotificationChannel int
296337
callCountListNotificationChannels int
297338
callCountDeleteNotificationChannel int
339+
callCountCreateSavedSearchSubscription int
340+
callCountDeleteSavedSearchSubscription int
341+
callCountGetSavedSearchSubscription int
342+
callCountListSavedSearchSubscriptions int
343+
callCountUpdateSavedSearchSubscription int
298344
}
299345

300346
func (m *MockWPTMetricsStorer) GetIDFromFeatureKey(
@@ -308,6 +354,76 @@ func (m *MockWPTMetricsStorer) GetIDFromFeatureKey(
308354
return m.getIDFromFeatureKeyConfig.result, m.getIDFromFeatureKeyConfig.err
309355
}
310356

357+
func (m *MockWPTMetricsStorer) CreateSavedSearchSubscription(_ context.Context, userID string,
358+
subscription backend.Subscription) (*backend.SubscriptionResponse, error) {
359+
m.callCountCreateSavedSearchSubscription++
360+
if userID != m.createSavedSearchSubscriptionCfg.expectedUserID {
361+
m.t.Errorf("unexpected user id %s", userID)
362+
}
363+
if !reflect.DeepEqual(subscription, m.createSavedSearchSubscriptionCfg.expectedSubscription) {
364+
m.t.Errorf("unexpected subscription %+v", subscription)
365+
}
366+
367+
return m.createSavedSearchSubscriptionCfg.output, m.createSavedSearchSubscriptionCfg.err
368+
}
369+
370+
func (m *MockWPTMetricsStorer) DeleteSavedSearchSubscription(_ context.Context, userID, subscriptionID string) error {
371+
m.callCountDeleteSavedSearchSubscription++
372+
if userID != m.deleteSavedSearchSubscriptionCfg.expectedUserID {
373+
m.t.Errorf("unexpected user id %s", userID)
374+
}
375+
if subscriptionID != m.deleteSavedSearchSubscriptionCfg.expectedSubscriptionID {
376+
m.t.Errorf("unexpected subscription id %s", subscriptionID)
377+
}
378+
379+
return m.deleteSavedSearchSubscriptionCfg.err
380+
}
381+
382+
func (m *MockWPTMetricsStorer) GetSavedSearchSubscription(_ context.Context,
383+
userID, subscriptionID string) (*backend.SubscriptionResponse, error) {
384+
m.callCountGetSavedSearchSubscription++
385+
if userID != m.getSavedSearchSubscriptionCfg.expectedUserID {
386+
m.t.Errorf("unexpected user id %s", userID)
387+
}
388+
if subscriptionID != m.getSavedSearchSubscriptionCfg.expectedSubscriptionID {
389+
m.t.Errorf("unexpected subscription id %s", subscriptionID)
390+
}
391+
392+
return m.getSavedSearchSubscriptionCfg.output, m.getSavedSearchSubscriptionCfg.err
393+
}
394+
395+
func (m *MockWPTMetricsStorer) ListSavedSearchSubscriptions(_ context.Context,
396+
userID string, pageSize int, pageToken *string) (*backend.SubscriptionPage, error) {
397+
m.callCountListSavedSearchSubscriptions++
398+
if userID != m.listSavedSearchSubscriptionsCfg.expectedUserID {
399+
m.t.Errorf("unexpected user id %s", userID)
400+
}
401+
if pageSize != m.listSavedSearchSubscriptionsCfg.expectedPageSize {
402+
m.t.Errorf("unexpected page size %d", pageSize)
403+
}
404+
if !reflect.DeepEqual(pageToken, m.listSavedSearchSubscriptionsCfg.expectedPageToken) {
405+
m.t.Errorf("unexpected page token %+v", pageToken)
406+
}
407+
408+
return m.listSavedSearchSubscriptionsCfg.output, m.listSavedSearchSubscriptionsCfg.err
409+
}
410+
411+
func (m *MockWPTMetricsStorer) UpdateSavedSearchSubscription(_ context.Context, userID, subscriptionID string,
412+
req backend.UpdateSubscriptionRequest) (*backend.SubscriptionResponse, error) {
413+
m.callCountUpdateSavedSearchSubscription++
414+
if userID != m.updateSavedSearchSubscriptionCfg.expectedUserID {
415+
m.t.Errorf("unexpected user id %s", userID)
416+
}
417+
if subscriptionID != m.updateSavedSearchSubscriptionCfg.expectedSubscriptionID {
418+
m.t.Errorf("unexpected subscription id %s", subscriptionID)
419+
}
420+
if !reflect.DeepEqual(req, m.updateSavedSearchSubscriptionCfg.expectedUpdateRequest) {
421+
m.t.Errorf("unexpected update request %+v", req)
422+
}
423+
424+
return m.updateSavedSearchSubscriptionCfg.output, m.updateSavedSearchSubscriptionCfg.err
425+
}
426+
311427
func (m *MockWPTMetricsStorer) ListMetricsForFeatureIDBrowserAndChannel(_ context.Context,
312428
featureID string, browser string, channel string,
313429
metric backend.WPTMetricView,

lib/backendtypes/types.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414

1515
package backendtypes
1616

17-
import "errors"
17+
import (
18+
"errors"
19+
"log/slog"
20+
21+
"github.com/GoogleChrome/webstatus.dev/lib/gen/openapi/backend"
22+
)
1823

1924
var (
2025
// ErrInvalidPageToken indicates the page token is invalid.
@@ -55,3 +60,29 @@ type UserProfile struct {
5560
GitHubUserID int64
5661
Emails []string
5762
}
63+
64+
// AttemptToStoreSubscriptionTrigger attempts to convert the given subscription trigger
65+
// writable into a subscription trigger response value. If the conversion fails,
66+
// it logs a warning and returns an empty SubscriptionTriggerResponseValue.
67+
func AttemptToStoreSubscriptionTrigger(t backend.SubscriptionTriggerWritable) backend.SubscriptionTriggerResponseValue {
68+
ret := backend.SubscriptionTriggerResponseValue{}
69+
err := ret.FromSubscriptionTriggerWritable(t)
70+
if err != nil {
71+
slog.Warn("unable to convert trigger from database. skipping", "err", err, "value", t)
72+
}
73+
74+
return ret
75+
}
76+
77+
// AttemptToStoreSubscriptionTriggerUnknown attempts to convert an unknown subscription trigger
78+
// into a subscription trigger response value. If the conversion fails,
79+
// it logs a warning and returns an empty SubscriptionTriggerResponseValue.
80+
func AttemptToStoreSubscriptionTriggerUnknown() backend.SubscriptionTriggerResponseValue {
81+
ret := backend.SubscriptionTriggerResponseValue{}
82+
err := ret.FromEnumUnknown(backend.EnumUnknownValue)
83+
if err != nil {
84+
slog.Warn("unable to convert trigger from database. skipping", "err", err)
85+
}
86+
87+
return ret
88+
}

lib/gcpspanner/spanneradapters/backend.go

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,26 +1341,6 @@ func backendTriggersToSpannerTriggers(backendTriggers []backend.SubscriptionTrig
13411341
return triggers
13421342
}
13431343

1344-
func attemptToStoreSubscriptionTrigger(t backend.SubscriptionTriggerWritable) backend.SubscriptionTriggerResponseValue {
1345-
ret := backend.SubscriptionTriggerResponseValue{}
1346-
err := ret.FromSubscriptionTriggerWritable(t)
1347-
if err != nil {
1348-
slog.Warn("unable to convert trigger from database. skipping", "err", err, "value", t)
1349-
}
1350-
1351-
return ret
1352-
}
1353-
1354-
func attemptToStoreSubscriptionTriggerUnknown() backend.SubscriptionTriggerResponseValue {
1355-
ret := backend.SubscriptionTriggerResponseValue{}
1356-
err := ret.FromEnumUnknown(backend.EnumUnknownValue)
1357-
if err != nil {
1358-
slog.Warn("unable to convert trigger from database. skipping", "err", err)
1359-
}
1360-
1361-
return ret
1362-
}
1363-
13641344
func spannerTriggersToBackendTriggers(spannerTriggers []string) []backend.SubscriptionTriggerResponseItem {
13651345
triggers := make([]backend.SubscriptionTriggerResponseItem, 0, len(spannerTriggers))
13661346
for _, trigger := range spannerTriggers {
@@ -1370,13 +1350,13 @@ func spannerTriggersToBackendTriggers(spannerTriggers []string) []backend.Subscr
13701350
backend.SubscriptionTriggerFeatureBaselineLimitedToNewly,
13711351
backend.SubscriptionTriggerFeatureBaselineRegressionNewlyToLimited:
13721352
triggers = append(triggers, backend.SubscriptionTriggerResponseItem{
1373-
Value: attemptToStoreSubscriptionTrigger(input),
1353+
Value: backendtypes.AttemptToStoreSubscriptionTrigger(input),
13741354
RawValue: nil,
13751355
})
13761356
default:
13771357
value := trigger
13781358
triggers = append(triggers, backend.SubscriptionTriggerResponseItem{
1379-
Value: attemptToStoreSubscriptionTriggerUnknown(),
1359+
Value: backendtypes.AttemptToStoreSubscriptionTriggerUnknown(),
13801360
RawValue: &value,
13811361
})
13821362
}

lib/gcpspanner/spanneradapters/backend_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3687,7 +3687,7 @@ func TestCreateSavedSearchSubscription(t *testing.T) {
36873687
SavedSearchId: savedSearchID,
36883688
Triggers: []backend.SubscriptionTriggerResponseItem{
36893689
{
3690-
Value: attemptToStoreSubscriptionTrigger(
3690+
Value: backendtypes.AttemptToStoreSubscriptionTrigger(
36913691
backend.SubscriptionTriggerFeatureAnyBrowserImplementationComplete),
36923692
RawValue: nil,
36933693
},
@@ -3814,7 +3814,7 @@ func TestListSavedSearchSubscriptions(t *testing.T) {
38143814
SavedSearchId: "search1",
38153815
Triggers: []backend.SubscriptionTriggerResponseItem{
38163816
{
3817-
Value: attemptToStoreSubscriptionTrigger(
3817+
Value: backendtypes.AttemptToStoreSubscriptionTrigger(
38183818
backend.SubscriptionTriggerFeatureAnyBrowserImplementationComplete),
38193819
RawValue: nil,
38203820
},
@@ -3903,7 +3903,7 @@ func TestGetSavedSearchSubscription(t *testing.T) {
39033903
SavedSearchId: "search1",
39043904
Triggers: []backend.SubscriptionTriggerResponseItem{
39053905
{
3906-
Value: attemptToStoreSubscriptionTrigger(
3906+
Value: backendtypes.AttemptToStoreSubscriptionTrigger(
39073907
backend.SubscriptionTriggerFeatureAnyBrowserImplementationComplete),
39083908
RawValue: nil,
39093909
},
@@ -4017,7 +4017,7 @@ func TestUpdateSavedSearchSubscription(t *testing.T) {
40174017
Id: subID,
40184018
Triggers: []backend.SubscriptionTriggerResponseItem{
40194019
{
4020-
Value: attemptToStoreSubscriptionTrigger(
4020+
Value: backendtypes.AttemptToStoreSubscriptionTrigger(
40214021
backend.SubscriptionTriggerFeatureBaselineLimitedToNewly),
40224022
RawValue: nil,
40234023
},
@@ -4069,7 +4069,7 @@ func TestUpdateSavedSearchSubscription(t *testing.T) {
40694069
SavedSearchId: "savedsearchid",
40704070
Triggers: []backend.SubscriptionTriggerResponseItem{
40714071
{
4072-
Value: attemptToStoreSubscriptionTrigger(
4072+
Value: backendtypes.AttemptToStoreSubscriptionTrigger(
40734073
backend.SubscriptionTriggerFeatureAnyBrowserImplementationComplete),
40744074
RawValue: nil,
40754075
},

0 commit comments

Comments
 (0)