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.
4 "code.secondbit.org/uuid.hg"
7 func stripeSubscriptionInMemstore(stripeSubscription string, m *Memstore) bool {
8 for _, sub := range m.subscriptions {
9 if sub.StripeSubscription == stripeSubscription {
16 func (m *Memstore) CreateSubscription(sub Subscription) error {
17 m.subscriptionLock.Lock()
18 defer m.subscriptionLock.Unlock()
20 if _, ok := m.subscriptions[sub.UserID.String()]; ok {
21 return ErrSubscriptionAlreadyExists
23 if stripeSubscriptionInMemstore(sub.StripeSubscription, m) {
24 return ErrStripeSubscriptionAlreadyExists
26 m.subscriptions[sub.UserID.String()] = sub
30 func (m *Memstore) UpdateSubscription(id uuid.ID, change SubscriptionChange) error {
32 return ErrSubscriptionChangeEmpty
35 m.subscriptionLock.Lock()
36 defer m.subscriptionLock.Unlock()
38 s, ok := m.subscriptions[id.String()]
40 return ErrSubscriptionNotFound
42 if change.StripeSubscription != nil {
43 if stripeSubscriptionInMemstore(*change.StripeSubscription, m) {
44 return ErrStripeSubscriptionAlreadyExists
48 m.subscriptions[id.String()] = s
52 func (m *Memstore) DeleteSubscription(id uuid.ID) error {
53 m.subscriptionLock.Lock()
54 defer m.subscriptionLock.Unlock()
56 _, ok := m.subscriptions[id.String()]
58 return ErrSubscriptionNotFound
60 delete(m.subscriptions, id.String())
64 func (m *Memstore) GetSubscriptions(ids []uuid.ID) (map[string]Subscription, error) {
66 return map[string]Subscription{}, ErrNoSubscriptionID
68 m.subscriptionLock.RLock()
69 defer m.subscriptionLock.RUnlock()
71 result := map[string]Subscription{}
73 for _, id := range ids {
74 s, ok := m.subscriptions[id.String()]
78 result[s.UserID.String()] = s
83 func (m *Memstore) GetSubscriptionStats() (SubscriptionStats, error) {
84 m.subscriptionLock.RLock()
85 defer m.subscriptionLock.RUnlock()
87 stats := SubscriptionStats{
88 Plans: map[string]int64{},
91 for _, subscription := range m.subscriptions {
93 stats.Plans[subscription.Plan]++
95 if subscription.Canceling {
98 if subscription.Status == "past_due" || subscription.Status == "unpaid" {