From 9612a24b921d4aeb8ab4b22e8c5ddd93e84ecf9e Mon Sep 17 00:00:00 2001
From: Peter Deme
Date: Tue, 10 May 2022 16:17:24 +0200
Subject: [PATCH] feat(context): add context as first argument (#123)
---
.github/workflows/initiate_release.yml | 2 +-
.github/workflows/release.yml | 4 +-
.github/workflows/reviewdog.yml | 2 +-
README.md | 95 ++++++++++--------
aggregated_feed.go | 25 ++---
aggregated_feed_test.go | 29 +++---
analytics.go | 9 +-
analytics_test.go | 7 +-
client.go | 129 +++++++++++++------------
client_internal_test.go | 4 +-
client_test.go | 45 ++++++---
collections.go | 29 +++---
collections_test.go | 22 +++--
feed.go | 49 +++++-----
feed_test.go | 34 ++++---
flat_feed.go | 37 +++----
flat_feed_test.go | 38 ++++----
notification_feed.go | 21 ++--
notification_feed_test.go | 25 ++---
personalization.go | 13 +--
personalization_test.go | 16 +--
reactions.go | 33 ++++---
reactions_test.go | 40 +++++---
run-lint.sh | 2 +-
users.go | 17 ++--
users_test.go | 13 ++-
26 files changed, 416 insertions(+), 324 deletions(-)
diff --git a/.github/workflows/initiate_release.yml b/.github/workflows/initiate_release.yml
index f45e15d..29c8229 100644
--- a/.github/workflows/initiate_release.yml
+++ b/.github/workflows/initiate_release.yml
@@ -28,7 +28,7 @@ jobs:
git push -q -u origin "release-$VERSION"
- name: Get changelog diff
- uses: actions/github-script@v5
+ uses: actions/github-script@v6
with:
script: |
const get_change_log_diff = require('./scripts/get_changelog_diff.js')
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 65bb61f..fd0a06e 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -12,11 +12,11 @@ jobs:
if: github.event.pull_request.merged && startsWith(github.head_ref, 'release-')
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
with:
fetch-depth: 0
- - uses: actions/github-script@v5
+ - uses: actions/github-script@v6
with:
script: |
const get_change_log_diff = require('./scripts/get_changelog_diff.js')
diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml
index 2d15bf0..291d4f8 100644
--- a/.github/workflows/reviewdog.yml
+++ b/.github/workflows/reviewdog.yml
@@ -24,7 +24,7 @@ jobs:
- name: Install golangci-lint
run:
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.45.2
+ curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.46.0
- name: Reviewdog
env:
diff --git a/README.md b/README.md
index 051bdde..b5fb872 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,10 @@
Request Feature
+---
+> ## 🚨 Breaking change in v7.0 <
+> From version 7.0.0, all methods' first argument is `context.Context`. The reason is that we internally changed `http.NewRequest()` to `http.NewRequestWithContext()` so that it's easier to handle cancellations, timeouts and deadlines for our users.
+
## About Stream
stream-go2 is a Go client for [Stream](https://getstream.io) Feeds API.
@@ -170,7 +174,7 @@ for _, activity := range resp.Results {
You can retrieve flat feeds with [custom ranking](https://getstream.io/docs/#custom_ranking), using the dedicated method:
```go
-resp, err := flat.GetActivitiesWithRanking("popularity")
+resp, err := flat.GetActivitiesWithRanking(ctx, "popularity")
if err != nil {
// ...
}
@@ -179,7 +183,7 @@ if err != nil {
#### Aggregated feeds
```go
-resp, err := aggregated.GetActivities()
+resp, err := aggregated.GetActivities(ctx)
if err != nil {
// ...
}
@@ -200,7 +204,7 @@ for _, group := range resp.Results {
#### Notification feeds
```go
-resp, err := notification.GetActivities()
+resp, err := notification.GetActivities(ctx)
if err != nil {
// ...
}
@@ -227,6 +231,7 @@ You can pass supported options and filters when retrieving activities:
```go
resp, err := flat.GetActivities(
+ ctx,
stream.WithActivitiesIDGTE("f505b3fb-a212-11e7-..."),
stream.WithActivitiesLimit(5),
...,
@@ -238,7 +243,7 @@ resp, err := flat.GetActivities(
Add a single activity:
```go
-resp, err := feed.AddActivity(stream.Activity{Actor: "bob", ...})
+resp, err := feed.AddActivity(ctx, stream.Activity{Actor: "bob", ...})
if err != nil {
// ...
}
@@ -255,7 +260,7 @@ a1 := stream.Activity{Actor: "bob", ...}
a2 := stream.Activity{Actor: "john", ...}
a3 := stream.Activity{Actor: "alice", ...}
-resp, err := feed.AddActivities(a1, a2, a3)
+resp, err := feed.AddActivities(ctx, a1, a2, a3)
if err != nil {
// ...
}
@@ -271,7 +276,7 @@ for _, activity := range resp.Activities {
### Updating activities
```go
-_, err := feed.UpdateActivities(a1, a2, ...)
+_, err := feed.UpdateActivities(ctx, a1, a2, ...)
if err != nil {
// ...
}
@@ -284,7 +289,7 @@ You can partial update activities identified either by ID:
``` go
changesetA := stream.NewUpdateActivityRequestByID("f505b3fb-a212-11e7-...", map[string]interface{}{"key": "new-value"}, []string{"removed", "keys"})
changesetB := stream.NewUpdateActivityRequestByID("f707b3fb-a212-11e7-...", map[string]interface{}{"key": "new-value"}, []string{"removed", "keys"})
-resp, err := client.PartialUpdateActivities(changesetA, changesetB)
+resp, err := client.PartialUpdateActivities(ctx, changesetA, changesetB)
if err != nil {
// ...
}
@@ -294,7 +299,7 @@ or by a ForeignID and timestamp pair:
``` go
changesetA := stream.NewUpdateActivityRequestByForeignID("dothings:1", stream.Time{...}, map[string]interface{}{"key": "new-value"}, []string{"removed", "keys"})
changesetB := stream.NewUpdateActivityRequestByForeignID("dothings:2", stream.Time{...}, map[string]interface{}{"key": "new-value"}, []string{"removed", "keys"})
-resp, err := client.PartialUpdateActivities(changesetA, changesetB)
+resp, err := client.PartialUpdateActivities(ctx, changesetA, changesetB)
if err != nil {
// ...
}
@@ -305,12 +310,12 @@ if err != nil {
You can either remove activities by ID or ForeignID:
```go
-_, err := feed.RemoveActivityByID("f505b3fb-a212-11e7-...")
+_, err := feed.RemoveActivityByID(ctx, "f505b3fb-a212-11e7-...")
if err != nil {
// ...
}
-_, err := feed.RemoveActivityByForeignID("bob:123")
+_, err := feed.RemoveActivityByForeignID(ctx, "bob:123")
if err != nil {
// ...
}
@@ -319,7 +324,7 @@ if err != nil {
### Following another feed
```go
-_, err := feed.Follow(anotherFeed)
+_, err := feed.Follow(ctx, anotherFeed)
if err != nil {
// ...
}
@@ -332,7 +337,8 @@ Beware that it's possible to follow only flat feeds.
You can pass options to the `Follow` method. For example:
```go
-_, err := feed.Follow(anotherFeed,
+_, err := feed.Follow(ctx,
+ anotherFeed,
stream.WithFollowFeedActivityCopyLimit(15),
...,
)
@@ -345,7 +351,7 @@ _, err := feed.Follow(anotherFeed,
Get the feeds that a feed is following:
```go
-resp, err := feed.GetFollowing()
+resp, err := feed.GetFollowing(ctx)
if err != nil {
// ...
}
@@ -360,6 +366,7 @@ You can pass options to `GetFollowing`:
```go
resp, err := feed.GetFollowing(
+ ctx,
stream.WithFollowingLimit(5),
...,
)
@@ -368,7 +375,7 @@ resp, err := feed.GetFollowing(
#### Followers
```go
-resp, err := flat.GetFollowers()
+resp, err := flat.GetFollowers(ctx)
if err != nil {
// ...
}
@@ -386,6 +393,7 @@ You can pass options to `GetFollowers`:
```go
resp, err := feed.GetFollowing(
+ ctx,
stream.WithFollowersLimit(5),
...,
)
@@ -394,7 +402,7 @@ resp, err := feed.GetFollowing(
### Unfollowing a feed
```go
-_, err := flat.Unfollow(anotherFeed)
+_, err := flat.Unfollow(ctx, anotherFeed)
if err != nil {
// ...
}
@@ -403,7 +411,8 @@ if err != nil {
You can pass options to `Unfollow`:
```go
-_, err := flat.Unfollow(anotherFeed,
+_, err := flat.Unfollow(ctx,
+ anotherFeed,
stream.WithUnfollowKeepHistory(true),
...,
)
@@ -416,7 +425,7 @@ Remove all old targets and set new ones (replace):
```go
newTargets := []stream.Feed{f1, f2}
-_, err := feed.UpdateToTargets(activity, stream.WithToTargetsNew(newTargets...))
+_, err := feed.UpdateToTargets(ctx, activity, stream.WithToTargetsNew(newTargets...))
if err != nil {
// ...
}
@@ -429,6 +438,7 @@ add := []stream.Feed{target1, target2}
remove := []stream.Feed{oldTarget1, oldTarget2}
_, err := feed.UpdateToTargets(
+ ctx,
activity,
stream.WithToTargetsAdd(add),
stream.WithToTargetsRemove(remove),
@@ -445,8 +455,8 @@ Note: you can't mix `stream.WithToTargetsNew` with `stream.WithToTargetsAdd` or
You can add the same activities to multiple feeds at once with the `(*Client).AddToMany` method ([docs](https://getstream.io/docs_rest/#add_to_many)):
```go
-_, err := client.AddToMany(activity,
- feed1, feed2, ...,
+_, err := client.AddToMany(ctx,
+ activity, feed1, feed2, ...,
)
if err != nil {
// ...
@@ -463,7 +473,7 @@ relationships := []stream.FollowRelationship{
...,
}
-_, err := client.FollowMany(relationships)
+_, err := client.FollowMany(ctx, relationships)
if err != nil {
// ...
}
@@ -515,7 +525,7 @@ event := stream.EngagementEvent{}.
WithLocation("homepage")
// Track the event(s)
-_, err := analytics.TrackEngagement(event)
+_, err := analytics.TrackEngagement(ctx, event)
if err != nil {
// ...
}
@@ -533,7 +543,7 @@ imp := stream.ImpressionEventData{}.
WithLocation("storepage")
// Track the events
-_, err := analytics.TrackImpression(imp)
+_, err := analytics.TrackImpression(ctx, imp)
if err != nil {
// ...
}
@@ -590,7 +600,7 @@ data := map[string]interface{}{
"source_feed_slug": "timeline",
"target_feed_slug": "user",
}
-resp, err = personalization.Get("follow_recommendations", data)
+resp, err = personalization.Get(ctx, "follow_recommendations", data)
if err != nil {
// ...
}
@@ -618,25 +628,25 @@ object := stream.CollectionObject{
"location": "North America",
},
}
-_, err = collections.Upsert("picture", object)
+_, err = collections.Upsert(ctx, "picture", object)
if err != nil {
// ...
}
// Get the data from the "picture" collection for ID "123" and "456"
-objects, err := collections.Select("picture", "123", "456")
+objects, err := collections.Select(ctx, "picture", "123", "456")
if err != nil {
// ...
}
// Delete the data from the "picture" collection for picture with ID "123"
-_, err = collections.Delete("picture", "123")
+_, err = collections.Delete(ctx, "picture", "123")
if err != nil {
// ...
}
// Get a single collection object from the "pictures" collection with ID "123"
-_, err = collections.Get("pictures", "123")
+_, err = collections.Get(ctx, "pictures", "123")
if err != nil {
// ...
}
@@ -662,7 +672,7 @@ user := stream.User{
},
}
-insertedUser, err := users.Add(user, false)
+insertedUser, err := users.Add(ctx, user, false)
if err != nil {
// ...
}
@@ -672,12 +682,12 @@ newUserData :=map[string]interface{}{
"age": 7,
}
-updatedUser, err := users.Update("123", newUserData)
+updatedUser, err := users.Update(ctx, "123", newUserData)
if err != nil {
// ...
}
-_, err = users.Delete("123")
+_, err = users.Delete(ctx, "123")
if err != nil {
// ...
}
@@ -706,7 +716,7 @@ r := stream.AddReactionRequestObject{
TargetFeeds: []string{"user:bob", "timeline:alice"},
}
-comment, err := reactions.Add(r)
+comment, err := reactions.Add(ctx, r)
if err != nil {
// ...
}
@@ -716,13 +726,13 @@ like := stream.AddReactionRequestObject{
UserID: "456",
}
-childReaction, err := reactions.AddChild(comment.ID, like)
+childReaction, err := reactions.AddChild(ctx, comment.ID, like)
if err != nil {
// ...
}
// If we fetch the "comment" reaction now, it will have the child reaction(s) present.
-parent, err := reactions.Get(comment.ID)
+parent, err := reactions.Get(ctx, comment.ID)
if err != nil {
// ...
}
@@ -732,14 +742,15 @@ for kind, children := range parent.ChildrenReactions {
}
// update the target feeds for the `comment` reaction
-updatedReaction, err := reactions.Update(comment.ID, nil, []string{"timeline:jeff"})
+updatedReaction, err := reactions.Update(ctx, comment.ID, nil, []string{"timeline:jeff"})
if err != nil {
// ...
}
// get all reactions for the activity "87a9eec0-fd5f-11e8-8080-80013fed2f5b",
// paginated 5 at a time, including the activity data
-response, err := reactions.Filter(stream.ByActivityID("87a9eec0-fd5f-11e8-8080-80013fed2f5b"),
+response, err := reactions.Filter(ctx,
+ stream.ByActivityID("87a9eec0-fd5f-11e8-8080-80013fed2f5b"),
stream.WithLimit(5),
stream.WithActivityData())
if err != nil {
@@ -754,13 +765,13 @@ for _, reaction := range response.Results{
}
//get the next page of reactions
-response, err = reactions.GetNextPageFilteredReactions(response)
+response, err = reactions.GetNextPageFilteredReactions(ctx, response)
if err != nil {
// ...
}
// get all likes by user "123"
-response, err = reactions.Filter(stream.ByUserID("123").ByKind("like"))
+response, err = reactions.Filter(ctx, stream.ByUserID("123").ByKind("like"))
if err != nil {
// ...
}
@@ -783,7 +794,7 @@ u := stream.User{
}
// We add a user
-user, err := client.Users().Add(u, true)
+user, err := client.Users().Add(ctx, u, true)
if err != nil {
// ...
}
@@ -797,7 +808,7 @@ c := stream.CollectionObject{
}
// We add a collection object
-collectionObject, err := client.Collections().Add("picture", c)
+collectionObject, err := client.Collections().Add(ctx, "picture", c)
if err != nil {
// ...
}
@@ -813,19 +824,19 @@ act := stream.Activity{
// We add the activity to the user's feed
feed, _ := client.FlatFeed("user", "123")
-_, err = feed.AddActivity(act)
+_, err = feed.AddActivity(ctx, act)
if err != nil {
// ...
}
-result, err := feed.GetActivities()
+result, err := feed.GetActivities(ctx)
if err != nil {
// ...
}
fmt.Println(result.Results[0].Actor) // Will output the user reference
fmt.Println(result.Results[0].Object) // Will output the collection reference
-enrichedResult, err := feed.GetEnrichedActivities()
+enrichedResult, err := feed.GetEnrichedActivities(ctx)
if err != nil {
// ...
}
diff --git a/aggregated_feed.go b/aggregated_feed.go
index 402ff48..0e2b5f2 100644
--- a/aggregated_feed.go
+++ b/aggregated_feed.go
@@ -1,6 +1,7 @@
package stream
import (
+ "context"
"encoding/json"
)
@@ -12,8 +13,8 @@ type AggregatedFeed struct {
// GetActivities requests and retrieves the activities and groups for the
// aggregated feed.
-func (f *AggregatedFeed) GetActivities(opts ...GetActivitiesOption) (*AggregatedFeedResponse, error) {
- body, err := f.client.getActivities(f, opts...)
+func (f *AggregatedFeed) GetActivities(ctx context.Context, opts ...GetActivitiesOption) (*AggregatedFeedResponse, error) {
+ body, err := f.client.getActivities(ctx, f, opts...)
if err != nil {
return nil, err
}
@@ -26,24 +27,24 @@ func (f *AggregatedFeed) GetActivities(opts ...GetActivitiesOption) (*Aggregated
// GetActivitiesWithRanking returns the activities and groups for the given AggregatedFeed,
// using the provided ranking method.
-func (f *AggregatedFeed) GetActivitiesWithRanking(ranking string, opts ...GetActivitiesOption) (*AggregatedFeedResponse, error) {
- return f.GetActivities(append(opts, withActivitiesRanking(ranking))...)
+func (f *AggregatedFeed) GetActivitiesWithRanking(ctx context.Context, ranking string, opts ...GetActivitiesOption) (*AggregatedFeedResponse, error) {
+ return f.GetActivities(ctx, append(opts, withActivitiesRanking(ranking))...)
}
// GetNextPageActivities returns the activities for the given AggregatedFeed at the "next" page
// of a previous *AggregatedFeedResponse response, if any.
-func (f *AggregatedFeed) GetNextPageActivities(resp *AggregatedFeedResponse) (*AggregatedFeedResponse, error) {
+func (f *AggregatedFeed) GetNextPageActivities(ctx context.Context, resp *AggregatedFeedResponse) (*AggregatedFeedResponse, error) {
opts, err := resp.parseNext()
if err != nil {
return nil, err
}
- return f.GetActivities(opts...)
+ return f.GetActivities(ctx, opts...)
}
// GetEnrichedActivities requests and retrieves the enriched activities and groups for the
// aggregated feed.
-func (f *AggregatedFeed) GetEnrichedActivities(opts ...GetActivitiesOption) (*EnrichedAggregatedFeedResponse, error) {
- body, err := f.client.getEnrichedActivities(f, opts...)
+func (f *AggregatedFeed) GetEnrichedActivities(ctx context.Context, opts ...GetActivitiesOption) (*EnrichedAggregatedFeedResponse, error) {
+ body, err := f.client.getEnrichedActivities(ctx, f, opts...)
if err != nil {
return nil, err
}
@@ -56,16 +57,16 @@ func (f *AggregatedFeed) GetEnrichedActivities(opts ...GetActivitiesOption) (*En
// GetNextPageEnrichedActivities returns the enriched activities for the given AggregatedFeed at the "next" page
// of a previous *EnrichedAggregatedFeedResponse response, if any.
-func (f *AggregatedFeed) GetNextPageEnrichedActivities(resp *EnrichedAggregatedFeedResponse) (*EnrichedAggregatedFeedResponse, error) {
+func (f *AggregatedFeed) GetNextPageEnrichedActivities(ctx context.Context, resp *EnrichedAggregatedFeedResponse) (*EnrichedAggregatedFeedResponse, error) {
opts, err := resp.parseNext()
if err != nil {
return nil, err
}
- return f.GetEnrichedActivities(opts...)
+ return f.GetEnrichedActivities(ctx, opts...)
}
// GetEnrichedActivitiesWithRanking returns the enriched activities and groups for the given AggregatedFeed,
// using the provided ranking method.
-func (f *AggregatedFeed) GetEnrichedActivitiesWithRanking(ranking string, opts ...GetActivitiesOption) (*EnrichedAggregatedFeedResponse, error) {
- return f.GetEnrichedActivities(append(opts, withActivitiesRanking(ranking))...)
+func (f *AggregatedFeed) GetEnrichedActivitiesWithRanking(ctx context.Context, ranking string, opts ...GetActivitiesOption) (*EnrichedAggregatedFeedResponse, error) {
+ return f.GetEnrichedActivities(ctx, append(opts, withActivitiesRanking(ranking))...)
}
diff --git a/aggregated_feed_test.go b/aggregated_feed_test.go
index 31b293b..9fd2cc4 100644
--- a/aggregated_feed_test.go
+++ b/aggregated_feed_test.go
@@ -1,6 +1,7 @@
package stream_test
import (
+ "context"
"fmt"
"net/http"
"testing"
@@ -12,6 +13,7 @@ import (
)
func TestAggregatedFeedGetActivities(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
aggregated, _ := newAggregatedFeedWithUserID(client, "123")
testCases := []struct {
@@ -36,55 +38,56 @@ func TestAggregatedFeedGetActivities(t *testing.T) {
}
for _, tc := range testCases {
- _, err := aggregated.GetActivities(tc.opts...)
+ _, err := aggregated.GetActivities(ctx, tc.opts...)
assert.NoError(t, err)
testRequest(t, requester.req, http.MethodGet, tc.url, "")
- _, err = aggregated.GetActivitiesWithRanking("popularity", tc.opts...)
+ _, err = aggregated.GetActivitiesWithRanking(ctx, "popularity", tc.opts...)
testRequest(t, requester.req, http.MethodGet, fmt.Sprintf("%s&ranking=popularity", tc.url), "")
assert.NoError(t, err)
- _, err = aggregated.GetEnrichedActivities(tc.opts...)
+ _, err = aggregated.GetEnrichedActivities(ctx, tc.opts...)
assert.NoError(t, err)
testRequest(t, requester.req, http.MethodGet, tc.enrichedURL, "")
- _, err = aggregated.GetEnrichedActivitiesWithRanking("popularity", tc.opts...)
+ _, err = aggregated.GetEnrichedActivitiesWithRanking(ctx, "popularity", tc.opts...)
testRequest(t, requester.req, http.MethodGet, fmt.Sprintf("%s&ranking=popularity", tc.enrichedURL), "")
assert.NoError(t, err)
}
}
func TestAggregatedFeedGetNextPageActivities(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
aggregated, _ := newAggregatedFeedWithUserID(client, "123")
requester.resp = `{"next":"/api/v1.0/feed/aggregated/123/?id_lt=78c1a709-aff2-11e7-b3a7-a45e60be7d3b&limit=25"}`
- resp, err := aggregated.GetActivities()
+ resp, err := aggregated.GetActivities(ctx)
require.NoError(t, err)
- _, err = aggregated.GetNextPageActivities(resp)
+ _, err = aggregated.GetNextPageActivities(ctx, resp)
testRequest(t, requester.req, http.MethodGet, "https://api.stream-io-api.com/api/v1.0/feed/aggregated/123/?api_key=key&id_lt=78c1a709-aff2-11e7-b3a7-a45e60be7d3b&limit=25", "")
require.NoError(t, err)
requester.resp = `{"next":"/api/v1.0/enrich/feed/aggregated/123/?id_lt=78c1a709-aff2-11e7-b3a7-a45e60be7d3b&limit=25"}`
- enrichedResp, err := aggregated.GetEnrichedActivities()
+ enrichedResp, err := aggregated.GetEnrichedActivities(ctx)
require.NoError(t, err)
- _, err = aggregated.GetNextPageEnrichedActivities(enrichedResp)
+ _, err = aggregated.GetNextPageEnrichedActivities(ctx, enrichedResp)
testRequest(t, requester.req, http.MethodGet, "https://api.stream-io-api.com/api/v1.0/enrich/feed/aggregated/123/?api_key=key&id_lt=78c1a709-aff2-11e7-b3a7-a45e60be7d3b&limit=25", "")
require.NoError(t, err)
requester.resp = `{"next":123}`
- _, err = aggregated.GetActivities()
+ _, err = aggregated.GetActivities(ctx)
require.Error(t, err)
requester.resp = `{"next":"123"}`
- resp, err = aggregated.GetActivities()
+ resp, err = aggregated.GetActivities(ctx)
require.NoError(t, err)
- _, err = aggregated.GetNextPageActivities(resp)
+ _, err = aggregated.GetNextPageActivities(ctx, resp)
require.Error(t, err)
requester.resp = `{"next":"?q=a%"}`
- resp, err = aggregated.GetActivities()
+ resp, err = aggregated.GetActivities(ctx)
require.NoError(t, err)
- _, err = aggregated.GetNextPageActivities(resp)
+ _, err = aggregated.GetNextPageActivities(ctx, resp)
require.Error(t, err)
}
diff --git a/analytics.go b/analytics.go
index 38f525c..42269b4 100644
--- a/analytics.go
+++ b/analytics.go
@@ -1,6 +1,7 @@
package stream
import (
+ "context"
"encoding/json"
)
@@ -11,18 +12,18 @@ type AnalyticsClient struct {
}
// TrackEngagement is used to send and track analytics EngagementEvents.
-func (c *AnalyticsClient) TrackEngagement(events ...EngagementEvent) (*BaseResponse, error) {
+func (c *AnalyticsClient) TrackEngagement(ctx context.Context, events ...EngagementEvent) (*BaseResponse, error) {
endpoint := c.client.makeEndpoint("engagement/")
data := map[string]interface{}{
"content_list": events,
}
- return decode(c.client.post(endpoint, data, c.client.authenticator.analyticsAuth))
+ return decode(c.client.post(ctx, endpoint, data, c.client.authenticator.analyticsAuth))
}
// TrackImpression is used to send and track analytics ImpressionEvents.
-func (c *AnalyticsClient) TrackImpression(eventsData ImpressionEventsData) (*BaseResponse, error) {
+func (c *AnalyticsClient) TrackImpression(ctx context.Context, eventsData ImpressionEventsData) (*BaseResponse, error) {
endpoint := c.client.makeEndpoint("impression/")
- return decode(c.client.post(endpoint, eventsData, c.client.authenticator.analyticsAuth))
+ return decode(c.client.post(ctx, endpoint, eventsData, c.client.authenticator.analyticsAuth))
}
// RedirectAndTrack is used to send and track analytics ImpressionEvents. It tracks
diff --git a/analytics_test.go b/analytics_test.go
index ce34044..9b804f6 100644
--- a/analytics_test.go
+++ b/analytics_test.go
@@ -1,6 +1,7 @@
package stream_test
import (
+ "context"
"net/http"
"net/url"
"testing"
@@ -12,6 +13,7 @@ import (
)
func TestAnalyticsTrackEngagement(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
analytics := client.Analytics()
event1 := stream.EngagementEvent{}.
@@ -33,7 +35,7 @@ func TestAnalyticsTrackEngagement(t *testing.T) {
stream.NewEventFeature("size", "xxl"),
)
- _, err := analytics.TrackEngagement(event1, event2)
+ _, err := analytics.TrackEngagement(ctx, event1, event2)
require.NoError(t, err)
expectedURL := "https://analytics.stream-io-api.com/analytics/v1.0/engagement/?api_key=key"
expectedBody := `{"content_list":[{"boost":10,"content":"abcdef","feed_id":"timeline:123","label":"click","location":"hawaii","position":42,"user_data":{"alias":"John Doe","id":12345}},{"content":"aabbccdd","features":[{"group":"color","value":"red"},{"group":"size","value":"xxl"}],"feed_id":"timeline:123","label":"share","user_data":"bob"}]}`
@@ -41,6 +43,7 @@ func TestAnalyticsTrackEngagement(t *testing.T) {
}
func TestAnalyticsTrackImpression(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
analytics := client.Analytics()
imp := stream.ImpressionEventsData{}.
@@ -54,7 +57,7 @@ func TestAnalyticsTrackImpression(t *testing.T) {
WithLocation("hawaii").
WithPosition(42)
- _, err := analytics.TrackImpression(imp)
+ _, err := analytics.TrackImpression(ctx, imp)
require.NoError(t, err)
expectedURL := "https://analytics.stream-io-api.com/analytics/v1.0/impression/?api_key=key"
expectedBody := `{"content_list":["a","b","c","d"],"features":[{"group":"color","value":"red"},{"group":"size","value":"xxl"}],"feed_id":"timeline:123","location":"hawaii","position":42,"user_data":123}`
diff --git a/client.go b/client.go
index 8990a2e..4e7ece8 100644
--- a/client.go
+++ b/client.go
@@ -2,6 +2,7 @@ package stream
import (
"bytes"
+ "context"
"encoding/json"
"errors"
"fmt"
@@ -158,7 +159,7 @@ func (c *Client) GenericFeed(targetID string) (Feed, error) {
}
// AddToMany adds an activity to multiple feeds at once.
-func (c *Client) AddToMany(activity Activity, feeds ...Feed) error {
+func (c *Client) AddToMany(ctx context.Context, activity Activity, feeds ...Feed) error {
endpoint := c.makeEndpoint("feed/add_to_many/")
ids := make([]string, len(feeds))
for i := range feeds {
@@ -168,24 +169,24 @@ func (c *Client) AddToMany(activity Activity, feeds ...Feed) error {
Activity: activity,
FeedIDs: ids,
}
- _, err := c.post(endpoint, req, c.authenticator.feedAuth(resFeed, nil))
+ _, err := c.post(ctx, endpoint, req, c.authenticator.feedAuth(resFeed, nil))
return err
}
// FollowMany creates multiple follows at once.
-func (c *Client) FollowMany(relationships []FollowRelationship, opts ...FollowManyOption) error {
+func (c *Client) FollowMany(ctx context.Context, relationships []FollowRelationship, opts ...FollowManyOption) error {
endpoint := c.makeEndpoint("follow_many/")
for _, opt := range opts {
endpoint.addQueryParam(opt)
}
- _, err := c.post(endpoint, relationships, c.authenticator.feedAuth(resFollower, nil))
+ _, err := c.post(ctx, endpoint, relationships, c.authenticator.feedAuth(resFollower, nil))
return err
}
// UnfollowMany removes multiple follow relationships at once.
-func (c *Client) UnfollowMany(relationships []UnfollowRelationship) error {
+func (c *Client) UnfollowMany(ctx context.Context, relationships []UnfollowRelationship) error {
endpoint := c.makeEndpoint("unfollow_many/")
- _, err := c.post(endpoint, relationships, c.authenticator.feedAuth(resFollower, nil))
+ _, err := c.post(ctx, endpoint, relationships, c.authenticator.feedAuth(resFollower, nil))
return err
}
@@ -229,30 +230,30 @@ func (c *Client) Personalization() *PersonalizationClient {
}
// GetActivitiesByID returns activities for the current app having the given IDs.
-func (c *Client) GetActivitiesByID(ids ...string) (*GetActivitiesResponse, error) {
- return c.getAppActivities(makeRequestOption("ids", strings.Join(ids, ",")))
+func (c *Client) GetActivitiesByID(ctx context.Context, ids ...string) (*GetActivitiesResponse, error) {
+ return c.getAppActivities(ctx, makeRequestOption("ids", strings.Join(ids, ",")))
}
// GetActivitiesByForeignID returns activities for the current app having the given foreign IDs and timestamps.
-func (c *Client) GetActivitiesByForeignID(values ...ForeignIDTimePair) (*GetActivitiesResponse, error) {
+func (c *Client) GetActivitiesByForeignID(ctx context.Context, values ...ForeignIDTimePair) (*GetActivitiesResponse, error) {
foreignIDs := make([]string, len(values))
timestamps := make([]string, len(values))
for i, v := range values {
foreignIDs[i] = v.ForeignID
timestamps[i] = v.Timestamp.Format(TimeLayout)
}
- return c.getAppActivities(
+ return c.getAppActivities(ctx,
makeRequestOption("foreign_ids", strings.Join(foreignIDs, ",")),
makeRequestOption("timestamps", strings.Join(timestamps, ",")),
)
}
-func (c *Client) getAppActivities(values ...valuer) (*GetActivitiesResponse, error) {
+func (c *Client) getAppActivities(ctx context.Context, values ...valuer) (*GetActivitiesResponse, error) {
endpoint := c.makeEndpoint("activities/")
for _, v := range values {
endpoint.addQueryParam(v)
}
- data, err := c.get(endpoint, nil, c.authenticator.feedAuth(resActivities, nil))
+ data, err := c.get(ctx, endpoint, nil, c.authenticator.feedAuth(resActivities, nil))
if err != nil {
return nil, err
}
@@ -265,13 +266,13 @@ func (c *Client) getAppActivities(values ...valuer) (*GetActivitiesResponse, err
}
// GetEnrichedActivitiesByID returns enriched activities for the current app having the given IDs.
-func (c *Client) GetEnrichedActivitiesByID(ids []string, opts ...GetActivitiesOption) (*GetEnrichedActivitiesResponse, error) {
+func (c *Client) GetEnrichedActivitiesByID(ctx context.Context, ids []string, opts ...GetActivitiesOption) (*GetEnrichedActivitiesResponse, error) {
options := []GetActivitiesOption{{makeRequestOption("ids", strings.Join(ids, ","))}}
- return c.getAppEnrichedActivities(append(options, opts...)...)
+ return c.getAppEnrichedActivities(ctx, append(options, opts...)...)
}
// GetEnrichedActivitiesByForeignID returns enriched activities for the current app having the given foreign IDs and timestamps.
-func (c *Client) GetEnrichedActivitiesByForeignID(values []ForeignIDTimePair, opts ...GetActivitiesOption) (*GetEnrichedActivitiesResponse, error) {
+func (c *Client) GetEnrichedActivitiesByForeignID(ctx context.Context, values []ForeignIDTimePair, opts ...GetActivitiesOption) (*GetEnrichedActivitiesResponse, error) {
foreignIDs := make([]string, len(values))
timestamps := make([]string, len(values))
for i, v := range values {
@@ -283,15 +284,15 @@ func (c *Client) GetEnrichedActivitiesByForeignID(values []ForeignIDTimePair, op
{makeRequestOption("timestamps", strings.Join(timestamps, ","))},
}
- return c.getAppEnrichedActivities(append(options, opts...)...)
+ return c.getAppEnrichedActivities(ctx, append(options, opts...)...)
}
-func (c *Client) getAppEnrichedActivities(options ...GetActivitiesOption) (*GetEnrichedActivitiesResponse, error) {
+func (c *Client) getAppEnrichedActivities(ctx context.Context, options ...GetActivitiesOption) (*GetEnrichedActivitiesResponse, error) {
endpoint := c.makeEndpoint("enrich/activities/")
for _, v := range options {
endpoint.addQueryParam(v.requestOption)
}
- data, err := c.get(endpoint, nil, c.authenticator.feedAuth(resActivities, nil))
+ data, err := c.get(ctx, endpoint, nil, c.authenticator.feedAuth(resActivities, nil))
if err != nil {
return nil, err
}
@@ -304,26 +305,26 @@ func (c *Client) getAppEnrichedActivities(options ...GetActivitiesOption) (*GetE
}
// UpdateActivities updates existing activities.
-func (c *Client) UpdateActivities(activities ...Activity) (*BaseResponse, error) {
+func (c *Client) UpdateActivities(ctx context.Context, activities ...Activity) (*BaseResponse, error) {
req := struct {
Activities []Activity `json:"activities,omitempty"`
}{
Activities: activities,
}
endpoint := c.makeEndpoint("activities/")
- return decode(c.post(endpoint, req, c.authenticator.feedAuth(resActivities, nil)))
+ return decode(c.post(ctx, endpoint, req, c.authenticator.feedAuth(resActivities, nil)))
}
// PartialUpdateActivities performs a partial update on multiple activities with the given set and unset operations
// specified by each changeset. This returns the affected activities.
-func (c *Client) PartialUpdateActivities(changesets ...UpdateActivityRequest) (*UpdateActivitiesResponse, error) {
+func (c *Client) PartialUpdateActivities(ctx context.Context, changesets ...UpdateActivityRequest) (*UpdateActivitiesResponse, error) {
req := struct {
Activities []UpdateActivityRequest `json:"changes,omitempty"`
}{
Activities: changesets,
}
endpoint := c.makeEndpoint("activity/")
- data, err := c.post(endpoint, req, c.authenticator.feedAuth(resActivities, nil))
+ data, err := c.post(ctx, endpoint, req, c.authenticator.feedAuth(resActivities, nil))
if err != nil {
return nil, err
}
@@ -336,8 +337,8 @@ func (c *Client) PartialUpdateActivities(changesets ...UpdateActivityRequest) (*
// UpdateActivityByID performs a partial activity update with the given set and unset operations, returning the
// affected activity, on the activity with the given ID.
-func (c *Client) UpdateActivityByID(id string, set map[string]interface{}, unset []string) (*UpdateActivityResponse, error) {
- return c.updateActivity(UpdateActivityRequest{
+func (c *Client) UpdateActivityByID(ctx context.Context, id string, set map[string]interface{}, unset []string) (*UpdateActivityResponse, error) {
+ return c.updateActivity(ctx, UpdateActivityRequest{
ID: &id,
Set: set,
Unset: unset,
@@ -346,8 +347,8 @@ func (c *Client) UpdateActivityByID(id string, set map[string]interface{}, unset
// UpdateActivityByForeignID performs a partial activity update with the given set and unset operations, returning the
// affected activity, on the activity with the given foreign ID and timestamp.
-func (c *Client) UpdateActivityByForeignID(foreignID string, timestamp Time, set map[string]interface{}, unset []string) (*UpdateActivityResponse, error) {
- return c.updateActivity(UpdateActivityRequest{
+func (c *Client) UpdateActivityByForeignID(ctx context.Context, foreignID string, timestamp Time, set map[string]interface{}, unset []string) (*UpdateActivityResponse, error) {
+ return c.updateActivity(ctx, UpdateActivityRequest{
ForeignID: &foreignID,
Time: ×tamp,
Set: set,
@@ -355,9 +356,9 @@ func (c *Client) UpdateActivityByForeignID(foreignID string, timestamp Time, set
})
}
-func (c *Client) updateActivity(req UpdateActivityRequest) (*UpdateActivityResponse, error) {
+func (c *Client) updateActivity(ctx context.Context, req UpdateActivityRequest) (*UpdateActivityResponse, error) {
endpoint := c.makeEndpoint("activity/")
- data, err := c.post(endpoint, req, c.authenticator.feedAuth(resActivities, nil))
+ data, err := c.post(ctx, endpoint, req, c.authenticator.feedAuth(resActivities, nil))
if err != nil {
return nil, err
}
@@ -417,20 +418,20 @@ func (c *Client) makeEndpoint(format string, a ...interface{}) endpoint {
}
}
-func (c *Client) get(endpoint endpoint, data interface{}, authFn authFunc) ([]byte, error) {
- return c.request(http.MethodGet, endpoint, data, authFn)
+func (c *Client) get(ctx context.Context, endpoint endpoint, data interface{}, authFn authFunc) ([]byte, error) {
+ return c.request(ctx, http.MethodGet, endpoint, data, authFn)
}
-func (c *Client) post(endpoint endpoint, data interface{}, authFn authFunc) ([]byte, error) {
- return c.request(http.MethodPost, endpoint, data, authFn)
+func (c *Client) post(ctx context.Context, endpoint endpoint, data interface{}, authFn authFunc) ([]byte, error) {
+ return c.request(ctx, http.MethodPost, endpoint, data, authFn)
}
-func (c *Client) put(endpoint endpoint, data interface{}, authFn authFunc) ([]byte, error) {
- return c.request(http.MethodPut, endpoint, data, authFn)
+func (c *Client) put(ctx context.Context, endpoint endpoint, data interface{}, authFn authFunc) ([]byte, error) {
+ return c.request(ctx, http.MethodPut, endpoint, data, authFn)
}
-func (c *Client) delete(endpoint endpoint, data interface{}, authFn authFunc) ([]byte, error) {
- return c.request(http.MethodDelete, endpoint, data, authFn)
+func (c *Client) delete(ctx context.Context, endpoint endpoint, data interface{}, authFn authFunc) ([]byte, error) {
+ return c.request(ctx, http.MethodDelete, endpoint, data, authFn)
}
func (c *Client) setBaseHeaders(r *http.Request) {
@@ -438,7 +439,7 @@ func (c *Client) setBaseHeaders(r *http.Request) {
r.Header.Set("X-Stream-Client", fmt.Sprintf("stream-go2-client-%s", Version))
}
-func (c *Client) request(method string, endpoint endpoint, data interface{}, authFn authFunc) ([]byte, error) {
+func (c *Client) request(ctx context.Context, method string, endpoint endpoint, data interface{}, authFn authFunc) ([]byte, error) {
var reader io.Reader
if data != nil {
payload, err := json.Marshal(data)
@@ -448,7 +449,7 @@ func (c *Client) request(method string, endpoint endpoint, data interface{}, aut
reader = bytes.NewReader(payload)
}
- req, err := http.NewRequest(method, endpoint.String(), reader)
+ req, err := http.NewRequestWithContext(ctx, method, endpoint.String(), reader)
if err != nil {
return nil, fmt.Errorf("cannot create request: %w", err)
}
@@ -491,9 +492,9 @@ func (c *Client) request(method string, endpoint endpoint, data interface{}, aut
return body, nil
}
-func (c *Client) addActivity(feed Feed, activity Activity) (*AddActivityResponse, error) {
+func (c *Client) addActivity(ctx context.Context, feed Feed, activity Activity) (*AddActivityResponse, error) {
endpoint := c.makeEndpoint("feed/%s/%s/", feed.Slug(), feed.UserID())
- resp, err := c.post(endpoint, activity, c.authenticator.feedAuth(resFeed, feed))
+ resp, err := c.post(ctx, endpoint, activity, c.authenticator.feedAuth(resFeed, feed))
if err != nil {
return nil, err
}
@@ -504,14 +505,14 @@ func (c *Client) addActivity(feed Feed, activity Activity) (*AddActivityResponse
return &out, nil
}
-func (c *Client) addActivities(feed Feed, activities ...Activity) (*AddActivitiesResponse, error) {
+func (c *Client) addActivities(ctx context.Context, feed Feed, activities ...Activity) (*AddActivitiesResponse, error) {
reqBody := struct {
Activities []Activity `json:"activities,omitempty"`
}{
Activities: activities,
}
endpoint := c.makeEndpoint("feed/%s/%s/", feed.Slug(), feed.UserID())
- resp, err := c.post(endpoint, reqBody, c.authenticator.feedAuth(resFeed, feed))
+ resp, err := c.post(ctx, endpoint, reqBody, c.authenticator.feedAuth(resFeed, feed))
if err != nil {
return nil, err
}
@@ -522,9 +523,9 @@ func (c *Client) addActivities(feed Feed, activities ...Activity) (*AddActivitie
return &out, nil
}
-func (c *Client) removeActivityByID(feed Feed, activityID string) (*RemoveActivityResponse, error) {
+func (c *Client) removeActivityByID(ctx context.Context, feed Feed, activityID string) (*RemoveActivityResponse, error) {
endpoint := c.makeEndpoint("feed/%s/%s/%s/", feed.Slug(), feed.UserID(), activityID)
- resp, err := c.delete(endpoint, nil, c.authenticator.feedAuth(resFeed, feed))
+ resp, err := c.delete(ctx, endpoint, nil, c.authenticator.feedAuth(resFeed, feed))
if err != nil {
return nil, err
}
@@ -535,10 +536,10 @@ func (c *Client) removeActivityByID(feed Feed, activityID string) (*RemoveActivi
return &out, nil
}
-func (c *Client) removeActivityByForeignID(feed Feed, foreignID string) (*RemoveActivityResponse, error) {
+func (c *Client) removeActivityByForeignID(ctx context.Context, feed Feed, foreignID string) (*RemoveActivityResponse, error) {
endpoint := c.makeEndpoint("feed/%s/%s/%s/", feed.Slug(), feed.UserID(), foreignID)
endpoint.addQueryParam(makeRequestOption("foreign_id", 1))
- resp, err := c.delete(endpoint, nil, c.authenticator.feedAuth(resFeed, feed))
+ resp, err := c.delete(ctx, endpoint, nil, c.authenticator.feedAuth(resFeed, feed))
if err != nil {
return nil, err
}
@@ -549,35 +550,35 @@ func (c *Client) removeActivityByForeignID(feed Feed, foreignID string) (*Remove
return &out, nil
}
-func (c *Client) getActivities(feed Feed, opts ...GetActivitiesOption) ([]byte, error) {
+func (c *Client) getActivities(ctx context.Context, feed Feed, opts ...GetActivitiesOption) ([]byte, error) {
endpoint := c.makeEndpoint("feed/%s/%s/", feed.Slug(), feed.UserID())
- return c.getActivitiesInternal(endpoint, feed, opts...)
+ return c.getActivitiesInternal(ctx, endpoint, feed, opts...)
}
-func (c *Client) getEnrichedActivities(feed Feed, opts ...GetActivitiesOption) ([]byte, error) {
+func (c *Client) getEnrichedActivities(ctx context.Context, feed Feed, opts ...GetActivitiesOption) ([]byte, error) {
endpoint := c.makeEndpoint("enrich/feed/%s/%s/", feed.Slug(), feed.UserID())
- return c.getActivitiesInternal(endpoint, feed, opts...)
+ return c.getActivitiesInternal(ctx, endpoint, feed, opts...)
}
-func (c *Client) getActivitiesInternal(endpoint endpoint, feed Feed, opts ...GetActivitiesOption) ([]byte, error) {
+func (c *Client) getActivitiesInternal(ctx context.Context, endpoint endpoint, feed Feed, opts ...GetActivitiesOption) ([]byte, error) {
for _, opt := range opts {
endpoint.addQueryParam(opt)
}
- return c.get(endpoint, nil, c.authenticator.feedAuth(resFeed, feed))
+ return c.get(ctx, endpoint, nil, c.authenticator.feedAuth(resFeed, feed))
}
-func (c *Client) follow(feed Feed, opts *followFeedOptions) (*BaseResponse, error) {
+func (c *Client) follow(ctx context.Context, feed Feed, opts *followFeedOptions) (*BaseResponse, error) {
endpoint := c.makeEndpoint("feed/%s/%s/follows/", feed.Slug(), feed.UserID())
- return decode(c.post(endpoint, opts, c.authenticator.feedAuth(resFollower, feed)))
+ return decode(c.post(ctx, endpoint, opts, c.authenticator.feedAuth(resFollower, feed)))
}
-func (c *Client) getFollowers(feed Feed, opts ...FollowersOption) (*FollowersResponse, error) {
+func (c *Client) getFollowers(ctx context.Context, feed Feed, opts ...FollowersOption) (*FollowersResponse, error) {
endpoint := c.makeEndpoint("feed/%s/%s/followers/", feed.Slug(), feed.UserID())
for _, opt := range opts {
endpoint.addQueryParam(opt)
}
- resp, err := c.get(endpoint, nil, c.authenticator.feedAuth(resFollower, feed))
+ resp, err := c.get(ctx, endpoint, nil, c.authenticator.feedAuth(resFollower, feed))
if err != nil {
return nil, err
}
@@ -588,13 +589,13 @@ func (c *Client) getFollowers(feed Feed, opts ...FollowersOption) (*FollowersRes
return &out, nil
}
-func (c *Client) getFollowing(feed Feed, opts ...FollowingOption) (*FollowingResponse, error) {
+func (c *Client) getFollowing(ctx context.Context, feed Feed, opts ...FollowingOption) (*FollowingResponse, error) {
endpoint := c.makeEndpoint("feed/%s/%s/follows/", feed.Slug(), feed.UserID())
for _, opt := range opts {
endpoint.addQueryParam(opt)
}
- resp, err := c.get(endpoint, nil, c.authenticator.feedAuth(resFollower, feed))
+ resp, err := c.get(ctx, endpoint, nil, c.authenticator.feedAuth(resFollower, feed))
if err != nil {
return nil, err
}
@@ -605,16 +606,16 @@ func (c *Client) getFollowing(feed Feed, opts ...FollowingOption) (*FollowingRes
return &out, nil
}
-func (c *Client) unfollow(feed Feed, target string, opts ...UnfollowOption) (*BaseResponse, error) {
+func (c *Client) unfollow(ctx context.Context, feed Feed, target string, opts ...UnfollowOption) (*BaseResponse, error) {
endpoint := c.makeEndpoint("feed/%s/%s/follows/%s/", feed.Slug(), feed.UserID(), target)
for _, opt := range opts {
endpoint.addQueryParam(opt)
}
- return decode(c.delete(endpoint, nil, c.authenticator.feedAuth(resFollower, feed)))
+ return decode(c.delete(ctx, endpoint, nil, c.authenticator.feedAuth(resFollower, feed)))
}
-func (c *Client) followStats(feed Feed, opts ...FollowStatOption) (*FollowStatResponse, error) {
+func (c *Client) followStats(ctx context.Context, feed Feed, opts ...FollowStatOption) (*FollowStatResponse, error) {
endpoint := c.makeEndpoint("stats/follow/")
endpoint.addQueryParam(makeRequestOption("followers", feed.ID()))
endpoint.addQueryParam(makeRequestOption("following", feed.ID()))
@@ -622,7 +623,7 @@ func (c *Client) followStats(feed Feed, opts ...FollowStatOption) (*FollowStatRe
endpoint.addQueryParam(opt)
}
- resp, err := c.get(endpoint, nil, c.authenticator.feedAuth(resFollower, nil))
+ resp, err := c.get(ctx, endpoint, nil, c.authenticator.feedAuth(resFollower, nil))
if err != nil {
return nil, err
}
@@ -633,7 +634,7 @@ func (c *Client) followStats(feed Feed, opts ...FollowStatOption) (*FollowStatRe
return &out, nil
}
-func (c *Client) updateToTargets(feed Feed, activity Activity, opts ...UpdateToTargetsOption) (*UpdateToTargetsResponse, error) {
+func (c *Client) updateToTargets(ctx context.Context, feed Feed, activity Activity, opts ...UpdateToTargetsOption) (*UpdateToTargetsResponse, error) {
endpoint := c.makeEndpoint("feed_targets/%s/%s/activity_to_targets/", feed.Slug(), feed.UserID())
req := &updateToTargetsRequest{
@@ -644,7 +645,7 @@ func (c *Client) updateToTargets(feed Feed, activity Activity, opts ...UpdateToT
opt(req)
}
- resp, err := c.post(endpoint, req, c.authenticator.feedAuth(resFeedTargets, feed))
+ resp, err := c.post(ctx, endpoint, req, c.authenticator.feedAuth(resFeedTargets, feed))
if err != nil {
return nil, err
}
diff --git a/client_internal_test.go b/client_internal_test.go
index 54f7dc2..5cccb86 100644
--- a/client_internal_test.go
+++ b/client_internal_test.go
@@ -1,6 +1,7 @@
package stream
import (
+ "context"
"fmt"
"io"
"net/http"
@@ -193,6 +194,7 @@ func (r requester) Do(*http.Request) (*http.Response, error) {
}
func Test_requestErrors(t *testing.T) {
+ ctx := context.Background()
testCases := []struct {
data interface{}
method string
@@ -236,7 +238,7 @@ func Test_requestErrors(t *testing.T) {
for _, tc := range testCases {
c := &Client{requester: tc.requester}
- _, err := c.request(tc.method, endpoint{url: &url.URL{}, query: url.Values{}}, tc.data, tc.authFn)
+ _, err := c.request(ctx, tc.method, endpoint{url: &url.URL{}, query: url.Values{}}, tc.data, tc.authFn)
require.Error(t, err)
assert.Equal(t, tc.expected.Error(), err.Error())
}
diff --git a/client_test.go b/client_test.go
index 68c7da1..3e34028 100644
--- a/client_test.go
+++ b/client_test.go
@@ -1,6 +1,7 @@
package stream_test
import (
+ "context"
"net/http"
"strconv"
"testing"
@@ -14,11 +15,12 @@ import (
)
func TestHeaders(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
feed, err := client.FlatFeed("user", "123")
require.NoError(t, err)
- _, err = feed.GetActivities()
+ _, err = feed.GetActivities(ctx)
require.NoError(t, err)
assert.Equal(t, "application/json", requester.req.Header.Get("content-type"))
assert.Regexp(t, "^stream-go2-client-v[0-9\\.]+$", requester.req.Header.Get("x-stream-client"))
@@ -27,12 +29,13 @@ func TestHeaders(t *testing.T) {
func TestAddToMany(t *testing.T) {
var (
client, requester = newClient(t)
+ ctx = context.Background()
activity = stream.Activity{Actor: "bob", Verb: "like", Object: "cake"}
flat, _ = newFlatFeedWithUserID(client, "123")
aggregated, _ = newAggregatedFeedWithUserID(client, "123")
)
- err := client.AddToMany(activity, flat, aggregated)
+ err := client.AddToMany(ctx, activity, flat, aggregated)
require.NoError(t, err)
body := `{"activity":{"actor":"bob","object":"cake","verb":"like"},"feeds":["flat:123","aggregated:123"]}`
testRequest(t, requester.req, http.MethodPost, "https://api.stream-io-api.com/api/v1.0/feed/add_to_many/?api_key=key", body)
@@ -41,6 +44,7 @@ func TestAddToMany(t *testing.T) {
func TestFollowMany(t *testing.T) {
var (
client, requester = newClient(t)
+ ctx = context.Background()
relationships = make([]stream.FollowRelationship, 3)
flat, _ = newFlatFeedWithUserID(client, "123")
)
@@ -50,12 +54,12 @@ func TestFollowMany(t *testing.T) {
relationships[i] = stream.NewFollowRelationship(other, flat)
}
- err := client.FollowMany(relationships)
+ err := client.FollowMany(ctx, relationships)
require.NoError(t, err)
body := `[{"source":"aggregated:0","target":"flat:123"},{"source":"aggregated:1","target":"flat:123"},{"source":"aggregated:2","target":"flat:123"}]`
testRequest(t, requester.req, http.MethodPost, "https://api.stream-io-api.com/api/v1.0/follow_many/?api_key=key", body)
- err = client.FollowMany(relationships, stream.WithFollowManyActivityCopyLimit(500))
+ err = client.FollowMany(ctx, relationships, stream.WithFollowManyActivityCopyLimit(500))
require.NoError(t, err)
body = `[{"source":"aggregated:0","target":"flat:123"},{"source":"aggregated:1","target":"flat:123"},{"source":"aggregated:2","target":"flat:123"}]`
testRequest(t, requester.req, http.MethodPost, "https://api.stream-io-api.com/api/v1.0/follow_many/?activity_copy_limit=500&api_key=key", body)
@@ -64,6 +68,7 @@ func TestFollowMany(t *testing.T) {
func TestFollowManyActivityCopyLimit(t *testing.T) {
var (
client, requester = newClient(t)
+ ctx = context.Background()
relationships = make([]stream.FollowRelationship, 3)
flat, _ = newFlatFeedWithUserID(client, "123")
)
@@ -73,12 +78,12 @@ func TestFollowManyActivityCopyLimit(t *testing.T) {
relationships[i] = stream.NewFollowRelationship(other, flat, stream.WithFollowRelationshipActivityCopyLimit(i))
}
- err := client.FollowMany(relationships)
+ err := client.FollowMany(ctx, relationships)
require.NoError(t, err)
body := `[{"source":"aggregated:0","target":"flat:123","activity_copy_limit":0},{"source":"aggregated:1","target":"flat:123","activity_copy_limit":1},{"source":"aggregated:2","target":"flat:123","activity_copy_limit":2}]`
testRequest(t, requester.req, http.MethodPost, "https://api.stream-io-api.com/api/v1.0/follow_many/?api_key=key", body)
- err = client.FollowMany(relationships, stream.WithFollowManyActivityCopyLimit(123))
+ err = client.FollowMany(ctx, relationships, stream.WithFollowManyActivityCopyLimit(123))
require.NoError(t, err)
body = `[{"source":"aggregated:0","target":"flat:123","activity_copy_limit":0},{"source":"aggregated:1","target":"flat:123","activity_copy_limit":1},{"source":"aggregated:2","target":"flat:123","activity_copy_limit":2}]`
testRequest(t, requester.req, http.MethodPost, "https://api.stream-io-api.com/api/v1.0/follow_many/?activity_copy_limit=123&api_key=key", body)
@@ -87,6 +92,7 @@ func TestFollowManyActivityCopyLimit(t *testing.T) {
func TestUnfollowMany(t *testing.T) {
var (
client, requester = newClient(t)
+ ctx = context.Background()
relationships = make([]stream.UnfollowRelationship, 3)
)
for i := range relationships {
@@ -102,18 +108,20 @@ func TestUnfollowMany(t *testing.T) {
relationships[i] = stream.NewUnfollowRelationship(src, tgt, options...)
}
- err := client.UnfollowMany(relationships)
+ err := client.UnfollowMany(ctx, relationships)
require.NoError(t, err)
body := `[{"source":"src:0","target":"tgt:0","keep_history":true},{"source":"src:1","target":"tgt:1","keep_history":false},{"source":"src:2","target":"tgt:2","keep_history":true}]`
testRequest(t, requester.req, http.MethodPost, "https://api.stream-io-api.com/api/v1.0/unfollow_many/?api_key=key", body)
}
func TestGetActivities(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
- _, err := client.GetActivitiesByID("foo", "bar", "baz")
+ _, err := client.GetActivitiesByID(ctx, "foo", "bar", "baz")
require.NoError(t, err)
testRequest(t, requester.req, http.MethodGet, "https://api.stream-io-api.com/api/v1.0/activities/?api_key=key&ids=foo%2Cbar%2Cbaz", "")
_, err = client.GetActivitiesByForeignID(
+ ctx,
stream.NewForeignIDTimePair("foo", stream.Time{}),
stream.NewForeignIDTimePair("bar", stream.Time{Time: time.Time{}.Add(time.Second)}),
)
@@ -122,11 +130,13 @@ func TestGetActivities(t *testing.T) {
}
func TestGetEnrichedActivities(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
- _, err := client.GetEnrichedActivitiesByID([]string{"foo", "bar", "baz"}, stream.WithEnrichReactionCounts())
+ _, err := client.GetEnrichedActivitiesByID(ctx, []string{"foo", "bar", "baz"}, stream.WithEnrichReactionCounts())
require.NoError(t, err)
testRequest(t, requester.req, http.MethodGet, "https://api.stream-io-api.com/api/v1.0/enrich/activities/?api_key=key&ids=foo%2Cbar%2Cbaz&withReactionCounts=true", "")
_, err = client.GetEnrichedActivitiesByForeignID(
+ ctx,
[]stream.ForeignIDTimePair{
stream.NewForeignIDTimePair("foo", stream.Time{}),
stream.NewForeignIDTimePair("bar", stream.Time{Time: time.Time{}.Add(time.Second)}),
@@ -138,28 +148,31 @@ func TestGetEnrichedActivities(t *testing.T) {
}
func TestUpdateActivityByID(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
- _, err := client.UpdateActivityByID("abcdef", map[string]interface{}{"foo.bar": "baz", "popularity": 42, "color": map[string]interface{}{"hex": "FF0000", "rgb": "255,0,0"}}, []string{"a", "b", "c"})
+ _, err := client.UpdateActivityByID(ctx, "abcdef", map[string]interface{}{"foo.bar": "baz", "popularity": 42, "color": map[string]interface{}{"hex": "FF0000", "rgb": "255,0,0"}}, []string{"a", "b", "c"})
require.NoError(t, err)
body := `{"id":"abcdef","set":{"color":{"hex":"FF0000","rgb":"255,0,0"},"foo.bar":"baz","popularity":42},"unset":["a","b","c"]}`
testRequest(t, requester.req, http.MethodPost, "https://api.stream-io-api.com/api/v1.0/activity/?api_key=key", body)
- _, err = client.UpdateActivityByID("abcdef", map[string]interface{}{"foo.bar": "baz", "popularity": 42, "color": map[string]interface{}{"hex": "FF0000", "rgb": "255,0,0"}}, nil)
+ _, err = client.UpdateActivityByID(ctx, "abcdef", map[string]interface{}{"foo.bar": "baz", "popularity": 42, "color": map[string]interface{}{"hex": "FF0000", "rgb": "255,0,0"}}, nil)
require.NoError(t, err)
body = `{"id":"abcdef","set":{"color":{"hex":"FF0000","rgb":"255,0,0"},"foo.bar":"baz","popularity":42}}`
testRequest(t, requester.req, http.MethodPost, "https://api.stream-io-api.com/api/v1.0/activity/?api_key=key", body)
- _, err = client.UpdateActivityByID("abcdef", nil, []string{"a", "b", "c"})
+ _, err = client.UpdateActivityByID(ctx, "abcdef", nil, []string{"a", "b", "c"})
require.NoError(t, err)
body = `{"id":"abcdef","unset":["a","b","c"]}`
testRequest(t, requester.req, http.MethodPost, "https://api.stream-io-api.com/api/v1.0/activity/?api_key=key", body)
}
func TestPartialUpdateActivities(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
_, err := client.PartialUpdateActivities(
+ ctx,
stream.NewUpdateActivityRequestByID(
"abcdef",
map[string]interface{}{"foo.bar": "baz"},
@@ -177,6 +190,7 @@ func TestPartialUpdateActivities(t *testing.T) {
tt, _ := time.Parse(stream.TimeLayout, "2006-01-02T15:04:05.999999")
_, err = client.PartialUpdateActivities(
+ ctx,
stream.NewUpdateActivityRequestByForeignID(
"abcdef:123",
stream.Time{Time: tt},
@@ -196,21 +210,22 @@ func TestPartialUpdateActivities(t *testing.T) {
}
func TestUpdateActivityByForeignID(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
tt := stream.Time{Time: time.Date(2018, 6, 24, 11, 28, 0, 0, time.UTC)}
- _, err := client.UpdateActivityByForeignID("fid:123", tt, map[string]interface{}{"foo.bar": "baz", "popularity": 42, "color": map[string]interface{}{"hex": "FF0000", "rgb": "255,0,0"}}, []string{"a", "b", "c"})
+ _, err := client.UpdateActivityByForeignID(ctx, "fid:123", tt, map[string]interface{}{"foo.bar": "baz", "popularity": 42, "color": map[string]interface{}{"hex": "FF0000", "rgb": "255,0,0"}}, []string{"a", "b", "c"})
require.NoError(t, err)
body := `{"foreign_id":"fid:123","time":"2018-06-24T11:28:00","set":{"color":{"hex":"FF0000","rgb":"255,0,0"},"foo.bar":"baz","popularity":42},"unset":["a","b","c"]}`
testRequest(t, requester.req, http.MethodPost, "https://api.stream-io-api.com/api/v1.0/activity/?api_key=key", body)
- _, err = client.UpdateActivityByForeignID("fid:123", tt, map[string]interface{}{"foo.bar": "baz", "popularity": 42, "color": map[string]interface{}{"hex": "FF0000", "rgb": "255,0,0"}}, nil)
+ _, err = client.UpdateActivityByForeignID(ctx, "fid:123", tt, map[string]interface{}{"foo.bar": "baz", "popularity": 42, "color": map[string]interface{}{"hex": "FF0000", "rgb": "255,0,0"}}, nil)
require.NoError(t, err)
body = `{"foreign_id":"fid:123","time":"2018-06-24T11:28:00","set":{"color":{"hex":"FF0000","rgb":"255,0,0"},"foo.bar":"baz","popularity":42}}`
testRequest(t, requester.req, http.MethodPost, "https://api.stream-io-api.com/api/v1.0/activity/?api_key=key", body)
- _, err = client.UpdateActivityByForeignID("fid:123", tt, nil, []string{"a", "b", "c"})
+ _, err = client.UpdateActivityByForeignID(ctx, "fid:123", tt, nil, []string{"a", "b", "c"})
require.NoError(t, err)
body = `{"foreign_id":"fid:123","time":"2018-06-24T11:28:00","unset":["a","b","c"]}`
testRequest(t, requester.req, http.MethodPost, "https://api.stream-io-api.com/api/v1.0/activity/?api_key=key", body)
diff --git a/collections.go b/collections.go
index 4c0c5d5..00c277b 100644
--- a/collections.go
+++ b/collections.go
@@ -1,6 +1,7 @@
package stream
import (
+ "context"
"encoding/json"
"errors"
"fmt"
@@ -13,7 +14,7 @@ type CollectionsClient struct {
}
// Upsert creates new or updates existing objects for the given collection's name.
-func (c *CollectionsClient) Upsert(collection string, objects ...CollectionObject) (*BaseResponse, error) {
+func (c *CollectionsClient) Upsert(ctx context.Context, collection string, objects ...CollectionObject) (*BaseResponse, error) {
if collection == "" {
return nil, errors.New("collection name required")
}
@@ -23,12 +24,12 @@ func (c *CollectionsClient) Upsert(collection string, objects ...CollectionObjec
collection: objects,
},
}
- return decode(c.client.post(endpoint, data, c.client.authenticator.collectionsAuth))
+ return decode(c.client.post(ctx, endpoint, data, c.client.authenticator.collectionsAuth))
}
// Select returns a list of CollectionObjects for the given collection name
// having the given IDs.
-func (c *CollectionsClient) Select(collection string, ids ...string) (*GetCollectionResponse, error) {
+func (c *CollectionsClient) Select(ctx context.Context, collection string, ids ...string) (*GetCollectionResponse, error) {
if collection == "" {
return nil, errors.New("collection name required")
}
@@ -38,7 +39,7 @@ func (c *CollectionsClient) Select(collection string, ids ...string) (*GetCollec
}
endpoint := c.client.makeEndpoint("collections/")
endpoint.addQueryParam(makeRequestOption("foreign_ids", strings.Join(foreignIDs, ",")))
- resp, err := c.client.get(endpoint, nil, c.client.authenticator.collectionsAuth)
+ resp, err := c.client.get(ctx, endpoint, nil, c.client.authenticator.collectionsAuth)
if err != nil {
return nil, err
}
@@ -53,14 +54,14 @@ func (c *CollectionsClient) Select(collection string, ids ...string) (*GetCollec
}
// DeleteMany removes from a collection the objects having the given IDs.
-func (c *CollectionsClient) DeleteMany(collection string, ids ...string) (*BaseResponse, error) {
+func (c *CollectionsClient) DeleteMany(ctx context.Context, collection string, ids ...string) (*BaseResponse, error) {
if collection == "" {
return nil, errors.New("collection name required")
}
endpoint := c.client.makeEndpoint("collections/")
endpoint.addQueryParam(makeRequestOption("collection_name", collection))
endpoint.addQueryParam(makeRequestOption("ids", strings.Join(ids, ",")))
- return decode(c.client.delete(endpoint, nil, c.client.authenticator.collectionsAuth))
+ return decode(c.client.delete(ctx, endpoint, nil, c.client.authenticator.collectionsAuth))
}
func (c *CollectionsClient) decodeObject(resp []byte, err error) (*CollectionObjectResponse, error) {
@@ -75,7 +76,7 @@ func (c *CollectionsClient) decodeObject(resp []byte, err error) (*CollectionObj
}
// Add adds a single object to a collection.
-func (c *CollectionsClient) Add(collection string, object CollectionObject, opts ...AddObjectOption) (*CollectionObjectResponse, error) {
+func (c *CollectionsClient) Add(ctx context.Context, collection string, object CollectionObject, opts ...AddObjectOption) (*CollectionObjectResponse, error) {
if collection == "" {
return nil, errors.New("collection name required")
}
@@ -90,21 +91,21 @@ func (c *CollectionsClient) Add(collection string, object CollectionObject, opts
req.ID = object.ID
req.Data = object.Data
- return c.decodeObject(c.client.post(endpoint, req, c.client.authenticator.collectionsAuth))
+ return c.decodeObject(c.client.post(ctx, endpoint, req, c.client.authenticator.collectionsAuth))
}
// Get retrieves a collection object having the given ID.
-func (c *CollectionsClient) Get(collection, id string) (*CollectionObjectResponse, error) {
+func (c *CollectionsClient) Get(ctx context.Context, collection, id string) (*CollectionObjectResponse, error) {
if collection == "" {
return nil, errors.New("collection name required")
}
endpoint := c.client.makeEndpoint("collections/%s/%s/", collection, id)
- return c.decodeObject(c.client.get(endpoint, nil, c.client.authenticator.collectionsAuth))
+ return c.decodeObject(c.client.get(ctx, endpoint, nil, c.client.authenticator.collectionsAuth))
}
// Update updates the given collection object's data.
-func (c *CollectionsClient) Update(collection, id string, data map[string]interface{}) (*CollectionObjectResponse, error) {
+func (c *CollectionsClient) Update(ctx context.Context, collection, id string, data map[string]interface{}) (*CollectionObjectResponse, error) {
if collection == "" {
return nil, errors.New("collection name required")
}
@@ -113,17 +114,17 @@ func (c *CollectionsClient) Update(collection, id string, data map[string]interf
"data": data,
}
- return c.decodeObject(c.client.put(endpoint, reqData, c.client.authenticator.collectionsAuth))
+ return c.decodeObject(c.client.put(ctx, endpoint, reqData, c.client.authenticator.collectionsAuth))
}
// Delete removes from a collection the object having the given ID.
-func (c *CollectionsClient) Delete(collection, id string) (*BaseResponse, error) {
+func (c *CollectionsClient) Delete(ctx context.Context, collection, id string) (*BaseResponse, error) {
if collection == "" {
return nil, errors.New("collection name required")
}
endpoint := c.client.makeEndpoint("collections/%s/%s/", collection, id)
- return decode(c.client.delete(endpoint, nil, c.client.authenticator.collectionsAuth))
+ return decode(c.client.delete(ctx, endpoint, nil, c.client.authenticator.collectionsAuth))
}
// CreateReference returns a new reference string in the form SO::.
diff --git a/collections_test.go b/collections_test.go
index 031bb3e..78144c8 100644
--- a/collections_test.go
+++ b/collections_test.go
@@ -1,6 +1,7 @@
package stream_test
import (
+ "context"
"net/http"
"net/url"
"testing"
@@ -18,6 +19,7 @@ func TestCollectionRefHelpers(t *testing.T) {
}
func TestUpsertCollectionObjects(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
testCases := []struct {
objects []stream.CollectionObject
@@ -62,13 +64,14 @@ func TestUpsertCollectionObjects(t *testing.T) {
},
}
for _, tc := range testCases {
- _, err := client.Collections().Upsert(tc.collection, tc.objects...)
+ _, err := client.Collections().Upsert(ctx, tc.collection, tc.objects...)
require.NoError(t, err)
testRequest(t, requester.req, http.MethodPost, tc.expectedURL, tc.expectedBody)
}
}
func TestSelectCollectionObjects(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
testCases := []struct {
ids []string
@@ -88,13 +91,14 @@ func TestSelectCollectionObjects(t *testing.T) {
},
}
for _, tc := range testCases {
- _, err := client.Collections().Select(tc.collection, tc.ids...)
+ _, err := client.Collections().Select(ctx, tc.collection, tc.ids...)
require.NoError(t, err)
testRequest(t, requester.req, http.MethodGet, tc.expectedURL, tc.expectedBody)
}
}
func TestDeleteManyCollectionObjects(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
testCases := []struct {
ids []string
@@ -113,29 +117,32 @@ func TestDeleteManyCollectionObjects(t *testing.T) {
},
}
for _, tc := range testCases {
- _, err := client.Collections().DeleteMany(tc.collection, tc.ids...)
+ _, err := client.Collections().DeleteMany(ctx, tc.collection, tc.ids...)
require.NoError(t, err)
testRequest(t, requester.req, http.MethodDelete, tc.expectedURL, "")
}
}
func TestGetCollectionObject(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
- _, err := client.Collections().Get("test-get-one", "id1")
+ _, err := client.Collections().Get(ctx, "test-get-one", "id1")
require.NoError(t, err)
testRequest(t, requester.req, http.MethodGet, "https://api.stream-io-api.com/api/v1.0/collections/test-get-one/id1/?api_key=key", "")
}
func TestDeleteCollectionObject(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
- _, err := client.Collections().Delete("test-get-one", "id1")
+ _, err := client.Collections().Delete(ctx, "test-get-one", "id1")
require.NoError(t, err)
testRequest(t, requester.req, http.MethodDelete, "https://api.stream-io-api.com/api/v1.0/collections/test-get-one/id1/?api_key=key", "")
}
func TestAddCollectionObject(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
testCases := []struct {
object stream.CollectionObject
@@ -171,19 +178,20 @@ func TestAddCollectionObject(t *testing.T) {
},
}
for _, tc := range testCases {
- _, err := client.Collections().Add(tc.collection, tc.object, tc.opts...)
+ _, err := client.Collections().Add(ctx, tc.collection, tc.object, tc.opts...)
require.NoError(t, err)
testRequest(t, requester.req, http.MethodPost, tc.expectedURL, tc.expectedBody)
}
}
func TestUpdateCollectionObject(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
data := map[string]interface{}{
"name": "Jane",
}
- _, err := client.Collections().Update("test-collection", "123", data)
+ _, err := client.Collections().Update(ctx, "test-collection", "123", data)
require.NoError(t, err)
expectedBody := `{"data":{"name":"Jane"}}`
testRequest(t, requester.req, http.MethodPut, "https://api.stream-io-api.com/api/v1.0/collections/test-collection/123/?api_key=key", expectedBody)
diff --git a/feed.go b/feed.go
index 14fe972..df08e68 100644
--- a/feed.go
+++ b/feed.go
@@ -1,6 +1,7 @@
package stream
import (
+ "context"
"fmt"
"regexp"
)
@@ -17,14 +18,14 @@ type Feed interface {
ID() string
Slug() string
UserID() string
- AddActivity(Activity) (*AddActivityResponse, error)
- AddActivities(...Activity) (*AddActivitiesResponse, error)
- RemoveActivityByID(string) (*RemoveActivityResponse, error)
- RemoveActivityByForeignID(string) (*RemoveActivityResponse, error)
- Follow(*FlatFeed, ...FollowFeedOption) (*BaseResponse, error)
- GetFollowing(...FollowingOption) (*FollowingResponse, error)
- Unfollow(Feed, ...UnfollowOption) (*BaseResponse, error)
- UpdateToTargets(Activity, ...UpdateToTargetsOption) (*UpdateToTargetsResponse, error)
+ AddActivity(context.Context, Activity) (*AddActivityResponse, error)
+ AddActivities(context.Context, ...Activity) (*AddActivitiesResponse, error)
+ RemoveActivityByID(context.Context, string) (*RemoveActivityResponse, error)
+ RemoveActivityByForeignID(context.Context, string) (*RemoveActivityResponse, error)
+ Follow(context.Context, *FlatFeed, ...FollowFeedOption) (*BaseResponse, error)
+ GetFollowing(context.Context, ...FollowingOption) (*FollowingResponse, error)
+ Unfollow(context.Context, Feed, ...UnfollowOption) (*BaseResponse, error)
+ UpdateToTargets(context.Context, Activity, ...UpdateToTargetsOption) (*UpdateToTargetsResponse, error)
RealtimeToken(bool) string
}
@@ -66,30 +67,30 @@ func newFeed(slug, userID string, client *Client) (*feed, error) {
}
// AddActivity adds a new Activity to the feed.
-func (f *feed) AddActivity(activity Activity) (*AddActivityResponse, error) {
- return f.client.addActivity(f, activity)
+func (f *feed) AddActivity(ctx context.Context, activity Activity) (*AddActivityResponse, error) {
+ return f.client.addActivity(ctx, f, activity)
}
// AddActivities adds multiple activities to the feed.
-func (f *feed) AddActivities(activities ...Activity) (*AddActivitiesResponse, error) {
- return f.client.addActivities(f, activities...)
+func (f *feed) AddActivities(ctx context.Context, activities ...Activity) (*AddActivitiesResponse, error) {
+ return f.client.addActivities(ctx, f, activities...)
}
// RemoveActivityByID removes an activity from the feed (if present), using the provided
// id string argument as the ID field of the activity.
-func (f *feed) RemoveActivityByID(id string) (*RemoveActivityResponse, error) {
- return f.client.removeActivityByID(f, id)
+func (f *feed) RemoveActivityByID(ctx context.Context, id string) (*RemoveActivityResponse, error) {
+ return f.client.removeActivityByID(ctx, f, id)
}
// RemoveActivityByForeignID removes an activity from the feed (if present), using the provided
// foreignID string argument as the foreign_id field of the activity.
-func (f *feed) RemoveActivityByForeignID(foreignID string) (*RemoveActivityResponse, error) {
- return f.client.removeActivityByForeignID(f, foreignID)
+func (f *feed) RemoveActivityByForeignID(ctx context.Context, foreignID string) (*RemoveActivityResponse, error) {
+ return f.client.removeActivityByForeignID(ctx, f, foreignID)
}
// Follow follows the provided feed (which must be a FlatFeed), applying the provided FollowFeedOptions,
// if any.
-func (f *feed) Follow(feed *FlatFeed, opts ...FollowFeedOption) (*BaseResponse, error) {
+func (f *feed) Follow(ctx context.Context, feed *FlatFeed, opts ...FollowFeedOption) (*BaseResponse, error) {
followOptions := &followFeedOptions{
Target: fmt.Sprintf("%s:%s", feed.Slug(), feed.UserID()),
ActivityCopyLimit: defaultActivityCopyLimit,
@@ -97,24 +98,24 @@ func (f *feed) Follow(feed *FlatFeed, opts ...FollowFeedOption) (*BaseResponse,
for _, opt := range opts {
opt(followOptions)
}
- return f.client.follow(f, followOptions)
+ return f.client.follow(ctx, f, followOptions)
}
// GetFollowing returns the list of the feeds following the feed, applying the provided FollowingOptions,
// if any.
-func (f *feed) GetFollowing(opts ...FollowingOption) (*FollowingResponse, error) {
- return f.client.getFollowing(f, opts...)
+func (f *feed) GetFollowing(ctx context.Context, opts ...FollowingOption) (*FollowingResponse, error) {
+ return f.client.getFollowing(ctx, f, opts...)
}
// Unfollow unfollows the provided feed, applying the provided UnfollowOptions, if any.
-func (f *feed) Unfollow(target Feed, opts ...UnfollowOption) (*BaseResponse, error) {
- return f.client.unfollow(f, target.ID(), opts...)
+func (f *feed) Unfollow(ctx context.Context, target Feed, opts ...UnfollowOption) (*BaseResponse, error) {
+ return f.client.unfollow(ctx, f, target.ID(), opts...)
}
// UpdateToTargets updates the "to" targets for the provided activity, with the options passed
// as argument for replacing, adding, or removing to targets.
-func (f *feed) UpdateToTargets(activity Activity, opts ...UpdateToTargetsOption) (*UpdateToTargetsResponse, error) {
- return f.client.updateToTargets(f, activity, opts...)
+func (f *feed) UpdateToTargets(ctx context.Context, activity Activity, opts ...UpdateToTargetsOption) (*UpdateToTargetsResponse, error) {
+ return f.client.updateToTargets(ctx, f, activity, opts...)
}
// RealtimeToken returns a token that can be used client-side to listen in real-time to feed changes.
diff --git a/feed_test.go b/feed_test.go
index f5b85b9..c4daead 100644
--- a/feed_test.go
+++ b/feed_test.go
@@ -1,6 +1,7 @@
package stream_test
import (
+ "context"
"fmt"
"net/http"
"testing"
@@ -35,27 +36,29 @@ func TestInvalidFeedUserID(t *testing.T) {
func TestAddActivity(t *testing.T) {
var (
client, requester = newClient(t)
+ ctx = context.Background()
flat, _ = newFlatFeedWithUserID(client, "123")
bobActivity = stream.Activity{Actor: "bob", Verb: "like", Object: "ice-cream", To: []string{"flat:456"}}
)
- _, err := flat.AddActivity(bobActivity)
+ _, err := flat.AddActivity(ctx, bobActivity)
require.NoError(t, err)
body := `{"actor":"bob","object":"ice-cream","to":["flat:456"],"verb":"like"}`
testRequest(t, requester.req, http.MethodPost, "https://api.stream-io-api.com/api/v1.0/feed/flat/123/?api_key=key", body)
requester.resp = `{"duration": "1ms"}`
- _, err = flat.AddActivity(bobActivity)
+ _, err = flat.AddActivity(ctx, bobActivity)
require.NoError(t, err)
}
func TestAddActivities(t *testing.T) {
var (
client, requester = newClient(t)
+ ctx = context.Background()
flat, _ = newFlatFeedWithUserID(client, "123")
bobActivity = stream.Activity{Actor: "bob", Verb: "like", Object: "ice-cream"}
aliceActivity = stream.Activity{Actor: "alice", Verb: "dislike", Object: "ice-cream", To: []string{"flat:456"}}
)
- _, err := flat.AddActivities(bobActivity, aliceActivity)
+ _, err := flat.AddActivities(ctx, bobActivity, aliceActivity)
require.NoError(t, err)
body := `{"activities":[{"actor":"bob","object":"ice-cream","verb":"like"},{"actor":"alice","object":"ice-cream","to":["flat:456"],"verb":"dislike"}]}`
testRequest(t, requester.req, http.MethodPost, "https://api.stream-io-api.com/api/v1.0/feed/flat/123/?api_key=key", body)
@@ -64,6 +67,7 @@ func TestAddActivities(t *testing.T) {
func TestUpdateActivities(t *testing.T) {
var (
client, requester = newClient(t)
+ ctx = context.Background()
now = getTime(time.Now())
bobActivity = stream.Activity{
Actor: "bob",
@@ -74,7 +78,7 @@ func TestUpdateActivities(t *testing.T) {
Extra: map[string]interface{}{"influence": 42},
}
)
- _, err := client.UpdateActivities(bobActivity)
+ _, err := client.UpdateActivities(ctx, bobActivity)
require.NoError(t, err)
body := fmt.Sprintf(`{"activities":[{"actor":"bob","foreign_id":"bob:123","influence":42,"object":"ice-cream","time":%q,"verb":"like"}]}`, now.Format(stream.TimeLayout))
@@ -84,6 +88,7 @@ func TestUpdateActivities(t *testing.T) {
func TestFollow(t *testing.T) {
var (
client, requester = newClient(t)
+ ctx = context.Background()
f1, _ = newFlatFeedWithUserID(client, "f1")
f2, _ = newFlatFeedWithUserID(client, "f2")
)
@@ -103,7 +108,7 @@ func TestFollow(t *testing.T) {
},
}
for _, tc := range testCases {
- _, err := f1.Follow(f2, tc.opts...)
+ _, err := f1.Follow(ctx, f2, tc.opts...)
require.NoError(t, err)
testRequest(t, requester.req, http.MethodPost, tc.expectedURL, tc.expectedBody)
}
@@ -112,6 +117,7 @@ func TestFollow(t *testing.T) {
func TestGetFollowing(t *testing.T) {
var (
client, requester = newClient(t)
+ ctx = context.Background()
f1, _ = newFlatFeedWithUserID(client, "f1")
)
testCases := []struct {
@@ -127,7 +133,7 @@ func TestGetFollowing(t *testing.T) {
},
}
for _, tc := range testCases {
- _, err := f1.GetFollowing(tc.opts...)
+ _, err := f1.GetFollowing(ctx, tc.opts...)
require.NoError(t, err)
testRequest(t, requester.req, http.MethodGet, tc.expected, "")
}
@@ -136,6 +142,7 @@ func TestGetFollowing(t *testing.T) {
func TestGetFollowers(t *testing.T) {
var (
client, requester = newClient(t)
+ ctx = context.Background()
f1, _ = newFlatFeedWithUserID(client, "f1")
)
testCases := []struct {
@@ -151,7 +158,7 @@ func TestGetFollowers(t *testing.T) {
},
}
for _, tc := range testCases {
- _, err := f1.GetFollowers(tc.opts...)
+ _, err := f1.GetFollowers(ctx, tc.opts...)
require.NoError(t, err)
testRequest(t, requester.req, http.MethodGet, tc.expected, "")
}
@@ -160,6 +167,7 @@ func TestGetFollowers(t *testing.T) {
func TestUnfollow(t *testing.T) {
var (
client, requester = newClient(t)
+ ctx = context.Background()
f1, _ = newFlatFeedWithUserID(client, "f1")
f2, _ = newFlatFeedWithUserID(client, "f2")
)
@@ -181,19 +189,20 @@ func TestUnfollow(t *testing.T) {
}
for _, tc := range testCases {
- _, err := f1.Unfollow(f2, tc.opts...)
+ _, err := f1.Unfollow(ctx, f2, tc.opts...)
require.NoError(t, err)
testRequest(t, requester.req, http.MethodDelete, tc.expected, "")
}
}
func TestRemoveActivities(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
flat, _ := newFlatFeedWithUserID(client, "123")
- _, err := flat.RemoveActivityByID("id-to-remove")
+ _, err := flat.RemoveActivityByID(ctx, "id-to-remove")
require.NoError(t, err)
testRequest(t, requester.req, http.MethodDelete, "https://api.stream-io-api.com/api/v1.0/feed/flat/123/id-to-remove/?api_key=key", "")
- _, err = flat.RemoveActivityByForeignID("bob:123")
+ _, err = flat.RemoveActivityByForeignID(ctx, "bob:123")
require.NoError(t, err)
testRequest(t, requester.req, http.MethodDelete, "https://api.stream-io-api.com/api/v1.0/feed/flat/123/bob:123/?api_key=key&foreign_id=1", "")
}
@@ -201,6 +210,7 @@ func TestRemoveActivities(t *testing.T) {
func TestUpdateToTargets(t *testing.T) {
var (
client, requester = newClient(t)
+ ctx = context.Background()
flat, _ = newFlatFeedWithUserID(client, "123")
f1, _ = newFlatFeedWithUserID(client, "f1")
f2, _ = newFlatFeedWithUserID(client, "f2")
@@ -208,11 +218,11 @@ func TestUpdateToTargets(t *testing.T) {
now = getTime(time.Now())
activity = stream.Activity{Time: now, ForeignID: "bob:123", Actor: "bob", Verb: "like", Object: "ice-cream", To: []string{f1.ID()}, Extra: map[string]interface{}{"popularity": 9000}}
)
- _, err := flat.UpdateToTargets(activity, stream.WithToTargetsAdd(f2.ID()), stream.WithToTargetsRemove(f1.ID()))
+ _, err := flat.UpdateToTargets(ctx, activity, stream.WithToTargetsAdd(f2.ID()), stream.WithToTargetsRemove(f1.ID()))
require.NoError(t, err)
body := fmt.Sprintf(`{"foreign_id":"bob:123","time":%q,"added_targets":["flat:f2"],"removed_targets":["flat:f1"]}`, now.Format(stream.TimeLayout))
testRequest(t, requester.req, http.MethodPost, "https://api.stream-io-api.com/api/v1.0/feed_targets/flat/123/activity_to_targets/?api_key=key", body)
- _, err = flat.UpdateToTargets(activity, stream.WithToTargetsNew(f3.ID()))
+ _, err = flat.UpdateToTargets(ctx, activity, stream.WithToTargetsNew(f3.ID()))
require.NoError(t, err)
body = fmt.Sprintf(`{"foreign_id":"bob:123","time":%q,"new_targets":["flat:f3"]}`, now.Format(stream.TimeLayout))
testRequest(t, requester.req, http.MethodPost, "https://api.stream-io-api.com/api/v1.0/feed_targets/flat/123/activity_to_targets/?api_key=key", body)
diff --git a/flat_feed.go b/flat_feed.go
index 6857452..3f58d7f 100644
--- a/flat_feed.go
+++ b/flat_feed.go
@@ -1,6 +1,9 @@
package stream
-import "encoding/json"
+import (
+ "context"
+ "encoding/json"
+)
// FlatFeed is a Stream flat feed.
type FlatFeed struct {
@@ -9,8 +12,8 @@ type FlatFeed struct {
// GetActivities returns the activities for the given FlatFeed, filtering
// results with the provided GetActivitiesOption parameters.
-func (f *FlatFeed) GetActivities(opts ...GetActivitiesOption) (*FlatFeedResponse, error) {
- body, err := f.client.getActivities(f, opts...)
+func (f *FlatFeed) GetActivities(ctx context.Context, opts ...GetActivitiesOption) (*FlatFeedResponse, error) {
+ body, err := f.client.getActivities(ctx, f, opts...)
if err != nil {
return nil, err
}
@@ -23,29 +26,29 @@ func (f *FlatFeed) GetActivities(opts ...GetActivitiesOption) (*FlatFeedResponse
// GetNextPageActivities returns the activities for the given FlatFeed at the "next" page
// of a previous *FlatFeedResponse response, if any.
-func (f *FlatFeed) GetNextPageActivities(resp *FlatFeedResponse) (*FlatFeedResponse, error) {
+func (f *FlatFeed) GetNextPageActivities(ctx context.Context, resp *FlatFeedResponse) (*FlatFeedResponse, error) {
opts, err := resp.parseNext()
if err != nil {
return nil, err
}
- return f.GetActivities(opts...)
+ return f.GetActivities(ctx, opts...)
}
// GetActivitiesWithRanking returns the activities (filtered) for the given FlatFeed,
// using the provided ranking method.
-func (f *FlatFeed) GetActivitiesWithRanking(ranking string, opts ...GetActivitiesOption) (*FlatFeedResponse, error) {
- return f.GetActivities(append(opts, withActivitiesRanking(ranking))...)
+func (f *FlatFeed) GetActivitiesWithRanking(ctx context.Context, ranking string, opts ...GetActivitiesOption) (*FlatFeedResponse, error) {
+ return f.GetActivities(ctx, append(opts, withActivitiesRanking(ranking))...)
}
// GetFollowers returns the feeds following the given FlatFeed.
-func (f *FlatFeed) GetFollowers(opts ...FollowersOption) (*FollowersResponse, error) {
- return f.client.getFollowers(f, opts...)
+func (f *FlatFeed) GetFollowers(ctx context.Context, opts ...FollowersOption) (*FollowersResponse, error) {
+ return f.client.getFollowers(ctx, f, opts...)
}
// GetEnrichedActivities returns the enriched activities for the given FlatFeed, filtering
// results with the provided GetActivitiesOption parameters.
-func (f *FlatFeed) GetEnrichedActivities(opts ...GetActivitiesOption) (*EnrichedFlatFeedResponse, error) {
- body, err := f.client.getEnrichedActivities(f, opts...)
+func (f *FlatFeed) GetEnrichedActivities(ctx context.Context, opts ...GetActivitiesOption) (*EnrichedFlatFeedResponse, error) {
+ body, err := f.client.getEnrichedActivities(ctx, f, opts...)
if err != nil {
return nil, err
}
@@ -58,23 +61,23 @@ func (f *FlatFeed) GetEnrichedActivities(opts ...GetActivitiesOption) (*Enriched
// GetNextPageEnrichedActivities returns the enriched activities for the given FlatFeed at the "next" page
// of a previous *EnrichedFlatFeedResponse response, if any.
-func (f *FlatFeed) GetNextPageEnrichedActivities(resp *EnrichedFlatFeedResponse) (*EnrichedFlatFeedResponse, error) {
+func (f *FlatFeed) GetNextPageEnrichedActivities(ctx context.Context, resp *EnrichedFlatFeedResponse) (*EnrichedFlatFeedResponse, error) {
opts, err := resp.parseNext()
if err != nil {
return nil, err
}
- return f.GetEnrichedActivities(opts...)
+ return f.GetEnrichedActivities(ctx, opts...)
}
// GetEnrichedActivitiesWithRanking returns the enriched activities (filtered) for the given FlatFeed,
// using the provided ranking method.
-func (f *FlatFeed) GetEnrichedActivitiesWithRanking(ranking string, opts ...GetActivitiesOption) (*EnrichedFlatFeedResponse, error) {
- return f.GetEnrichedActivities(append(opts, withActivitiesRanking(ranking))...)
+func (f *FlatFeed) GetEnrichedActivitiesWithRanking(ctx context.Context, ranking string, opts ...GetActivitiesOption) (*EnrichedFlatFeedResponse, error) {
+ return f.GetEnrichedActivities(ctx, append(opts, withActivitiesRanking(ranking))...)
}
// FollowStats returns the follower/following counts of the feed.
// If options are given, counts are filtered for the given slugs.
// Counts will be capped at 10K, if higher counts are needed and contact to support.
-func (f *FlatFeed) FollowStats(opts ...FollowStatOption) (*FollowStatResponse, error) {
- return f.client.followStats(f, opts...)
+func (f *FlatFeed) FollowStats(ctx context.Context, opts ...FollowStatOption) (*FollowStatResponse, error) {
+ return f.client.followStats(ctx, f, opts...)
}
diff --git a/flat_feed_test.go b/flat_feed_test.go
index f59310d..c3108f2 100644
--- a/flat_feed_test.go
+++ b/flat_feed_test.go
@@ -1,6 +1,7 @@
package stream_test
import (
+ "context"
"fmt"
"net/http"
"testing"
@@ -12,6 +13,7 @@ import (
)
func TestFlatFeedGetActivities(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
flat, _ := newFlatFeedWithUserID(client, "123")
testCases := []struct {
@@ -50,80 +52,82 @@ func TestFlatFeedGetActivities(t *testing.T) {
}
for _, tc := range testCases {
- _, err := flat.GetActivities(tc.opts...)
+ _, err := flat.GetActivities(ctx, tc.opts...)
testRequest(t, requester.req, http.MethodGet, tc.url, "")
assert.NoError(t, err)
- _, err = flat.GetActivitiesWithRanking("popularity", tc.opts...)
+ _, err = flat.GetActivitiesWithRanking(ctx, "popularity", tc.opts...)
testRequest(t, requester.req, http.MethodGet, fmt.Sprintf("%s&ranking=popularity", tc.url), "")
assert.NoError(t, err)
- _, err = flat.GetEnrichedActivities(tc.opts...)
+ _, err = flat.GetEnrichedActivities(ctx, tc.opts...)
testRequest(t, requester.req, http.MethodGet, tc.enrichedURL, "")
assert.NoError(t, err)
- _, err = flat.GetEnrichedActivitiesWithRanking("popularity", tc.opts...)
+ _, err = flat.GetEnrichedActivitiesWithRanking(ctx, "popularity", tc.opts...)
testRequest(t, requester.req, http.MethodGet, fmt.Sprintf("%s&ranking=popularity", tc.enrichedURL), "")
assert.NoError(t, err)
}
}
func TestFlatFeedGetNextPageActivities(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
flat, _ := newFlatFeedWithUserID(client, "123")
requester.resp = `{"next":"/api/v1.0/feed/flat/123/?id_lt=78c1a709-aff2-11e7-b3a7-a45e60be7d3b&limit=25"}`
- resp, err := flat.GetActivities()
+ resp, err := flat.GetActivities(ctx)
require.NoError(t, err)
- _, err = flat.GetNextPageActivities(resp)
+ _, err = flat.GetNextPageActivities(ctx, resp)
testRequest(t, requester.req, http.MethodGet, "https://api.stream-io-api.com/api/v1.0/feed/flat/123/?api_key=key&id_lt=78c1a709-aff2-11e7-b3a7-a45e60be7d3b&limit=25", "")
require.NoError(t, err)
requester.resp = `{"next":"/api/v1.0/enrich/feed/flat/123/?id_lt=78c1a709-aff2-11e7-b3a7-a45e60be7d3b&limit=25"}`
- enrichedResp, err := flat.GetEnrichedActivities()
+ enrichedResp, err := flat.GetEnrichedActivities(ctx)
require.NoError(t, err)
- _, err = flat.GetNextPageEnrichedActivities(enrichedResp)
+ _, err = flat.GetNextPageEnrichedActivities(ctx, enrichedResp)
testRequest(t, requester.req, http.MethodGet, "https://api.stream-io-api.com/api/v1.0/enrich/feed/flat/123/?api_key=key&id_lt=78c1a709-aff2-11e7-b3a7-a45e60be7d3b&limit=25", "")
require.NoError(t, err)
requester.resp = `{"next":123}`
- _, err = flat.GetActivities()
+ _, err = flat.GetActivities(ctx)
require.Error(t, err)
requester.resp = `{"next":"123"}`
- resp, err = flat.GetActivities()
+ resp, err = flat.GetActivities(ctx)
require.NoError(t, err)
- _, err = flat.GetNextPageActivities(resp)
+ _, err = flat.GetNextPageActivities(ctx, resp)
require.Error(t, err)
requester.resp = `{"next":"?q=a%"}`
- resp, err = flat.GetActivities()
+ resp, err = flat.GetActivities(ctx)
require.NoError(t, err)
- _, err = flat.GetNextPageActivities(resp)
+ _, err = flat.GetNextPageActivities(ctx, resp)
require.Error(t, err)
}
func TestFlatFeedFollowStats(t *testing.T) {
+ ctx := context.Background()
endpoint := "https://api.stream-io-api.com/api/v1.0/stats/follow/?api_key=key"
client, requester := newClient(t)
flat, _ := newFlatFeedWithUserID(client, "123")
- _, err := flat.FollowStats()
+ _, err := flat.FollowStats(ctx)
testRequest(t, requester.req, http.MethodGet, endpoint+"&followers=flat%3A123&following=flat%3A123", "")
assert.NoError(t, err)
- _, err = flat.FollowStats(stream.WithFollowerSlugs("a", "b"))
+ _, err = flat.FollowStats(ctx, stream.WithFollowerSlugs("a", "b"))
testRequest(t, requester.req, http.MethodGet, endpoint+"&followers=flat%3A123&followers_slugs=a%2Cb&following=flat%3A123", "")
assert.NoError(t, err)
- _, err = flat.FollowStats(stream.WithFollowingSlugs("c", "d"))
+ _, err = flat.FollowStats(ctx, stream.WithFollowingSlugs("c", "d"))
testRequest(t, requester.req, http.MethodGet, endpoint+"&followers=flat%3A123&following=flat%3A123&following_slugs=c%2Cd", "")
assert.NoError(t, err)
- _, err = flat.FollowStats(stream.WithFollowingSlugs("c", "d"), stream.WithFollowerSlugs("a", "b"))
+ _, err = flat.FollowStats(ctx, stream.WithFollowingSlugs("c", "d"), stream.WithFollowerSlugs("a", "b"))
testRequest(t, requester.req, http.MethodGet, endpoint+"&followers=flat%3A123&followers_slugs=a%2Cb&following=flat%3A123&following_slugs=c%2Cd", "")
assert.NoError(t, err)
}
diff --git a/notification_feed.go b/notification_feed.go
index a18d0de..bb936ca 100644
--- a/notification_feed.go
+++ b/notification_feed.go
@@ -1,6 +1,9 @@
package stream
-import "encoding/json"
+import (
+ "context"
+ "encoding/json"
+)
// NotificationFeed is a Stream notification feed.
type NotificationFeed struct {
@@ -9,8 +12,8 @@ type NotificationFeed struct {
// GetActivities returns the activities for the given NotificationFeed, filtering
// results with the provided GetActivitiesOption parameters.
-func (f *NotificationFeed) GetActivities(opts ...GetActivitiesOption) (*NotificationFeedResponse, error) {
- body, err := f.client.getActivities(f, opts...)
+func (f *NotificationFeed) GetActivities(ctx context.Context, opts ...GetActivitiesOption) (*NotificationFeedResponse, error) {
+ body, err := f.client.getActivities(ctx, f, opts...)
if err != nil {
return nil, err
}
@@ -23,18 +26,18 @@ func (f *NotificationFeed) GetActivities(opts ...GetActivitiesOption) (*Notifica
// GetNextPageActivities returns the activities for the given NotificationFeed at the "next" page
// of a previous *NotificationFeedResponse response, if any.
-func (f *NotificationFeed) GetNextPageActivities(resp *NotificationFeedResponse) (*NotificationFeedResponse, error) {
+func (f *NotificationFeed) GetNextPageActivities(ctx context.Context, resp *NotificationFeedResponse) (*NotificationFeedResponse, error) {
opts, err := resp.parseNext()
if err != nil {
return nil, err
}
- return f.GetActivities(opts...)
+ return f.GetActivities(ctx, opts...)
}
// GetEnrichedActivities returns the enriched activities for the given NotificationFeed, filtering
// results with the provided GetActivitiesOption parameters.
-func (f *NotificationFeed) GetEnrichedActivities(opts ...GetActivitiesOption) (*EnrichedNotificationFeedResponse, error) {
- body, err := f.client.getEnrichedActivities(f, opts...)
+func (f *NotificationFeed) GetEnrichedActivities(ctx context.Context, opts ...GetActivitiesOption) (*EnrichedNotificationFeedResponse, error) {
+ body, err := f.client.getEnrichedActivities(ctx, f, opts...)
if err != nil {
return nil, err
}
@@ -47,10 +50,10 @@ func (f *NotificationFeed) GetEnrichedActivities(opts ...GetActivitiesOption) (*
// GetNextPageEnrichedActivities returns the enriched activities for the given NotificationFeed at the "next" page
// of a previous *EnrichedNotificationFeedResponse response, if any.
-func (f *NotificationFeed) GetNextPageEnrichedActivities(resp *EnrichedNotificationFeedResponse) (*EnrichedNotificationFeedResponse, error) {
+func (f *NotificationFeed) GetNextPageEnrichedActivities(ctx context.Context, resp *EnrichedNotificationFeedResponse) (*EnrichedNotificationFeedResponse, error) {
opts, err := resp.parseNext()
if err != nil {
return nil, err
}
- return f.GetEnrichedActivities(opts...)
+ return f.GetEnrichedActivities(ctx, opts...)
}
diff --git a/notification_feed_test.go b/notification_feed_test.go
index d1ddd3d..a72a023 100644
--- a/notification_feed_test.go
+++ b/notification_feed_test.go
@@ -1,6 +1,7 @@
package stream_test
import (
+ "context"
"net/http"
"testing"
@@ -11,6 +12,7 @@ import (
)
func TestGetNotificationActivities(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
notification, _ := newNotificationFeedWithUserID(client, "123")
testCases := []struct {
@@ -55,49 +57,50 @@ func TestGetNotificationActivities(t *testing.T) {
}
for _, tc := range testCases {
- _, err := notification.GetActivities(tc.opts...)
+ _, err := notification.GetActivities(ctx, tc.opts...)
testRequest(t, requester.req, http.MethodGet, tc.url, "")
assert.NoError(t, err)
- _, err = notification.GetEnrichedActivities(tc.opts...)
+ _, err = notification.GetEnrichedActivities(ctx, tc.opts...)
testRequest(t, requester.req, http.MethodGet, tc.enrichedURL, "")
assert.NoError(t, err)
}
}
func TestNotificationFeedGetNextPageActivities(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
notification, _ := newNotificationFeedWithUserID(client, "123")
requester.resp = `{"next":"/api/v1.0/feed/notification/123/?id_lt=78c1a709-aff2-11e7-b3a7-a45e60be7d3b&limit=25"}`
- resp, err := notification.GetActivities()
+ resp, err := notification.GetActivities(ctx)
require.NoError(t, err)
- _, err = notification.GetNextPageActivities(resp)
+ _, err = notification.GetNextPageActivities(ctx, resp)
testRequest(t, requester.req, http.MethodGet, "https://api.stream-io-api.com/api/v1.0/feed/notification/123/?api_key=key&id_lt=78c1a709-aff2-11e7-b3a7-a45e60be7d3b&limit=25", "")
require.NoError(t, err)
requester.resp = `{"next":"/api/v1.0/enrich/feed/notification/123/?id_lt=78c1a709-aff2-11e7-b3a7-a45e60be7d3b&limit=25"}`
- enrichedResp, err := notification.GetEnrichedActivities()
+ enrichedResp, err := notification.GetEnrichedActivities(ctx)
require.NoError(t, err)
- _, err = notification.GetNextPageEnrichedActivities(enrichedResp)
+ _, err = notification.GetNextPageEnrichedActivities(ctx, enrichedResp)
testRequest(t, requester.req, http.MethodGet, "https://api.stream-io-api.com/api/v1.0/enrich/feed/notification/123/?api_key=key&id_lt=78c1a709-aff2-11e7-b3a7-a45e60be7d3b&limit=25", "")
require.NoError(t, err)
requester.resp = `{"next":123}`
- _, err = notification.GetActivities()
+ _, err = notification.GetActivities(ctx)
require.Error(t, err)
requester.resp = `{"next":"123"}`
- resp, err = notification.GetActivities()
+ resp, err = notification.GetActivities(ctx)
require.NoError(t, err)
- _, err = notification.GetNextPageActivities(resp)
+ _, err = notification.GetNextPageActivities(ctx, resp)
require.Error(t, err)
requester.resp = `{"next":"?q=a%"}`
- resp, err = notification.GetActivities()
+ resp, err = notification.GetActivities(ctx)
require.NoError(t, err)
- _, err = notification.GetNextPageActivities(resp)
+ _, err = notification.GetNextPageActivities(ctx, resp)
require.Error(t, err)
}
diff --git a/personalization.go b/personalization.go
index be49233..a0da245 100644
--- a/personalization.go
+++ b/personalization.go
@@ -1,6 +1,7 @@
package stream
import (
+ "context"
"encoding/json"
"errors"
"fmt"
@@ -23,7 +24,7 @@ func (c *PersonalizationClient) decode(resp []byte, err error) (*Personalization
}
// Get obtains a PersonalizationResponse for the given resource and params.
-func (c *PersonalizationClient) Get(resource string, params map[string]interface{}) (*PersonalizationResponse, error) {
+func (c *PersonalizationClient) Get(ctx context.Context, resource string, params map[string]interface{}) (*PersonalizationResponse, error) {
if resource == "" {
return nil, errors.New("missing resource")
}
@@ -31,11 +32,11 @@ func (c *PersonalizationClient) Get(resource string, params map[string]interface
for k, v := range params {
endpoint.addQueryParam(makeRequestOption(k, v))
}
- return c.decode(c.client.get(endpoint, nil, c.client.authenticator.personalizationAuth))
+ return c.decode(c.client.get(ctx, endpoint, nil, c.client.authenticator.personalizationAuth))
}
// Post sends data to the given resource, adding the given params to the request.
-func (c *PersonalizationClient) Post(resource string, params, data map[string]interface{}) (*PersonalizationResponse, error) {
+func (c *PersonalizationClient) Post(ctx context.Context, resource string, params, data map[string]interface{}) (*PersonalizationResponse, error) {
if resource == "" {
return nil, errors.New("missing resource")
}
@@ -48,11 +49,11 @@ func (c *PersonalizationClient) Post(resource string, params, data map[string]in
"data": data,
}
}
- return c.decode(c.client.post(endpoint, data, c.client.authenticator.personalizationAuth))
+ return c.decode(c.client.post(ctx, endpoint, data, c.client.authenticator.personalizationAuth))
}
// Delete removes data from the given resource, adding the given params to the request.
-func (c *PersonalizationClient) Delete(resource string, params map[string]interface{}) (*PersonalizationResponse, error) {
+func (c *PersonalizationClient) Delete(ctx context.Context, resource string, params map[string]interface{}) (*PersonalizationResponse, error) {
if resource == "" {
return nil, errors.New("missing resource")
}
@@ -60,5 +61,5 @@ func (c *PersonalizationClient) Delete(resource string, params map[string]interf
for k, v := range params {
endpoint.addQueryParam(makeRequestOption(k, v))
}
- return c.decode(c.client.delete(endpoint, nil, c.client.authenticator.personalizationAuth))
+ return c.decode(c.client.delete(ctx, endpoint, nil, c.client.authenticator.personalizationAuth))
}
diff --git a/personalization_test.go b/personalization_test.go
index d8bbc87..49df41e 100644
--- a/personalization_test.go
+++ b/personalization_test.go
@@ -1,6 +1,7 @@
package stream_test
import (
+ "context"
"net/http"
"testing"
@@ -8,25 +9,27 @@ import (
)
func TestPersonalizationGet(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
p := client.Personalization()
params := map[string]interface{}{"answer": 42, "feed": "user:123"}
- _, err := p.Get("", params)
+ _, err := p.Get(ctx, "", params)
require.Error(t, err)
- _, err = p.Get("some_resource", params)
+ _, err = p.Get(ctx, "some_resource", params)
require.NoError(t, err)
expectedURL := "https://personalization.stream-io-api.com/personalization/v1.0/some_resource/?answer=42&api_key=key&feed=user%3A123"
testRequest(t, requester.req, http.MethodGet, expectedURL, "")
}
func TestPersonalizationPost(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
p := client.Personalization()
params := map[string]interface{}{"answer": 42, "feed": "user:123"}
- _, err := p.Post("", params, nil)
+ _, err := p.Post(ctx, "", params, nil)
require.Error(t, err)
data := map[string]interface{}{"foo": "bar", "baz": 42}
- _, err = p.Post("some_resource", params, data)
+ _, err = p.Post(ctx, "some_resource", params, data)
require.NoError(t, err)
expectedURL := "https://personalization.stream-io-api.com/personalization/v1.0/some_resource/?answer=42&api_key=key&feed=user%3A123"
expectedBody := `{"data":{"baz":42,"foo":"bar"}}`
@@ -34,12 +37,13 @@ func TestPersonalizationPost(t *testing.T) {
}
func TestPersonalizationDelete(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
p := client.Personalization()
params := map[string]interface{}{"answer": 42, "feed": "user:123"}
- _, err := p.Delete("", params)
+ _, err := p.Delete(ctx, "", params)
require.Error(t, err)
- _, err = p.Delete("some_resource", params)
+ _, err = p.Delete(ctx, "some_resource", params)
require.NoError(t, err)
expectedURL := "https://personalization.stream-io-api.com/personalization/v1.0/some_resource/?answer=42&api_key=key&feed=user%3A123"
testRequest(t, requester.req, http.MethodDelete, expectedURL, "")
diff --git a/reactions.go b/reactions.go
index 763a25e..e0bcac6 100644
--- a/reactions.go
+++ b/reactions.go
@@ -1,6 +1,7 @@
package stream
import (
+ "context"
"encoding/json"
"errors"
"fmt"
@@ -12,22 +13,22 @@ type ReactionsClient struct {
}
// Add adds a reaction.
-func (c *ReactionsClient) Add(r AddReactionRequestObject) (*ReactionResponse, error) {
+func (c *ReactionsClient) Add(ctx context.Context, r AddReactionRequestObject) (*ReactionResponse, error) {
if r.ParentID != "" {
return nil, errors.New("`Parent` not empty. For adding child reactions use `AddChild`")
}
- return c.addReaction(r)
+ return c.addReaction(ctx, r)
}
// AddChild adds a child reaction to the provided parent.
-func (c *ReactionsClient) AddChild(parentID string, r AddReactionRequestObject) (*ReactionResponse, error) {
+func (c *ReactionsClient) AddChild(ctx context.Context, parentID string, r AddReactionRequestObject) (*ReactionResponse, error) {
r.ParentID = parentID
- return c.addReaction(r)
+ return c.addReaction(ctx, r)
}
-func (c *ReactionsClient) addReaction(r AddReactionRequestObject) (*ReactionResponse, error) {
+func (c *ReactionsClient) addReaction(ctx context.Context, r AddReactionRequestObject) (*ReactionResponse, error) {
endpoint := c.client.makeEndpoint("reaction/")
- return c.decode(c.client.post(endpoint, r, c.client.authenticator.reactionsAuth))
+ return c.decode(c.client.post(ctx, endpoint, r, c.client.authenticator.reactionsAuth))
}
func (c *ReactionsClient) decode(resp []byte, err error) (*ReactionResponse, error) {
@@ -43,32 +44,32 @@ func (c *ReactionsClient) decode(resp []byte, err error) (*ReactionResponse, err
}
// Update updates the reaction's data and/or target feeds.
-func (c *ReactionsClient) Update(id string, data map[string]interface{}, targetFeeds []string) (*ReactionResponse, error) {
+func (c *ReactionsClient) Update(ctx context.Context, id string, data map[string]interface{}, targetFeeds []string) (*ReactionResponse, error) {
endpoint := c.client.makeEndpoint("reaction/%s/", id)
reqData := map[string]interface{}{
"data": data,
"target_feeds": targetFeeds,
}
- return c.decode(c.client.put(endpoint, reqData, c.client.authenticator.reactionsAuth))
+ return c.decode(c.client.put(ctx, endpoint, reqData, c.client.authenticator.reactionsAuth))
}
// Get retrieves a reaction having the given id.
-func (c *ReactionsClient) Get(id string) (*ReactionResponse, error) {
+func (c *ReactionsClient) Get(ctx context.Context, id string) (*ReactionResponse, error) {
endpoint := c.client.makeEndpoint("reaction/%s/", id)
- return c.decode(c.client.get(endpoint, nil, c.client.authenticator.reactionsAuth))
+ return c.decode(c.client.get(ctx, endpoint, nil, c.client.authenticator.reactionsAuth))
}
// Delete deletes a reaction having the given id.
-func (c *ReactionsClient) Delete(id string) (*ReactionResponse, error) {
+func (c *ReactionsClient) Delete(ctx context.Context, id string) (*ReactionResponse, error) {
endpoint := c.client.makeEndpoint("reaction/%s/", id)
- return c.decode(c.client.delete(endpoint, nil, c.client.authenticator.reactionsAuth))
+ return c.decode(c.client.delete(ctx, endpoint, nil, c.client.authenticator.reactionsAuth))
}
// Filter lists reactions based on the provided criteria and with the specified pagination.
-func (c *ReactionsClient) Filter(attr FilterReactionsAttribute, opts ...FilterReactionsOption) (*FilterReactionResponse, error) {
+func (c *ReactionsClient) Filter(ctx context.Context, attr FilterReactionsAttribute, opts ...FilterReactionsOption) (*FilterReactionResponse, error) {
endpointURI := fmt.Sprintf("reaction/%s/", attr())
endpoint := c.client.makeEndpoint(endpointURI)
@@ -76,7 +77,7 @@ func (c *ReactionsClient) Filter(attr FilterReactionsAttribute, opts ...FilterRe
endpoint.addQueryParam(opt)
}
- resp, err := c.client.get(endpoint, nil, c.client.authenticator.reactionsAuth)
+ resp, err := c.client.get(ctx, endpoint, nil, c.client.authenticator.reactionsAuth)
if err != nil {
return nil, err
}
@@ -89,10 +90,10 @@ func (c *ReactionsClient) Filter(attr FilterReactionsAttribute, opts ...FilterRe
}
// GetNextPageFilteredReactions returns the reactions at the "next" page of a previous *FilterReactionResponse response, if any.
-func (c *ReactionsClient) GetNextPageFilteredReactions(resp *FilterReactionResponse) (*FilterReactionResponse, error) {
+func (c *ReactionsClient) GetNextPageFilteredReactions(ctx context.Context, resp *FilterReactionResponse) (*FilterReactionResponse, error) {
opts, err := resp.parseNext()
if err != nil {
return nil, err
}
- return c.Filter(resp.meta.attr, opts...)
+ return c.Filter(ctx, resp.meta.attr, opts...)
}
diff --git a/reactions_test.go b/reactions_test.go
index 709be3f..d4f79e4 100644
--- a/reactions_test.go
+++ b/reactions_test.go
@@ -1,6 +1,7 @@
package stream_test
import (
+ "context"
"net/http"
"testing"
@@ -10,20 +11,23 @@ import (
)
func TestGetReaction(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
- _, err := client.Reactions().Get("id1")
+ _, err := client.Reactions().Get(ctx, "id1")
require.NoError(t, err)
testRequest(t, requester.req, http.MethodGet, "https://api.stream-io-api.com/api/v1.0/reaction/id1/?api_key=key", "")
}
func TestDeleteReaction(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
- _, err := client.Reactions().Delete("id1")
+ _, err := client.Reactions().Delete(ctx, "id1")
require.NoError(t, err)
testRequest(t, requester.req, http.MethodDelete, "https://api.stream-io-api.com/api/v1.0/reaction/id1/?api_key=key", "")
}
func TestAddReaction(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
testCases := []struct {
@@ -72,13 +76,14 @@ func TestAddReaction(t *testing.T) {
},
}
for _, tc := range testCases {
- _, err := client.Reactions().Add(tc.input)
+ _, err := client.Reactions().Add(ctx, tc.input)
require.NoError(t, err)
testRequest(t, requester.req, http.MethodPost, tc.expectedURL, tc.expectedBody)
}
}
func TestAddChildReaction(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
reaction := stream.AddReactionRequestObject{
@@ -100,12 +105,13 @@ func TestAddChildReaction(t *testing.T) {
"target_feeds": ["stalker:timeline"],"target_feeds_extra_data":{"activity_field":"activity_value"}
}`
- _, err := client.Reactions().AddChild("pid", reaction)
+ _, err := client.Reactions().AddChild(ctx, "pid", reaction)
require.NoError(t, err)
testRequest(t, requester.req, http.MethodPost, expectedURL, expectedBody)
}
func TestUpdateReaction(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
testCases := []struct {
@@ -131,13 +137,14 @@ func TestUpdateReaction(t *testing.T) {
},
}
for _, tc := range testCases {
- _, err := client.Reactions().Update(tc.id, tc.data, tc.targetFeeds)
+ _, err := client.Reactions().Update(ctx, tc.id, tc.data, tc.targetFeeds)
require.NoError(t, err)
testRequest(t, requester.req, http.MethodPut, tc.expectedURL, tc.expectedBody)
}
}
func TestFilterReactions(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
testCases := []struct {
attr stream.FilterReactionsAttribute
@@ -173,25 +180,27 @@ func TestFilterReactions(t *testing.T) {
}
for _, tc := range testCases {
- _, err := client.Reactions().Filter(tc.attr, tc.opts...)
+ _, err := client.Reactions().Filter(ctx, tc.attr, tc.opts...)
require.NoError(t, err)
testRequest(t, requester.req, http.MethodGet, tc.expectedURL, "")
}
}
func TestGetNextPageReactions(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
requester.resp = `{"next":"/api/v1.0/reaction/user_id/uid/upvote/?api_key=key&id_gt=uid1&limit=100&with_activity_data=true"}`
- resp, err := client.Reactions().Filter(stream.ByUserID("uid").ByKind("like"), stream.WithLimit(10), stream.WithActivityData(), stream.WithIDGT("id1"))
+ resp, err := client.Reactions().Filter(ctx, stream.ByUserID("uid").ByKind("like"), stream.WithLimit(10), stream.WithActivityData(), stream.WithIDGT("id1"))
require.NoError(t, err)
- _, err = client.Reactions().GetNextPageFilteredReactions(resp)
+ _, err = client.Reactions().GetNextPageFilteredReactions(ctx, resp)
testRequest(t, requester.req, http.MethodGet, "https://api.stream-io-api.com/api/v1.0/reaction/user_id/uid/like/?api_key=key&id_gt=uid1&limit=100&with_activity_data=true", "")
require.NoError(t, err)
requester.resp = `{"next":"/api/v1.0/reaction/user_id/uid/upvote/?api_key=key&id_gt=uid1&limit=100&with_own_children=true"}`
resp, err = client.Reactions().Filter(
+ ctx,
stream.ByUserID("uid").ByKind("like"),
stream.WithLimit(10),
stream.WithOwnChildren(),
@@ -201,6 +210,7 @@ func TestGetNextPageReactions(t *testing.T) {
requester.resp = `{"next":"/api/v1.0/reaction/user_id/uid/upvote/?api_key=key&id_gt=uid1&limit=100&with_own_children=true&with_own_children_kinds=comment,like&user_id=something&children_user_id=child_user_id"}`
_, err = client.Reactions().Filter(
+ ctx,
stream.ByUserID("uid").ByKind("like"),
stream.WithLimit(10),
stream.WithIDGT("id1"),
@@ -209,27 +219,27 @@ func TestGetNextPageReactions(t *testing.T) {
)
require.NoError(t, err)
- _, err = client.Reactions().GetNextPageFilteredReactions(resp)
+ _, err = client.Reactions().GetNextPageFilteredReactions(ctx, resp)
testRequest(t, requester.req, http.MethodGet, "https://api.stream-io-api.com/api/v1.0/reaction/user_id/uid/like/?api_key=key&id_gt=uid1&limit=100&with_own_children=true", "")
require.NoError(t, err)
requester.resp = `{"next":"/api/v1.0/reaction/user_id/uid/upvote/?api_key=key&id_gt=uid1&limit=100&with_activity_data=false"}`
- resp, err = client.Reactions().Filter(stream.ByUserID("uid").ByKind("like"), stream.WithLimit(10), stream.WithActivityData(), stream.WithIDGT("id1"))
+ resp, err = client.Reactions().Filter(ctx, stream.ByUserID("uid").ByKind("like"), stream.WithLimit(10), stream.WithActivityData(), stream.WithIDGT("id1"))
require.NoError(t, err)
- _, err = client.Reactions().GetNextPageFilteredReactions(resp)
+ _, err = client.Reactions().GetNextPageFilteredReactions(ctx, resp)
testRequest(t, requester.req, http.MethodGet, "https://api.stream-io-api.com/api/v1.0/reaction/user_id/uid/like/?api_key=key&id_gt=uid1&limit=100", "")
require.NoError(t, err)
requester.resp = `{"next":"123"}`
- resp, err = client.Reactions().Filter(stream.ByActivityID("aid"))
+ resp, err = client.Reactions().Filter(ctx, stream.ByActivityID("aid"))
require.NoError(t, err)
- _, err = client.Reactions().GetNextPageFilteredReactions(resp)
+ _, err = client.Reactions().GetNextPageFilteredReactions(ctx, resp)
require.Error(t, err)
requester.resp = `{"next":"?q=a%"}`
- resp, err = client.Reactions().Filter(stream.ByActivityID("aid"))
+ resp, err = client.Reactions().Filter(ctx, stream.ByActivityID("aid"))
require.NoError(t, err)
- _, err = client.Reactions().GetNextPageFilteredReactions(resp)
+ _, err = client.Reactions().GetNextPageFilteredReactions(ctx, resp)
require.Error(t, err)
}
diff --git a/run-lint.sh b/run-lint.sh
index cfb9af4..966b3af 100755
--- a/run-lint.sh
+++ b/run-lint.sh
@@ -9,7 +9,7 @@ gopath="$(go env GOPATH)"
if ! [[ -x "$gopath/bin/golangci-lint" ]]; then
echo >&2 'Installing golangci-lint'
curl --silent --fail --location \
- https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "$gopath/bin" v1.45.2
+ https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "$gopath/bin" v1.46.0
fi
# configured by .golangci.yml
diff --git a/users.go b/users.go
index 92d11ab..a3e17aa 100644
--- a/users.go
+++ b/users.go
@@ -1,6 +1,7 @@
package stream
import (
+ "context"
"encoding/json"
"fmt"
)
@@ -22,35 +23,35 @@ func (c *UsersClient) decode(resp []byte, err error) (*UserResponse, error) {
}
// Add adds a new user with the specified id and optional extra data.
-func (c *UsersClient) Add(user User, getOrCreate bool) (*UserResponse, error) {
+func (c *UsersClient) Add(ctx context.Context, user User, getOrCreate bool) (*UserResponse, error) {
endpoint := c.client.makeEndpoint("user/")
endpoint.addQueryParam(makeRequestOption("get_or_create", getOrCreate))
- return c.decode(c.client.post(endpoint, user, c.client.authenticator.usersAuth))
+ return c.decode(c.client.post(ctx, endpoint, user, c.client.authenticator.usersAuth))
}
// Update updates the user's data.
-func (c *UsersClient) Update(id string, data map[string]interface{}) (*UserResponse, error) {
+func (c *UsersClient) Update(ctx context.Context, id string, data map[string]interface{}) (*UserResponse, error) {
endpoint := c.client.makeEndpoint("user/%s/", id)
reqData := map[string]interface{}{
"data": data,
}
- return c.decode(c.client.put(endpoint, reqData, c.client.authenticator.usersAuth))
+ return c.decode(c.client.put(ctx, endpoint, reqData, c.client.authenticator.usersAuth))
}
// Get retrieves a user having the given id.
-func (c *UsersClient) Get(id string) (*UserResponse, error) {
+func (c *UsersClient) Get(ctx context.Context, id string) (*UserResponse, error) {
endpoint := c.client.makeEndpoint("user/%s/", id)
- return c.decode(c.client.get(endpoint, nil, c.client.authenticator.usersAuth))
+ return c.decode(c.client.get(ctx, endpoint, nil, c.client.authenticator.usersAuth))
}
// Delete deletes a user having the given id.
-func (c *UsersClient) Delete(id string) (*BaseResponse, error) {
+func (c *UsersClient) Delete(ctx context.Context, id string) (*BaseResponse, error) {
endpoint := c.client.makeEndpoint("user/%s/", id)
- return decode(c.client.delete(endpoint, nil, c.client.authenticator.usersAuth))
+ return decode(c.client.delete(ctx, endpoint, nil, c.client.authenticator.usersAuth))
}
// CreateReference returns a new reference string in the form SU:.
diff --git a/users_test.go b/users_test.go
index 331a4a2..e6ef6b5 100644
--- a/users_test.go
+++ b/users_test.go
@@ -1,6 +1,7 @@
package stream_test
import (
+ "context"
"net/http"
"testing"
@@ -17,22 +18,25 @@ func TestUserRefHelpers(t *testing.T) {
}
func TestGetUser(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
- _, err := client.Users().Get("id1")
+ _, err := client.Users().Get(ctx, "id1")
require.NoError(t, err)
testRequest(t, requester.req, http.MethodGet, "https://api.stream-io-api.com/api/v1.0/user/id1/?api_key=key", "")
}
func TestDeleteUser(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
- _, err := client.Users().Delete("id1")
+ _, err := client.Users().Delete(ctx, "id1")
require.NoError(t, err)
testRequest(t, requester.req, http.MethodDelete, "https://api.stream-io-api.com/api/v1.0/user/id1/?api_key=key", "")
}
func TestAddUser(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
testCases := []struct {
object stream.User
@@ -66,19 +70,20 @@ func TestAddUser(t *testing.T) {
}
for _, tc := range testCases {
- _, err := client.Users().Add(tc.object, tc.getOrCreate)
+ _, err := client.Users().Add(ctx, tc.object, tc.getOrCreate)
require.NoError(t, err)
testRequest(t, requester.req, http.MethodPost, tc.expectedURL, tc.expectedBody)
}
}
func TestUpdateUser(t *testing.T) {
+ ctx := context.Background()
client, requester := newClient(t)
data := map[string]interface{}{
"name": "Jane",
}
- _, err := client.Users().Update("123", data)
+ _, err := client.Users().Update(ctx, "123", data)
require.NoError(t, err)
expectedBody := `{"data":{"name":"Jane"}}`
testRequest(t, requester.req, http.MethodPut, "https://api.stream-io-api.com/api/v1.0/user/123/?api_key=key", expectedBody)