Skip to content

Commit

Permalink
feat: introduce context for observability
Browse files Browse the repository at this point in the history
  • Loading branch information
hirokazumiyaji committed Jun 27, 2021
1 parent b8da021 commit 6ec9ec9
Show file tree
Hide file tree
Showing 13 changed files with 94 additions and 44 deletions.
6 changes: 4 additions & 2 deletions attribution.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package revenuecat

import "context"

// Network represents a predefined attribution channel.
type Network int

Expand All @@ -21,7 +23,7 @@ type AttributionData struct {

// AddUserAttribution attaches attribution data to a subscriber from specific supported networks.
// https://docs.revenuecat.com/reference#subscribersattribution
func (c *Client) AddUserAttribution(userID string, network Network, data AttributionData) error {
func (c *Client) AddUserAttribution(ctx context.Context, userID string, network Network, data AttributionData) error {
var resp struct {
Subscriber Subscriber `json:"subscriber"`
}
Expand All @@ -34,5 +36,5 @@ func (c *Client) AddUserAttribution(userID string, network Network, data Attribu
Network: network,
}

return c.call("POST", "subscribers/"+userID+"/attribution", req, "", &resp)
return c.call(ctx, "POST", "subscribers/"+userID+"/attribution", req, "", &resp)
}
3 changes: 2 additions & 1 deletion attribution_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package revenuecat

import (
"context"
"testing"
)

Expand All @@ -9,7 +10,7 @@ func TestAddUserAttribution(t *testing.T) {
rc := New("apikey")
rc.http = cl

err := rc.AddUserAttribution("123", Facebook, AttributionData{IDFA: "test"})
err := rc.AddUserAttribution(context.Background(), "123", Facebook, AttributionData{IDFA: "test"})
if err != nil {
t.Errorf("error: %v", err)
}
Expand Down
21 changes: 16 additions & 5 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package revenuecat

import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
Expand All @@ -23,17 +24,26 @@ type doer interface {
// New returns a new *Client for the provided API key.
// For more information on authentication, see https://docs.revenuecat.com/docs/authentication.
func New(apiKey string) *Client {
return &Client{
apiKey: apiKey,
apiURL: "https://api.revenuecat.com/v1/",
http: &http.Client{
return NewWithClient(
apiKey,
&http.Client{
// Set a long timeout here since calls to Apple are probably invloved.
Timeout: 10 * time.Second,
},
)
}

// NewWithClient returns a new *Client for the provided API key and http.Client.
// For more information on authentication, see https://docs.revenuecat.com/docs/authentication.
func NewWithClient(apiKey string, client *http.Client) *Client {
return &Client{
apiKey: apiKey,
apiURL: "https://api.revenuecat.com/v1/",
http: client,
}
}

func (c *Client) call(method, path string, reqBody interface{}, platform string, respBody interface{}) error {
func (c *Client) call(ctx context.Context, method, path string, reqBody interface{}, platform string, respBody interface{}) error {
var reqBodyJSON io.Reader
if reqBody != nil {
js, err := json.Marshal(reqBody)
Expand All @@ -51,6 +61,7 @@ func (c *Client) call(method, path string, reqBody interface{}, platform string,
if platform != "" {
req.Header.Add("X-Platform", platform)
}
req = req.WithContext(ctx)

resp, err := c.http.Do(req)
if err != nil {
Expand Down
18 changes: 13 additions & 5 deletions google.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
package revenuecat

import "time"
import (
"context"
"time"
)

// RefundGoogleSubscription immediately revokes access to a Google Subscription and issues a refund for the last purchase.
// https://docs.revenuecat.com/reference#revoke-a-google-subscription
func (c *Client) RefundGoogleSubscription(userID string, id string) (Subscriber, error) {
func (c *Client) RefundGoogleSubscription(ctx context.Context, userID string, id string) (Subscriber, error) {
var resp struct {
Subscriber Subscriber `json:"subscriber"`
}

err := c.call("POST", "subscribers/"+userID+"/subscriptions/"+id+"/revoke", nil, "", &resp)
err := c.call(ctx, "POST", "subscribers/"+userID+"/subscriptions/"+id+"/revoke", nil, "", &resp)
return resp.Subscriber, err
}

// DeferGoogleSubscription defers the purchase of a Google Subscription to a later date.
// https://docs.revenuecat.com/reference#defer-a-google-subscription
func (c *Client) DeferGoogleSubscription(userID string, id string, nextExpiry time.Time) (Subscriber, error) {
func (c *Client) DeferGoogleSubscription(
ctx context.Context,
userID string,
id string,
nextExpiry time.Time,
) (Subscriber, error) {
var resp struct {
Subscriber Subscriber `json:"subscriber"`
}
Expand All @@ -26,6 +34,6 @@ func (c *Client) DeferGoogleSubscription(userID string, id string, nextExpiry ti
ExpiryTime: toMilliseconds(nextExpiry),
}

err := c.call("POST", "subscribers/"+userID+"/subscriptions/"+id+"/defer", req, "", &resp)
err := c.call(ctx, "POST", "subscribers/"+userID+"/subscriptions/"+id+"/defer", req, "", &resp)
return resp.Subscriber, err
}
5 changes: 3 additions & 2 deletions google_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package revenuecat

import (
"context"
"testing"
)

Expand All @@ -9,7 +10,7 @@ func TestRefundGoogleSubscription(t *testing.T) {
rc := New("apikey")
rc.http = cl

_, err := rc.RefundGoogleSubscription("123", "sub")
_, err := rc.RefundGoogleSubscription(context.Background(), "123", "sub")
if err != nil {
t.Errorf("error: %v", err)
}
Expand All @@ -23,7 +24,7 @@ func TestDeferGoogleSubscription(t *testing.T) {
rc := New("apikey")
rc.http = cl

_, err := rc.DeferGoogleSubscription("123", "sub", staticTime(t, "2020-01-15 23:54:17"))
_, err := rc.DeferGoogleSubscription(context.Background(), "123", "sub", staticTime(t, "2020-01-15 23:54:17"))
if err != nil {
t.Errorf("error: %v", err)
}
Expand Down
10 changes: 6 additions & 4 deletions offerings.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
package revenuecat

import "context"

// OverrideOffering overrides the current Offering for a specific user.
// https://docs.revenuecat.com/reference#override-offering
func (c *Client) OverrideOffering(userID string, offeringUUID string) (Subscriber, error) {
func (c *Client) OverrideOffering(ctx context.Context, userID string, offeringUUID string) (Subscriber, error) {
var resp struct {
Subscriber Subscriber `json:"subscriber"`
}
err := c.call("POST", "subscribers/"+userID+"/offerings/"+offeringUUID+"/override", nil, "", &resp)
err := c.call(ctx, "POST", "subscribers/"+userID+"/offerings/"+offeringUUID+"/override", nil, "", &resp)
return resp.Subscriber, err
}

// DeleteOfferingOverride reset the offering overrides back to the current offering for a specific user.
// https://docs.revenuecat.com/reference#delete-offering-override
func (c *Client) DeleteOfferingOverride(userID string) (Subscriber, error) {
func (c *Client) DeleteOfferingOverride(ctx context.Context, userID string) (Subscriber, error) {
var resp struct {
Subscriber Subscriber `json:"subscriber"`
}
err := c.call("DELETE", "subscribers/"+userID+"/offerings/override", nil, "", &resp)
err := c.call(ctx, "DELETE", "subscribers/"+userID+"/offerings/override", nil, "", &resp)
return resp.Subscriber, err
}
5 changes: 3 additions & 2 deletions offerings_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package revenuecat

import (
"context"
"testing"
)

Expand All @@ -9,7 +10,7 @@ func TestOverrideOffering(t *testing.T) {
rc := New("apikey")
rc.http = cl

_, err := rc.OverrideOffering("123", "testUUID")
_, err := rc.OverrideOffering(context.Background(), "123", "testUUID")
if err != nil {
t.Errorf("error: %v", err)
}
Expand All @@ -23,7 +24,7 @@ func TestDeleteOfferingOverride(t *testing.T) {
rc := New("apikey")
rc.http = cl

_, err := rc.DeleteOfferingOverride("123")
_, err := rc.DeleteOfferingOverride(context.Background(), "123")
if err != nil {
t.Errorf("error: %v", err)
}
Expand Down
19 changes: 14 additions & 5 deletions promotions.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
package revenuecat

import "time"
import (
"context"
"time"
)

// GrantEntitlement grants a user a promotional entitlement.
// https://docs.revenuecat.com/reference#grant-a-promotional-entitlement
func (c *Client) GrantEntitlement(userID string, id string, duration Duration, startTime time.Time) (Subscriber, error) {
func (c *Client) GrantEntitlement(
ctx context.Context,
userID string,
id string,
duration Duration,
startTime time.Time,
) (Subscriber, error) {
var resp struct {
Subscriber Subscriber `json:"subscriber"`
}
Expand All @@ -20,17 +29,17 @@ func (c *Client) GrantEntitlement(userID string, id string, duration Duration, s
req.StartTime = toMilliseconds(startTime)
}

err := c.call("POST", "subscribers/"+userID+"/entitlements/"+id+"/promotional", req, "", &resp)
err := c.call(ctx, "POST", "subscribers/"+userID+"/entitlements/"+id+"/promotional", req, "", &resp)
return resp.Subscriber, err
}

// RevokeEntitlement revokes all promotional entitlements for a given entitlement identifier and app user ID.
// https://docs.revenuecat.com/reference#revoke-promotional-entitlements
func (c *Client) RevokeEntitlement(userID string, id string) (Subscriber, error) {
func (c *Client) RevokeEntitlement(ctx context.Context, userID string, id string) (Subscriber, error) {
var resp struct {
Subscriber Subscriber `json:"subscriber"`
}

err := c.call("POST", "subscribers/"+userID+"/entitlements/"+id+"/revoke_promotionals", nil, "", &resp)
err := c.call(ctx, "POST", "subscribers/"+userID+"/entitlements/"+id+"/revoke_promotionals", nil, "", &resp)
return resp.Subscriber, err
}
5 changes: 3 additions & 2 deletions promotions_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package revenuecat

import (
"context"
"testing"
)

Expand All @@ -9,7 +10,7 @@ func TestGrantEntitlement(t *testing.T) {
rc := New("apikey")
rc.http = cl

_, err := rc.GrantEntitlement("123", "all", ThreeMonth, staticTime(t, "2020-01-15 23:54:17"))
_, err := rc.GrantEntitlement(context.Background(), "123", "all", ThreeMonth, staticTime(t, "2020-01-15 23:54:17"))
if err != nil {
t.Errorf("error: %v", err)
}
Expand All @@ -24,7 +25,7 @@ func TestRevokeEntitlement(t *testing.T) {
rc := New("apikey")
rc.http = cl

_, err := rc.RevokeEntitlement("123", "all")
_, err := rc.RevokeEntitlement(context.Background(), "123", "all")
if err != nil {
t.Errorf("error: %v", err)
}
Expand Down
11 changes: 9 additions & 2 deletions purchases.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package revenuecat

import "context"

// CreatePurchaseOptions holds the optional values for creating a purchase.
// https://docs.revenuecat.com/reference#receipts
type CreatePurchaseOptions struct {
Expand All @@ -16,7 +18,12 @@ type CreatePurchaseOptions struct {

// CreatePurchase records a purchase for a user from iOS, Android, or Stripe and will create a user if they don't already exist.
// https://docs.revenuecat.com/reference#receipts
func (c *Client) CreatePurchase(userID string, receipt string, opt *CreatePurchaseOptions) (Subscriber, error) {
func (c *Client) CreatePurchase(
ctx context.Context,
userID string,
receipt string,
opt *CreatePurchaseOptions,
) (Subscriber, error) {
var resp struct {
Subscriber Subscriber `json:"subscriber"`
}
Expand All @@ -36,6 +43,6 @@ func (c *Client) CreatePurchase(userID string, receipt string, opt *CreatePurcha
platform = opt.Platform
}

err := c.call("POST", "receipts", req, platform, &resp)
err := c.call(ctx, "POST", "receipts", req, platform, &resp)
return resp.Subscriber, err
}
5 changes: 3 additions & 2 deletions purchases_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package revenuecat

import (
"context"
"testing"
)

Expand All @@ -9,7 +10,7 @@ func TestCreatePurchaseWithoutOpts(t *testing.T) {
rc := New("apikey")
rc.http = cl

_, err := rc.CreatePurchase("123", "testreceipt", nil)
_, err := rc.CreatePurchase(context.Background(), "123", "testreceipt", nil)
if err != nil {
t.Errorf("error: %v", err)
}
Expand All @@ -32,7 +33,7 @@ func TestCreatePurchaseWithOpts(t *testing.T) {
IsRestore: true,
}

_, err := rc.CreatePurchase("123", "testreceipt", opt)
_, err := rc.CreatePurchase(context.Background(), "123", "testreceipt", opt)
if err != nil {
t.Errorf("error: %v", err)
}
Expand Down
21 changes: 13 additions & 8 deletions subscribers.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package revenuecat

import (
"context"
"encoding/json"
"time"
)
Expand Down Expand Up @@ -83,36 +84,40 @@ func (s Subscriber) IsEntitledTo(entitlement string) bool {

// GetSubscriber gets the latest subscriber info or creates one if it doesn't exist.
// https://docs.revenuecat.com/reference#subscribers
func (c *Client) GetSubscriber(userID string) (Subscriber, error) {
return c.GetSubscriberWithPlatform(userID, "")
func (c *Client) GetSubscriber(ctx context.Context, userID string) (Subscriber, error) {
return c.GetSubscriberWithPlatform(ctx, userID, "")
}

// GetSubscriberWithPlatform gets the latest subscriber info or creates one if it doesn't exist, updating the subscriber record's last_seen
// value for the platform provided.
// https://docs.revenuecat.com/reference#subscribers
func (c *Client) GetSubscriberWithPlatform(userID string, platform string) (Subscriber, error) {
func (c *Client) GetSubscriberWithPlatform(ctx context.Context, userID string, platform string) (Subscriber, error) {
var resp struct {
Subscriber Subscriber `json:"subscriber"`
}
err := c.call("GET", "subscribers/"+userID, nil, platform, &resp)
err := c.call(ctx, "GET", "subscribers/"+userID, nil, platform, &resp)
return resp.Subscriber, err
}

// UpdateSubscriberAttributes updates subscriber attributes for a user.
// https://docs.revenuecat.com/reference#update-subscriber-attributes
func (c *Client) UpdateSubscriberAttributes(userID string, attributes map[string]SubscriberAttribute) error {
func (c *Client) UpdateSubscriberAttributes(
ctx context.Context,
userID string,
attributes map[string]SubscriberAttribute,
) error {
req := struct {
Attributes map[string]SubscriberAttribute `json:"attributes"`
}{
Attributes: attributes,
}
return c.call("POST", "subscribers/"+userID+"/attributes", req, "", nil)
return c.call(ctx, "POST", "subscribers/"+userID+"/attributes", req, "", nil)
}

// DeleteSubscriber permanently deletes a subscriber.
// https://docs.revenuecat.com/reference#subscribersapp_user_id
func (c *Client) DeleteSubscriber(userID string) error {
return c.call("DELETE", "subscribers/"+userID, nil, "", nil)
func (c *Client) DeleteSubscriber(ctx context.Context, userID string) error {
return c.call(ctx, "DELETE", "subscribers/"+userID, nil, "", nil)
}

func (attr SubscriberAttribute) MarshalJSON() ([]byte, error) {
Expand Down
Loading

0 comments on commit 6ec9ec9

Please sign in to comment.