ducky/subscriptions
15:aab6ba5ae392
Go to Latest
ducky/subscriptions/client/subscription.go
Log Postgres test failures more verbosely, fix SubscriptionChange.IsEmpty.
SubscriptionChange.IsEmpty() would return false even if no actual database
operations are going to be performed. This is because we allow information we
_don't_ store in the database (Stripe source, Stripe email) to be specified in a
SubscriptionChange object, just so we can easily access them. Then we use the
Stripe API to store them in Stripe's databases, and turn them into data _we_
store in our database. Think of them as pre-processed values that are never
stored raw.
The problem is, we were treating these properties the same as the properties we
actually stored in the database, and (worse) were running database tests for
combinations of these properties, which was causing test failures because we
were trying to update no columns in the database. Whoops.
I removed these properties from the IsEmpty helper, and removed them from the
code that generates the SubscriptionChange permutations for testing. This allows
tests to pass, but also stays closer to what the system was designed to do.
In tracking down this bug, I discovered that the logging we had for errors when
running Postgres tests was inadequate, so I updated the logs when that failure
occurs while testing Postgres to help surface future failures faster.
4 commonAPI "code.secondbit.org/api.hg"
5 "code.secondbit.org/auth.hg"
7 "code.secondbit.org/ducky/subscriptions.hg"
8 "code.secondbit.org/ducky/subscriptions.hg/api"
11 func (c *Client) CreateSubscription(change subscriptions.SubscriptionChange) (subscriptions.Subscription, error) {
12 resp, err := c.Post("/subscriptions/", change, auth.Scopes{api.ScopeSubscription, api.ScopeSubscriptionAdmin}.Strings(), change.UserID)
14 hErr, ok := err.(httpErrors)
16 for _, e := range hErr {
17 if e.Slug == commonAPI.RequestErrConflict &&
18 e.Field == "/user_id" {
19 return subscriptions.Subscription{}, subscriptions.ErrSubscriptionAlreadyExists
20 } else if e.Slug == commonAPI.RequestErrConflict &&
21 e.Field == "/stripe_token" {
22 return subscriptions.Subscription{}, subscriptions.ErrStripeSubscriptionAlreadyExists
26 return subscriptions.Subscription{}, err
28 if len(resp.Subscriptions) < 1 {
29 return subscriptions.Subscription{}, subscriptions.ErrSubscriptionNotFound
31 return resp.Subscriptions[0], nil
34 func (c *Client) UpdateSubscription(change subscriptions.SubscriptionChange) (subscriptions.Subscription, error) {
35 resp, err := c.Patch("/subscriptions/"+change.UserID.String(), change, auth.Scopes{api.ScopeSubscription, api.ScopeSubscriptionAdmin}.Strings(), change.UserID)
37 return subscriptions.Subscription{}, err
39 if len(resp.Subscriptions) < 1 {
40 return subscriptions.Subscription{}, subscriptions.ErrSubscriptionNotFound
42 return resp.Subscriptions[0], nil