Skip to content
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

minimal implementation of care partner alerts #715

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4b0c20a
adds List and Get methods to alerts client
ewollesen May 6, 2024
3792407
lift Repeat out of the base alert config
ewollesen May 6, 2024
6a77fe1
adds activity tracking to alert configurations
ewollesen May 6, 2024
c35c1b5
adds auth endpoint to retrieve a user's device tokens
ewollesen May 7, 2024
26c333b
adds the ability to retrieve device tokens to the auth client
ewollesen May 7, 2024
016620b
remove unused device tokens repo from data
ewollesen May 7, 2024
0199d25
adds a pusher client for sending APNs push notifications
ewollesen May 7, 2024
06a52e1
adapts sarama.Logger to implement log.Logger
ewollesen Jun 26, 2024
0af87eb
adapts go-common's asyncevents.SaramaEventsConsumer for alerts
ewollesen May 8, 2024
3a60854
allow invites to set an upload id
ewollesen Jul 2, 2024
1c41f09
integrates an APNs pusher into data service
ewollesen Jul 8, 2024
f342504
adds Evaluate methods to alerts.Config
ewollesen Jul 8, 2024
5fc206a
adds the alerts events consumer to the data service
ewollesen Jul 8, 2024
4f48dfa
remove some debugging logs
ewollesen Jul 11, 2024
a24c3c3
small fixes from code review
ewollesen Jul 12, 2024
29205ff
rename Note => Notification
ewollesen Jul 12, 2024
362207d
one mock of DeviceTokenRepository is enough
ewollesen Jul 19, 2024
d79fc56
add a topic cascading retry mechanism for care partner alerts
ewollesen Jul 24, 2024
f6f069b
modifies DelayingConsumer to use a message header instead of a delay
ewollesen Sep 16, 2024
d6b82b5
just a little more explanation of cascading consumer
ewollesen Sep 20, 2024
28fdf06
don't read topic and consumer group id from runtime configuration
ewollesen Oct 7, 2024
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
45 changes: 39 additions & 6 deletions alerts/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/tidepool-org/platform/auth"
"github.com/tidepool-org/platform/client"
"github.com/tidepool-org/platform/errors"
platformlog "github.com/tidepool-org/platform/log"
"github.com/tidepool-org/platform/log/null"
"github.com/tidepool-org/platform/platform"
Expand Down Expand Up @@ -42,14 +43,22 @@ type PlatformClient interface {
requestBody interface{}, responseBody interface{}, inspectors ...request.ResponseInspector) error
}

// TokenProvider retrieves session tokens needed for calling the alerts API.
//
// client.External is one implementation
type TokenProvider interface {
// ServerSessionToken provides a server-to-server API authentication token.
ServerSessionToken() (string, error)
}

// request performs common operations before passing a request off to the
// underlying platform.Client.
func (c *Client) request(ctx context.Context, method, url string, body any) error {
func (c *Client) request(ctx context.Context, method, url string, reqBody, resBody any) error {
// Platform's client.Client expects a logger to exist in the request's
// context. If it doesn't exist, request processing will panic.
loggingCtx := platformlog.NewContextWithLogger(ctx, c.logger)
// Make sure the auth token is injected into the request's headers.
return c.requestWithAuth(loggingCtx, method, url, body)
return c.requestWithAuth(loggingCtx, method, url, reqBody, resBody)
}

// requestWithAuth injects an auth token before calling platform.Client.RequestData.
Expand All @@ -58,20 +67,44 @@ func (c *Client) request(ctx context.Context, method, url string, body any) erro
// platform.Client. It might be nice to be able to use a mutator, but the auth
// is specifically handled by the platform.Client via the context field, and
// if left blank, platform.Client errors.
func (c *Client) requestWithAuth(ctx context.Context, method, url string, body any) error {
return c.client.RequestData(auth.NewContextWithServerSessionTokenProvider(ctx, c.tokenProvider), method, url, nil, body, nil)
func (c *Client) requestWithAuth(ctx context.Context, method, url string, reqBody, resBody any) error {
return c.client.RequestData(auth.NewContextWithServerSessionTokenProvider(ctx, c.tokenProvider), method, url, nil, reqBody, resBody)
}

// Upsert updates cfg if it exists or creates it if it doesn't.
func (c *Client) Upsert(ctx context.Context, cfg *Config) error {
url := c.client.ConstructURL("v1", "users", cfg.FollowedUserID, "followers", cfg.UserID, "alerts")
return c.request(ctx, http.MethodPost, url, cfg)
return c.request(ctx, http.MethodPost, url, cfg, nil)
}

// Delete the alerts config.
func (c *Client) Delete(ctx context.Context, cfg *Config) error {
url := c.client.ConstructURL("v1", "users", cfg.FollowedUserID, "followers", cfg.UserID, "alerts")
return c.request(ctx, http.MethodDelete, url, nil)
return c.request(ctx, http.MethodDelete, url, nil, nil)
}

// Get a user's alerts configuration for the followed user.
func (c *Client) Get(ctx context.Context, followedUserID, userID string) (*Config, error) {
url := c.client.ConstructURL("v1", "users", followedUserID, "followers", userID, "alerts")
cfg := &Config{}
err := c.request(ctx, http.MethodGet, url, nil, cfg)
if err != nil {
return nil, errors.Wrap(err, "Unable to request alerts config")
}
return cfg, nil
}

// List the alerts configurations that follow the given user.
//
// This method should only be called via an authenticated service session.
func (c *Client) List(ctx context.Context, followedUserID string) ([]*Config, error) {
url := c.client.ConstructURL("v1", "users", followedUserID, "followers", "alerts")
configs := []*Config{}
err := c.request(ctx, http.MethodGet, url, nil, &configs)
if err != nil {
return nil, errors.Wrap(err, "Unable to request alerts configs list")
}
return configs, nil
}

// ConfigLoader abstracts the method by which config values are loaded.
Expand Down
Loading