ducky/subscriptions

Paddy 2015-07-13 Parent:b240b6123548 Child:fb2c0e498e37

8:61583c1d3886 Go to Latest

ducky/subscriptions/subscription_memstore.go

Create a listener that will create subscriptions. We need a listener (as discussed in c4cfceb2f2fb) that will create a Subscription whenever an auth.Profile is created. This is the beginning of that effort. It hasn't been tested, and all the pieces aren't in place, but it's a rough skeleton. We have a Dockerfile that will correctly build a minimal container for the listener. We have a build-docker.sh script that will correctly build a binary that will be used in the Dockerfile. We have a ca-certificates.crt, which are pulled from Ubuntu, and are necessary before we can safely consume SSL endpoints. We created a small consumer script that listens for events off NSQ, and calls the appropriate endpoint for our Subscriptions API. This is untested, and it doesn't build at the moment, but that's awaiting changes in the code.secondbit.org/auth.hg package. Finally, we have a wrapper.sh file that will expose the Stripe secret key being used from a Kubernetes secret file as an environment variable, instead.

History
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 }