8
8
"context"
9
9
"encoding/json"
10
10
"fmt"
11
+ "github.com/gitpod-io/gitpod/usage/pkg/db"
11
12
"os"
12
13
"strings"
13
14
@@ -17,8 +18,8 @@ import (
17
18
)
18
19
19
20
const (
20
- ReportIDMetadataKey = "reportId"
21
- TeamIDMetadataKey = "teamId "
21
+ ReportIDMetadataKey = "reportId"
22
+ AttributionIDMetadataKey = "attributionId "
22
23
)
23
24
24
25
type Client struct {
@@ -63,19 +64,14 @@ type Invoice struct {
63
64
Credits int64
64
65
}
65
66
66
- type CreditSummary struct {
67
- Credits int64
68
- ReportID string
69
- }
70
-
71
67
// UpdateUsage updates teams' Stripe subscriptions with usage data
72
68
// `usageForTeam` is a map from team name to total workspace seconds used within a billing period.
73
- func (c * Client ) UpdateUsage (ctx context.Context , creditsPerTeam map [string ] CreditSummary ) error {
74
- teamIds := make ([]string , 0 , len (creditsPerTeam ))
75
- for k := range creditsPerTeam {
76
- teamIds = append (teamIds , k )
69
+ func (c * Client ) UpdateUsage (ctx context.Context , creditsPerAttributionID map [db. AttributionID ] int64 ) error {
70
+ attributionIDs := make ([]db. AttributionID , 0 , len (creditsPerAttributionID ))
71
+ for k := range creditsPerAttributionID {
72
+ attributionIDs = append (attributionIDs , k )
77
73
}
78
- queries := queriesForCustomersWithTeamIds ( teamIds )
74
+ queries := queriesForCustomersWithAttributionIDs ( attributionIDs )
79
75
80
76
for _ , query := range queries {
81
77
log .Infof ("Searching customers in Stripe with query: %q" , query )
@@ -86,14 +82,21 @@ func (c *Client) UpdateUsage(ctx context.Context, creditsPerTeam map[string]Cred
86
82
}
87
83
88
84
for _ , customer := range customers {
89
- teamID := customer .Metadata ["teamId" ]
90
- log .Infof ("Found customer %q for teamId %q" , customer .Name , teamID )
85
+ attributionIDRaw := customer .Metadata [AttributionIDMetadataKey ]
86
+ log .Infof ("Found customer %q for attribution ID %q" , customer .Name , attributionIDRaw )
87
+
88
+ attributionID , err := db .ParseAttributionID (attributionIDRaw )
89
+ if err != nil {
90
+ log .WithError (err ).Error ("Failed to parse attribution ID from Stripe metadata." )
91
+ continue
92
+ }
91
93
92
- _ , err : = c .updateUsageForCustomer (ctx , customer , creditsPerTeam [ teamID ])
94
+ _ , err = c .updateUsageForCustomer (ctx , customer , creditsPerAttributionID [ attributionID ])
93
95
if err != nil {
94
96
log .WithField ("customer_id" , customer .ID ).
95
97
WithField ("customer_name" , customer .Name ).
96
98
WithField ("subscriptions" , customer .Subscriptions ).
99
+ WithField ("attribution_id" , attributionID ).
97
100
WithError (err ).
98
101
Errorf ("Failed to update usage." )
99
102
@@ -127,7 +130,7 @@ func (c *Client) findCustomers(ctx context.Context, query string) ([]*stripe.Cus
127
130
return customers , nil
128
131
}
129
132
130
- func (c * Client ) updateUsageForCustomer (ctx context.Context , customer * stripe.Customer , summary CreditSummary ) (* UsageRecord , error ) {
133
+ func (c * Client ) updateUsageForCustomer (ctx context.Context , customer * stripe.Customer , credits int64 ) (* UsageRecord , error ) {
131
134
subscriptions := customer .Subscriptions .Data
132
135
if len (subscriptions ) != 1 {
133
136
return nil , fmt .Errorf ("customer has an unexpected number of subscriptions %v (expected 1, got %d)" , subscriptions , len (subscriptions ))
@@ -146,15 +149,15 @@ func (c *Client) updateUsageForCustomer(ctx context.Context, customer *stripe.Cu
146
149
Context : ctx ,
147
150
},
148
151
SubscriptionItem : stripe .String (subscriptionItemId ),
149
- Quantity : stripe .Int64 (summary . Credits ),
152
+ Quantity : stripe .Int64 (credits ),
150
153
})
151
154
if err != nil {
152
155
return nil , fmt .Errorf ("failed to register usage for customer %q on subscription item %s" , customer .Name , subscriptionItemId )
153
156
}
154
157
155
158
return & UsageRecord {
156
159
SubscriptionItemID : subscriptionItemId ,
157
- Quantity : summary . Credits ,
160
+ Quantity : credits ,
158
161
}, nil
159
162
}
160
163
@@ -246,19 +249,19 @@ func (c *Client) GetInvoice(ctx context.Context, invoiceID string) (*stripe.Invo
246
249
return invoice , nil
247
250
}
248
251
249
- // queriesForCustomersWithTeamIds constructs Stripe query strings to find the Stripe Customer for each teamId
252
+ // queriesForCustomersWithAttributionIDs constructs Stripe query strings to find the Stripe Customer for each teamId
250
253
// It returns multiple queries, each being a big disjunction of subclauses so that we can process multiple teamIds in one query.
251
254
// `clausesPerQuery` is a limit enforced by the Stripe API.
252
- func queriesForCustomersWithTeamIds ( teamIds []string ) []string {
255
+ func queriesForCustomersWithAttributionIDs ( attributionIDs []db. AttributionID ) []string {
253
256
const clausesPerQuery = 10
254
257
var queries []string
255
258
sb := strings.Builder {}
256
259
257
- for i := 0 ; i < len (teamIds ); i += clausesPerQuery {
260
+ for i := 0 ; i < len (attributionIDs ); i += clausesPerQuery {
258
261
sb .Reset ()
259
- for j := 0 ; j < clausesPerQuery && i + j < len (teamIds ); j ++ {
260
- sb .WriteString (fmt .Sprintf ("metadata['%s']:'%s'" , TeamIDMetadataKey , teamIds [i + j ]))
261
- if j < clausesPerQuery - 1 && i + j < len (teamIds )- 1 {
262
+ for j := 0 ; j < clausesPerQuery && i + j < len (attributionIDs ); j ++ {
263
+ sb .WriteString (fmt .Sprintf ("metadata['%s']:'%s'" , AttributionIDMetadataKey , attributionIDs [i + j ]))
264
+ if j < clausesPerQuery - 1 && i + j < len (attributionIDs )- 1 {
262
265
sb .WriteString (" OR " )
263
266
}
264
267
}
0 commit comments