ducky/subscriptions
ducky/subscriptions/subscription_memstore.go
Add comments, move ChangingSystemProperties to the api package. Add comments to all our exported types and variables in subscription.go, both to make golint happy and because it's good to have comments. Move the subscriptions.ChangingSystemProperties helper to api.changingSystemProperties, because it returns API-specific strings and there's no real reason it has to be in the subscriptions package--everything it needs to work on is exported.
1 package subscriptions
3 import (
4 "code.secondbit.org/uuid.hg"
5 )
7 func stripeSubscriptionInMemstore(stripeSubscription string, m *Memstore) bool {
8 for _, sub := range m.subscriptions {
9 if sub.StripeSubscription == stripeSubscription {
10 return true
11 }
12 }
13 return false
14 }
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
22 }
23 if stripeSubscriptionInMemstore(sub.StripeSubscription, m) {
24 return ErrStripeSubscriptionAlreadyExists
25 }
26 m.subscriptions[sub.UserID.String()] = sub
27 return nil
28 }
30 func (m *Memstore) UpdateSubscription(id uuid.ID, change SubscriptionChange) error {
31 if change.IsEmpty() {
32 return ErrSubscriptionChangeEmpty
33 }
35 m.subscriptionLock.Lock()
36 defer m.subscriptionLock.Unlock()
38 s, ok := m.subscriptions[id.String()]
39 if !ok {
40 return ErrSubscriptionNotFound
41 }
42 if change.StripeSubscription != nil {
43 if stripeSubscriptionInMemstore(*change.StripeSubscription, m) {
44 return ErrStripeSubscriptionAlreadyExists
45 }
46 }
47 s.ApplyChange(change)
48 m.subscriptions[id.String()] = s
49 return nil
50 }
52 func (m *Memstore) DeleteSubscription(id uuid.ID) error {
53 m.subscriptionLock.Lock()
54 defer m.subscriptionLock.Unlock()
56 _, ok := m.subscriptions[id.String()]
57 if !ok {
58 return ErrSubscriptionNotFound
59 }
60 delete(m.subscriptions, id.String())
61 return nil
62 }
64 func (m *Memstore) GetSubscriptions(ids []uuid.ID) (map[string]Subscription, error) {
65 if len(ids) < 1 {
66 return map[string]Subscription{}, ErrNoSubscriptionID
67 }
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()]
75 if !ok {
76 continue
77 }
78 result[s.UserID.String()] = s
79 }
80 return result, nil
81 }
83 func (m *Memstore) GetSubscriptionStats() (SubscriptionStats, error) {
84 m.subscriptionLock.RLock()
85 defer m.subscriptionLock.RUnlock()
87 stats := SubscriptionStats{
88 Plans: map[string]int64{},
89 }
91 for _, subscription := range m.subscriptions {
92 stats.Number++
93 stats.Plans[subscription.Plan]++
95 if subscription.Canceling {
96 stats.Canceling++
97 }
98 if subscription.Status == "past_due" || subscription.Status == "unpaid" {
99 stats.Failing++
100 }
101 }
102 return stats, nil
103 }