ducky/subscriptions
3:b240b6123548 Browse Files
Export all subscriptionStore methods. We're not going to wrap all our subscriptionStore interactions in a Context type, so we need to expose all the functions so other packages can call them. Also, it's now SubscriptionStore. Also creates a SubscriptionRequest type that is used to create a new Subscription instance, along with a Validate method on it, to detect errors when creating a SubscriptionRequest. Update our CreateSubscription function to be New, and have it take a SubscriptionRequest, a Stripe instance, and a SubscriptionStore as arguments. It'll create the Subscription in the SubscriptionStore, create a customer in Stripe, and create the subscription in Stripe, then associate the Stripe subscription with the created Subscription. Also, fix our StripeSubscriptionChange function to correctly equate a missing/zero Unix timestamp from Stripe with a missing/zero time.Time.
.hgignore memstore.go stripe.go subscription.go subscription_memstore.go subscription_postgres.go subscription_store_test.go
1.1 --- a/.hgignore Tue Jun 16 23:09:59 2015 -0400 1.2 +++ b/.hgignore Mon Jun 22 18:34:07 2015 -0400 1.3 @@ -1,2 +1,3 @@ 1.4 cover.out 1.5 .swp 1.6 +subscriptionsd/subscriptionsd
2.1 --- a/memstore.go Tue Jun 16 23:09:59 2015 -0400 2.2 +++ b/memstore.go Mon Jun 22 18:34:07 2015 -0400 2.3 @@ -19,7 +19,7 @@ 2.4 } 2.5 } 2.6 2.7 -func (m *Memstore) reset() error { 2.8 +func (m *Memstore) Reset() error { 2.9 m.subscriptionLock.Lock() 2.10 defer m.subscriptionLock.Unlock() 2.11
3.1 --- a/stripe.go Tue Jun 16 23:09:59 2015 -0400 3.2 +++ b/stripe.go Mon Jun 22 18:34:07 2015 -0400 3.3 @@ -1,6 +1,7 @@ 3.4 package subscriptions 3.5 3.6 import ( 3.7 + "log" 3.8 "time" 3.9 3.10 "code.secondbit.org/uuid.hg" 3.11 @@ -58,19 +59,20 @@ 3.12 return resp, nil 3.13 } 3.14 3.15 -func CreateSubscription(token, email string, subscription Subscription, s Stripe, store subscriptionStore) error { 3.16 +func New(req SubscriptionRequest, s Stripe, store SubscriptionStore) (Subscription, error) { 3.17 + subscription := SubscriptionFromRequest(req) 3.18 // create the subscription in our datastore 3.19 // this will fail if they already have a subscription, which prevents duplicate/orphaned Stripe customers being created 3.20 - err := store.createSubscription(subscription) 3.21 + err := store.CreateSubscription(subscription) 3.22 if err != nil { 3.23 - return err 3.24 + return subscription, err 3.25 } 3.26 3.27 // create the customer in Stripe, storing the token for reuse 3.28 - customer, err := CreateStripeCustomer(token, email, subscription.UserID, s) 3.29 + customer, err := CreateStripeCustomer(req.StripeToken, req.Email, req.UserID, s) 3.30 if err != nil { 3.31 // TODO: delete subscription object 3.32 - return err 3.33 + return subscription, err 3.34 } 3.35 3.36 // create the subscription in Stripe, storing the ID for tracking and associating purposes 3.37 @@ -78,17 +80,18 @@ 3.38 if err != nil { 3.39 // TODO: delete customer 3.40 // TODO: delete subscription object 3.41 - return err 3.42 + return subscription, err 3.43 } 3.44 3.45 // update our subscription in the datastore with the latest information from Stripe 3.46 change := StripeSubscriptionChange(subscription, *stripeSub) 3.47 - err = store.updateSubscription(subscription.UserID, change) 3.48 + err = store.UpdateSubscription(subscription.UserID, change) 3.49 if err != nil { 3.50 - // TODO: log an error, manually retry later? 3.51 - return err 3.52 + log.Printf("Error pairing Stripe subscription %s to user %s: %+v\nUser needs to have their subscription updated manually.", change.StripeSubscription, req.UserID, err) 3.53 + return subscription, nil 3.54 } 3.55 - return nil 3.56 + subscription.ApplyChange(change) 3.57 + return subscription, nil 3.58 } 3.59 3.60 func StripeSubscriptionChange(orig Subscription, subscription stripe.Sub) SubscriptionChange { 3.61 @@ -103,23 +106,23 @@ 3.62 if subscription.EndCancel != orig.Canceling { 3.63 change.Canceling = &subscription.EndCancel 3.64 } 3.65 - if !time.Unix(subscription.TrialStart, 0).Equal(orig.TrialStart) { 3.66 + if !time.Unix(subscription.TrialStart, 0).Equal(orig.TrialStart) && !(subscription.TrialStart == 0 && orig.TrialStart.IsZero()) { 3.67 trialStart := time.Unix(subscription.TrialStart, 0) 3.68 change.TrialStart = &trialStart 3.69 } 3.70 - if !time.Unix(subscription.TrialEnd, 0).Equal(orig.TrialEnd) { 3.71 + if !time.Unix(subscription.TrialEnd, 0).Equal(orig.TrialEnd) && !(subscription.TrialEnd == 0 && orig.TrialEnd.IsZero()) { 3.72 trialEnd := time.Unix(subscription.TrialEnd, 0) 3.73 change.TrialEnd = &trialEnd 3.74 } 3.75 - if !time.Unix(subscription.PeriodStart, 0).Equal(orig.PeriodStart) { 3.76 + if !time.Unix(subscription.PeriodStart, 0).Equal(orig.PeriodStart) && !(subscription.PeriodStart == 0 && orig.PeriodStart.IsZero()) { 3.77 periodStart := time.Unix(subscription.PeriodStart, 0) 3.78 change.PeriodStart = &periodStart 3.79 } 3.80 - if !time.Unix(subscription.PeriodEnd, 0).Equal(orig.PeriodEnd) { 3.81 + if !time.Unix(subscription.PeriodEnd, 0).Equal(orig.PeriodEnd) && !(subscription.PeriodEnd == 0 && orig.PeriodEnd.IsZero()) { 3.82 periodEnd := time.Unix(subscription.PeriodEnd, 0) 3.83 change.PeriodEnd = &periodEnd 3.84 } 3.85 - if !time.Unix(subscription.Canceled, 0).Equal(orig.CanceledAt) { 3.86 + if !time.Unix(subscription.Canceled, 0).Equal(orig.CanceledAt) && !(subscription.Canceled == 0 && orig.CanceledAt.IsZero()) { 3.87 canceledAt := time.Unix(subscription.Canceled, 0) 3.88 change.CanceledAt = &canceledAt 3.89 }
4.1 --- a/subscription.go Tue Jun 16 23:09:59 2015 -0400 4.2 +++ b/subscription.go Mon Jun 22 18:34:07 2015 -0400 4.3 @@ -4,6 +4,7 @@ 4.4 "errors" 4.5 "time" 4.6 4.7 + "code.secondbit.org/api.hg" 4.8 "code.secondbit.org/uuid.hg" 4.9 ) 4.10 4.11 @@ -25,6 +26,10 @@ 4.12 // ErrNoSubscriptionID is returned when one or more Subscription IDs 4.13 // are required, but none are provided. 4.14 ErrNoSubscriptionID = errors.New("no Subscription ID provided") 4.15 + 4.16 + planOptions = []string{"basic_monthly", "basic_yearly", "supporter_monthly", "supporter_yearly"} 4.17 + 4.18 + Version string 4.19 ) 4.20 4.21 // Subscription represents the state of a user's payments. It holds 4.22 @@ -32,20 +37,20 @@ 4.23 // should be charged, how to charge a user and how much to charge 4.24 // the user. 4.25 type Subscription struct { 4.26 - UserID uuid.ID 4.27 - StripeSubscription string 4.28 - Plan string 4.29 - Status string 4.30 - Canceling bool 4.31 - Created time.Time 4.32 - TrialStart time.Time 4.33 - TrialEnd time.Time 4.34 - PeriodStart time.Time 4.35 - PeriodEnd time.Time 4.36 - CanceledAt time.Time 4.37 - FailedChargeAttempts int 4.38 - LastFailedCharge time.Time 4.39 - LastNotified time.Time 4.40 + UserID uuid.ID `json:"user_id"` 4.41 + StripeSubscription string `json:"stripe_subscription"` 4.42 + Plan string `json:"plan"` 4.43 + Status string `json:"status"` 4.44 + Canceling bool `json:"canceling"` 4.45 + Created time.Time `json:"created"` 4.46 + TrialStart time.Time `json:"trial_start,omitempty"` 4.47 + TrialEnd time.Time `json:"trial_end,omitempty"` 4.48 + PeriodStart time.Time `json:"period_start,omitempty"` 4.49 + PeriodEnd time.Time `json:"period_end,omitempty"` 4.50 + CanceledAt time.Time `json:"canceled_at,omitempty"` 4.51 + FailedChargeAttempts int `json:"failed_charge_attempts"` 4.52 + LastFailedCharge time.Time `json:"last_failed_charge,omitempty"` 4.53 + LastNotified time.Time `json:"last_notified,omitempty"` 4.54 } 4.55 4.56 // SubscriptionChange represents desired changes to a Subscription 4.57 @@ -148,6 +153,53 @@ 4.58 } 4.59 } 4.60 4.61 +type SubscriptionRequest struct { 4.62 + UserID uuid.ID `json:"user_id"` 4.63 + Email string `json:"email"` 4.64 + StripeToken string `json:"stripe_token"` 4.65 + Plan string `json:"plan"` 4.66 +} 4.67 + 4.68 +func (req SubscriptionRequest) Validate(user uuid.ID, admin bool) []api.RequestError { 4.69 + var errors []api.RequestError 4.70 + if req.UserID == nil { 4.71 + errors = append(errors, api.RequestError{Slug: api.RequestErrMissing, Field: "/user_id"}) 4.72 + } else if !req.UserID.Equal(user) && !admin { 4.73 + errors = append(errors, api.RequestError{Slug: api.RequestErrAccessDenied, Field: "/user_id"}) 4.74 + } 4.75 + if req.Email == "" { 4.76 + errors = append(errors, api.RequestError{Slug: api.RequestErrMissing, Field: "/email"}) 4.77 + } 4.78 + if req.StripeToken == "" { 4.79 + errors = append(errors, api.RequestError{Slug: api.RequestErrMissing, Field: "/stripe_token"}) 4.80 + } 4.81 + if req.Plan == "" { 4.82 + errors = append(errors, api.RequestError{Slug: api.RequestErrMissing, Field: "/plan"}) 4.83 + } else { 4.84 + var acceptablePlan bool 4.85 + for _, p := range planOptions { 4.86 + if req.Plan == p { 4.87 + acceptablePlan = true 4.88 + break 4.89 + } 4.90 + } 4.91 + if !acceptablePlan { 4.92 + errors = append(errors, api.RequestError{Slug: api.RequestErrInvalidValue, Field: "/plan"}) 4.93 + } 4.94 + } 4.95 + return errors 4.96 +} 4.97 + 4.98 +func SubscriptionFromRequest(req SubscriptionRequest) Subscription { 4.99 + return Subscription{ 4.100 + UserID: req.UserID, 4.101 + StripeSubscription: req.StripeToken, 4.102 + Plan: req.Plan, 4.103 + Created: time.Now(), 4.104 + TrialStart: time.Now(), 4.105 + } 4.106 +} 4.107 + 4.108 // SubscriptionStats represents a set of statistics about our Subscription 4.109 // data that will be exposed to the Prometheus scraper. 4.110 type SubscriptionStats struct { 4.111 @@ -170,11 +222,11 @@ 4.112 // was omitted." 4.113 } 4.114 4.115 -type subscriptionStore interface { 4.116 - reset() error 4.117 - createSubscription(sub Subscription) error 4.118 - updateSubscription(id uuid.ID, change SubscriptionChange) error 4.119 - deleteSubscription(id uuid.ID) error 4.120 - getSubscriptions(ids []uuid.ID) (map[string]Subscription, error) 4.121 - getSubscriptionStats() (SubscriptionStats, error) 4.122 +type SubscriptionStore interface { 4.123 + Reset() error 4.124 + CreateSubscription(sub Subscription) error 4.125 + UpdateSubscription(id uuid.ID, change SubscriptionChange) error 4.126 + DeleteSubscription(id uuid.ID) error 4.127 + GetSubscriptions(ids []uuid.ID) (map[string]Subscription, error) 4.128 + GetSubscriptionStats() (SubscriptionStats, error) 4.129 }
5.1 --- a/subscription_memstore.go Tue Jun 16 23:09:59 2015 -0400 5.2 +++ b/subscription_memstore.go Mon Jun 22 18:34:07 2015 -0400 5.3 @@ -13,7 +13,7 @@ 5.4 return false 5.5 } 5.6 5.7 -func (m *Memstore) createSubscription(sub Subscription) error { 5.8 +func (m *Memstore) CreateSubscription(sub Subscription) error { 5.9 m.subscriptionLock.Lock() 5.10 defer m.subscriptionLock.Unlock() 5.11 5.12 @@ -27,7 +27,7 @@ 5.13 return nil 5.14 } 5.15 5.16 -func (m *Memstore) updateSubscription(id uuid.ID, change SubscriptionChange) error { 5.17 +func (m *Memstore) UpdateSubscription(id uuid.ID, change SubscriptionChange) error { 5.18 if change.IsEmpty() { 5.19 return ErrSubscriptionChangeEmpty 5.20 } 5.21 @@ -49,7 +49,7 @@ 5.22 return nil 5.23 } 5.24 5.25 -func (m *Memstore) deleteSubscription(id uuid.ID) error { 5.26 +func (m *Memstore) DeleteSubscription(id uuid.ID) error { 5.27 m.subscriptionLock.Lock() 5.28 defer m.subscriptionLock.Unlock() 5.29 5.30 @@ -61,7 +61,7 @@ 5.31 return nil 5.32 } 5.33 5.34 -func (m *Memstore) getSubscriptions(ids []uuid.ID) (map[string]Subscription, error) { 5.35 +func (m *Memstore) GetSubscriptions(ids []uuid.ID) (map[string]Subscription, error) { 5.36 if len(ids) < 1 { 5.37 return map[string]Subscription{}, ErrNoSubscriptionID 5.38 } 5.39 @@ -80,7 +80,7 @@ 5.40 return result, nil 5.41 } 5.42 5.43 -func (m *Memstore) getSubscriptionStats() (SubscriptionStats, error) { 5.44 +func (m *Memstore) GetSubscriptionStats() (SubscriptionStats, error) { 5.45 m.subscriptionLock.RLock() 5.46 defer m.subscriptionLock.RUnlock() 5.47
6.1 --- a/subscription_postgres.go Tue Jun 16 23:09:59 2015 -0400 6.2 +++ b/subscription_postgres.go Mon Jun 22 18:34:07 2015 -0400 6.3 @@ -21,7 +21,7 @@ 6.4 return query.FlushExpressions(" ") 6.5 } 6.6 6.7 -func (p Postgres) reset() error { 6.8 +func (p Postgres) Reset() error { 6.9 query := p.resetSQL() 6.10 _, err := p.Exec(query.String(), query.Args...) 6.11 if err != nil { 6.12 @@ -39,7 +39,7 @@ 6.13 return query.FlushExpressions(" ") 6.14 } 6.15 6.16 -func (p Postgres) createSubscription(sub Subscription) error { 6.17 +func (p Postgres) CreateSubscription(sub Subscription) error { 6.18 query := p.createSubscriptionSQL(sub) 6.19 _, err := p.Exec(query.String(), query.Args...) 6.20 if e, ok := err.(*pq.Error); ok && e.Constraint == "subscriptions_pkey" { 6.21 @@ -71,7 +71,7 @@ 6.22 return query.FlushExpressions(" ") 6.23 } 6.24 6.25 -func (p Postgres) updateSubscription(id uuid.ID, change SubscriptionChange) error { 6.26 +func (p Postgres) UpdateSubscription(id uuid.ID, change SubscriptionChange) error { 6.27 if change.IsEmpty() { 6.28 return ErrSubscriptionChangeEmpty 6.29 } 6.30 @@ -101,7 +101,7 @@ 6.31 return query.FlushExpressions(" ") 6.32 } 6.33 6.34 -func (p Postgres) deleteSubscription(id uuid.ID) error { 6.35 +func (p Postgres) DeleteSubscription(id uuid.ID) error { 6.36 query := p.deleteSubscriptionSQL(id) 6.37 res, err := p.Exec(query.String(), query.Args...) 6.38 if err != nil { 6.39 @@ -131,7 +131,7 @@ 6.40 return query.FlushExpressions(" ") 6.41 } 6.42 6.43 -func (p Postgres) getSubscriptions(ids []uuid.ID) (map[string]Subscription, error) { 6.44 +func (p Postgres) GetSubscriptions(ids []uuid.ID) (map[string]Subscription, error) { 6.45 results := map[string]Subscription{} 6.46 if len(ids) < 1 { 6.47 return results, ErrNoSubscriptionID 6.48 @@ -190,7 +190,7 @@ 6.49 return query.FlushExpressions(" ") 6.50 } 6.51 6.52 -func (p Postgres) getSubscriptionStats() (SubscriptionStats, error) { 6.53 +func (p Postgres) GetSubscriptionStats() (SubscriptionStats, error) { 6.54 stats := SubscriptionStats{ 6.55 Plans: map[string]int64{}, 6.56 }
7.1 --- a/subscription_store_test.go Tue Jun 16 23:09:59 2015 -0400 7.2 +++ b/subscription_store_test.go Mon Jun 22 18:34:07 2015 -0400 7.3 @@ -34,7 +34,7 @@ 7.4 } 7.5 } 7.6 7.7 -var testSubscriptionStores = []subscriptionStore{ 7.8 +var testSubscriptionStores = []SubscriptionStore{ 7.9 NewMemstore(), 7.10 } 7.11 7.12 @@ -124,7 +124,7 @@ 7.13 7.14 func TestCreateSubscription(t *testing.T) { 7.15 for _, store := range testSubscriptionStores { 7.16 - err := store.reset() 7.17 + err := store.Reset() 7.18 if err != nil { 7.19 t.Fatalf("Error resetting %T: %+v\n", store, err) 7.20 } 7.21 @@ -136,11 +136,11 @@ 7.22 TrialStart: time.Now().Round(time.Millisecond), 7.23 TrialEnd: time.Now().Round(time.Millisecond).Add(time.Hour * 24 * 31), 7.24 } 7.25 - err = store.createSubscription(sub) 7.26 + err = store.CreateSubscription(sub) 7.27 if err != nil { 7.28 t.Errorf("Error creating subscription in %T: %+v\n", store, err) 7.29 } 7.30 - retrieved, err := store.getSubscriptions([]uuid.ID{sub.UserID}) 7.31 + retrieved, err := store.GetSubscriptions([]uuid.ID{sub.UserID}) 7.32 if err != nil { 7.33 t.Errorf("Error retrieving subscription from %T: %+v\n", store, err) 7.34 } 7.35 @@ -151,17 +151,17 @@ 7.36 if !ok { 7.37 t.Errorf("Expected %s to be %v, got %v from %T\n", field, expected, result, store) 7.38 } 7.39 - err = store.createSubscription(sub) 7.40 + err = store.CreateSubscription(sub) 7.41 if err != ErrSubscriptionAlreadyExists { 7.42 t.Errorf("Unexpected error creating subscription in %T (wanted %+v): %+v\n", store, ErrSubscriptionAlreadyExists, err) 7.43 } 7.44 sub.UserID = uuid.NewID() 7.45 - err = store.createSubscription(sub) 7.46 + err = store.CreateSubscription(sub) 7.47 if err != ErrStripeSubscriptionAlreadyExists { 7.48 t.Errorf("Unexpected error creating subscription in %T (wanted %+v): %#+v\n", store, ErrStripeSubscriptionAlreadyExists, err) 7.49 } 7.50 sub.StripeSubscription = "stripeSubscription2" 7.51 - err = store.createSubscription(sub) 7.52 + err = store.CreateSubscription(sub) 7.53 if err != nil { 7.54 t.Errorf("Error creating subscription in %T: %+v\n", store, err) 7.55 } 7.56 @@ -188,11 +188,11 @@ 7.57 } 7.58 7.59 for _, store := range testSubscriptionStores { 7.60 - err := store.reset() 7.61 + err := store.Reset() 7.62 if err != nil { 7.63 t.Fatalf("Error resetting %T: %+v\n", store, err) 7.64 } 7.65 - err = store.createSubscription(sub) 7.66 + err = store.CreateSubscription(sub) 7.67 if err != nil { 7.68 t.Fatalf("Error saving subscription in %T: %s\n", store, err) 7.69 } 7.70 @@ -292,11 +292,11 @@ 7.71 if !match { 7.72 t.Errorf("Expected field `%s` to be `%v`, got `%v`\n", field, expected, got) 7.73 } 7.74 - err = store.updateSubscription(sub.UserID, change) 7.75 + err = store.UpdateSubscription(sub.UserID, change) 7.76 if err != nil { 7.77 t.Errorf("Error updating subscription in %T: %s\n", store, err) 7.78 } 7.79 - retrieved, err := store.getSubscriptions([]uuid.ID{sub.UserID}) 7.80 + retrieved, err := store.GetSubscriptions([]uuid.ID{sub.UserID}) 7.81 if err != nil { 7.82 t.Errorf("Error getting subscription from %T: %s\n", store, err) 7.83 } 7.84 @@ -311,22 +311,22 @@ 7.85 sub = result 7.86 } 7.87 7.88 - err = store.createSubscription(sub2) 7.89 + err = store.CreateSubscription(sub2) 7.90 if err != nil { 7.91 t.Fatalf("Error saving subscription in %T: %+v\n", store, err) 7.92 } 7.93 change := SubscriptionChange{} 7.94 - err = store.updateSubscription(sub.UserID, change) 7.95 + err = store.UpdateSubscription(sub.UserID, change) 7.96 if err != ErrSubscriptionChangeEmpty { 7.97 t.Errorf("Expected err to be %+v, but got %+v from %T\n", ErrSubscriptionChangeEmpty, err, store) 7.98 } 7.99 stripeSubscription := sub2.StripeSubscription 7.100 change.StripeSubscription = &stripeSubscription 7.101 - err = store.updateSubscription(uuid.NewID(), change) 7.102 + err = store.UpdateSubscription(uuid.NewID(), change) 7.103 if err != ErrSubscriptionNotFound { 7.104 t.Errorf("Expected err to be %+v, but got %+v from %T\n", ErrSubscriptionNotFound, err, store) 7.105 } 7.106 - err = store.updateSubscription(sub.UserID, change) 7.107 + err = store.UpdateSubscription(sub.UserID, change) 7.108 if err != ErrStripeSubscriptionAlreadyExists { 7.109 t.Errorf("Expected err to be %+v, but got %+v from %T\n", ErrStripeSubscriptionAlreadyExists, err, store) 7.110 } 7.111 @@ -335,7 +335,7 @@ 7.112 7.113 func TestDeleteSubscription(t *testing.T) { 7.114 for _, store := range testSubscriptionStores { 7.115 - err := store.reset() 7.116 + err := store.Reset() 7.117 if err != nil { 7.118 t.Fatalf("Error resetting %T: %+v\n", store, err) 7.119 } 7.120 @@ -347,19 +347,19 @@ 7.121 UserID: uuid.NewID(), 7.122 StripeSubscription: "stripeSubscription2", 7.123 } 7.124 - err = store.createSubscription(sub1) 7.125 + err = store.CreateSubscription(sub1) 7.126 if err != nil { 7.127 t.Fatalf("Error creating %+v in %T: %+v\n", sub1, store, err) 7.128 } 7.129 - err = store.createSubscription(sub2) 7.130 + err = store.CreateSubscription(sub2) 7.131 if err != nil { 7.132 t.Fatalf("Error creating %+v in %T: %+v\n", sub2, store, err) 7.133 } 7.134 - err = store.deleteSubscription(sub1.UserID) 7.135 + err = store.DeleteSubscription(sub1.UserID) 7.136 if err != nil { 7.137 t.Fatalf("Error deleting %+v in %T: %+v\n", sub1, store, err) 7.138 } 7.139 - retrieved, err := store.getSubscriptions([]uuid.ID{sub1.UserID, sub2.UserID}) 7.140 + retrieved, err := store.GetSubscriptions([]uuid.ID{sub1.UserID, sub2.UserID}) 7.141 if err != nil { 7.142 t.Errorf("Error retrieving subscriptions from %T: %+v\n", store, err) 7.143 } 7.144 @@ -371,7 +371,7 @@ 7.145 if !ok { 7.146 t.Errorf("Expected to retrieve %s from %T, but missing was %+v\n", sub2.UserID.String(), store, missing) 7.147 } 7.148 - err = store.deleteSubscription(sub1.UserID) 7.149 + err = store.DeleteSubscription(sub1.UserID) 7.150 if err != ErrSubscriptionNotFound { 7.151 t.Errorf("Expected err to be %+v, but got %+v from %T\n", ErrSubscriptionNotFound, err, store) 7.152 } 7.153 @@ -380,7 +380,7 @@ 7.154 7.155 func TestGetSubscriptions(t *testing.T) { 7.156 for _, store := range testSubscriptionStores { 7.157 - err := store.reset() 7.158 + err := store.Reset() 7.159 if err != nil { 7.160 t.Fatalf("Error resetting %T: %+v\n", store, err) 7.161 } 7.162 @@ -411,23 +411,23 @@ 7.163 PeriodEnd: time.Now().Round(time.Millisecond), 7.164 Status: "unpaid", 7.165 } 7.166 - err = store.createSubscription(sub1) 7.167 + err = store.CreateSubscription(sub1) 7.168 if err != nil { 7.169 t.Fatalf("Error creating %+v in %T: %+v\n", sub1, store, err) 7.170 } 7.171 - err = store.createSubscription(sub2) 7.172 + err = store.CreateSubscription(sub2) 7.173 if err != nil { 7.174 t.Fatalf("Error creating %+v in %T: %+v\n", sub1, store, err) 7.175 } 7.176 - err = store.createSubscription(sub3) 7.177 + err = store.CreateSubscription(sub3) 7.178 if err != nil { 7.179 t.Fatalf("Error creating %+v in %T: %+v\n", sub1, store, err) 7.180 } 7.181 - retrieved, err := store.getSubscriptions([]uuid.ID{}) 7.182 + retrieved, err := store.GetSubscriptions([]uuid.ID{}) 7.183 if err != ErrNoSubscriptionID { 7.184 t.Errorf("Error retrieving no subscriptions from %T. Expected %+v, got %+v\n", store, ErrNoSubscriptionID, err) 7.185 } 7.186 - retrieved, err = store.getSubscriptions([]uuid.ID{sub1.UserID}) 7.187 + retrieved, err = store.GetSubscriptions([]uuid.ID{sub1.UserID}) 7.188 if err != nil { 7.189 t.Errorf("Error retrieving %s from %T: %+v\n", sub1.UserID, store, err) 7.190 } 7.191 @@ -436,7 +436,7 @@ 7.192 t.Logf("Results: %+v\n", retrieved) 7.193 t.Errorf("Expected %+v to be in the results, was not for %T.\n", missing, store) 7.194 } 7.195 - retrieved, err = store.getSubscriptions([]uuid.ID{sub1.UserID, sub2.UserID}) 7.196 + retrieved, err = store.GetSubscriptions([]uuid.ID{sub1.UserID, sub2.UserID}) 7.197 if err != nil { 7.198 t.Errorf("Error retrieving %s and %s from %T: %+v\n", sub1.UserID, sub2.UserID, store, err) 7.199 } 7.200 @@ -445,7 +445,7 @@ 7.201 t.Logf("Results: %+v\n", retrieved) 7.202 t.Errorf("Expected %+v to be in the results, was not for %T.\n", missing, store) 7.203 } 7.204 - retrieved, err = store.getSubscriptions([]uuid.ID{sub1.UserID, sub3.UserID}) 7.205 + retrieved, err = store.GetSubscriptions([]uuid.ID{sub1.UserID, sub3.UserID}) 7.206 if err != nil { 7.207 t.Errorf("Error retrieving %s and %s from %T: %+v\n", sub1.UserID, sub3.UserID, store, err) 7.208 } 7.209 @@ -454,7 +454,7 @@ 7.210 t.Logf("Results: %+v\n", retrieved) 7.211 t.Errorf("Expected %+v to be in the results, was not for %T.\n", missing, store) 7.212 } 7.213 - retrieved, err = store.getSubscriptions([]uuid.ID{sub1.UserID, sub2.UserID, sub3.UserID}) 7.214 + retrieved, err = store.GetSubscriptions([]uuid.ID{sub1.UserID, sub2.UserID, sub3.UserID}) 7.215 if err != nil { 7.216 t.Errorf("Error retrieving %s, %s, and %s from %T: %+v\n", sub1.UserID, sub2.UserID, sub3.UserID, store, err) 7.217 } 7.218 @@ -463,7 +463,7 @@ 7.219 t.Logf("Results: %+v\n", retrieved) 7.220 t.Errorf("Expected %+v to be in the results, was not for %T.\n", missing, store) 7.221 } 7.222 - retrieved, err = store.getSubscriptions([]uuid.ID{sub2.UserID}) 7.223 + retrieved, err = store.GetSubscriptions([]uuid.ID{sub2.UserID}) 7.224 if err != nil { 7.225 t.Errorf("Error retrieving %s from %T: %+v\n", sub2.UserID, store, err) 7.226 } 7.227 @@ -472,7 +472,7 @@ 7.228 t.Logf("Results: %+v\n", retrieved) 7.229 t.Errorf("Expected %+v to be in the results, was not for %T.\n", missing, store) 7.230 } 7.231 - retrieved, err = store.getSubscriptions([]uuid.ID{sub2.UserID, sub3.UserID}) 7.232 + retrieved, err = store.GetSubscriptions([]uuid.ID{sub2.UserID, sub3.UserID}) 7.233 if err != nil { 7.234 t.Errorf("Error retrieving %s and %s from %T: %+v\n", sub2.UserID, sub3.UserID, store, err) 7.235 } 7.236 @@ -481,7 +481,7 @@ 7.237 t.Logf("Results: %+v\n", retrieved) 7.238 t.Errorf("Expected %+v to be in the results, was not for %T.\n", missing, store) 7.239 } 7.240 - retrieved, err = store.getSubscriptions([]uuid.ID{sub3.UserID}) 7.241 + retrieved, err = store.GetSubscriptions([]uuid.ID{sub3.UserID}) 7.242 if err != nil { 7.243 t.Errorf("Error retrieving %s from %T: %+v\n", sub3.UserID, store, err) 7.244 } 7.245 @@ -490,14 +490,14 @@ 7.246 t.Logf("Results: %+v\n", retrieved) 7.247 t.Errorf("Expected %+v to be in the results, was not for %T.\n", missing, store) 7.248 } 7.249 - retrieved, err = store.getSubscriptions([]uuid.ID{uuid.NewID()}) 7.250 + retrieved, err = store.GetSubscriptions([]uuid.ID{uuid.NewID()}) 7.251 if err != nil { 7.252 t.Errorf("Error retrieving non-existent ID from %T: %+v\n", store, err) 7.253 } 7.254 if len(retrieved) != 0 { 7.255 t.Errorf("Expected no results, %T returned %+v\n", store, retrieved) 7.256 } 7.257 - retrieved, err = store.getSubscriptions([]uuid.ID{sub1.UserID, sub2.UserID, uuid.NewID(), sub3.UserID}) 7.258 + retrieved, err = store.GetSubscriptions([]uuid.ID{sub1.UserID, sub2.UserID, uuid.NewID(), sub3.UserID}) 7.259 if err != nil { 7.260 t.Errorf("Error retrieving non-existent ID from %T: %+v\n", store, err) 7.261 } 7.262 @@ -514,7 +514,7 @@ 7.263 7.264 func TestGetSubscriptionStats(t *testing.T) { 7.265 for _, store := range testSubscriptionStores { 7.266 - err := store.reset() 7.267 + err := store.Reset() 7.268 if err != nil { 7.269 t.Fatalf("Error resetting %T: %+v\n", store, err) 7.270 } 7.271 @@ -530,11 +530,11 @@ 7.272 Plan: "plan2", 7.273 Status: "past_due", 7.274 } 7.275 - err = store.createSubscription(sub1) 7.276 + err = store.CreateSubscription(sub1) 7.277 if err != nil { 7.278 t.Fatalf("Error creating %+v in %T: %+v\n", sub1, store, err) 7.279 } 7.280 - stats, err := store.getSubscriptionStats() 7.281 + stats, err := store.GetSubscriptionStats() 7.282 if err != nil { 7.283 t.Errorf("Error getting stats from %T: %+v\n", store, err) 7.284 } 7.285 @@ -549,11 +549,11 @@ 7.286 if !ok { 7.287 t.Errorf("Expected %s to be %+v, got %+v from %T\n", field, expected, results, store) 7.288 } 7.289 - err = store.createSubscription(sub2) 7.290 + err = store.CreateSubscription(sub2) 7.291 if err != nil { 7.292 t.Fatalf("Error creating %+v in %T: %+v\n", sub2, store, err) 7.293 } 7.294 - stats, err = store.getSubscriptionStats() 7.295 + stats, err = store.GetSubscriptionStats() 7.296 if err != nil { 7.297 t.Errorf("Error getting status from %T: %+v\n", store, err) 7.298 } 7.299 @@ -569,11 +569,11 @@ 7.300 if !ok { 7.301 t.Errorf("Expected %s to be %+v, got %+v from %T\n", field, expected, results, store) 7.302 } 7.303 - err = store.deleteSubscription(sub1.UserID) 7.304 + err = store.DeleteSubscription(sub1.UserID) 7.305 if err != nil { 7.306 t.Errorf("Error deleting subscription from %T: %+v\n", store, err) 7.307 } 7.308 - stats, err = store.getSubscriptionStats() 7.309 + stats, err = store.GetSubscriptionStats() 7.310 if err != nil { 7.311 t.Errorf("Error getting status from %T: %+v\n", store, err) 7.312 }