-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[billing] Create Stripe invoices for teams based on their usage #10713
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
* Convert the usage report so that it contains one entry for each team that registered usage during the billing period. * For each team, query Stripe to find the corresponding Customer. * Update each Customer's subscription with their used credits.
/werft run with-payment=true 👍 started the job as gitpod-build-af-update-team-usage-in-stripe.11 |
Epic! 🔥 I can take a look. 👀 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change looks good and works like a charm! ✨ So cool to see this all coming together.
Added a few optional comments/thoughts/questions, but please feel free to dismiss any of them and merge as is. 🚢
/hold
|
||
// Convert the usage report into a set of teamIds occurring in the report | ||
// Convert the usage report to sum all entries for the same team. | ||
var summedReport = make(map[string]int64) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uint64
?
var summedReport = make(map[string]int64) | |
var summedReport = make(map[string]uint64) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're using int64
elsewhere to store workspace runtimes, which already gives us way more range on the positive side than we need to store monthly usage, so I don't think a switch to uint64
is necessary.
teamIds := make([]string, 0, len(teamIdSet)) | ||
for k := range teamIdSet { | ||
teamIds = append(teamIds, k) | ||
summedReport[usageEntry.TeamID] += usageEntry.WorkspaceSeconds |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Go newbie question: There is no need to initialize new Map entries to 0
in Go? 👀 Or is this a feature of make
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, maps are initialised such that values have the default value for their type.
func FindCustomersForTeamIds(teamIds []string) { | ||
// UpdateUsage updates teams' Stripe subscriptions with usage data | ||
// `usageForTeam` is a map from team name to total workspace seconds used within a billing period. | ||
func UpdateUsage(usageForTeam map[string]int64) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uint64
?
func UpdateUsage(usageForTeam map[string]int64) error { | |
func UpdateUsage(usageForTeam map[string]uint64) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See this comment.
|
||
// workspaceSecondsToCredits converts seconds (of workspace usage) into Stripe credits. | ||
func workspaceSecondsToCredits(seconds int64) int64 { | ||
return (seconds + 59) / 60 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, that's an interesting way to round up. I guess this is equivalent to something like Math.ceil(seconds / 60)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, this is an easy way to ensure that we bill partial minutes as full minutes.
/unhold |
Description
Update teams' Stripe subscriptions with their usage credits during a given billing period.
Each time the usage reconciler runs, update Stripe invoices with usage credits for each team.
An example invoice:
(exact dollar amounts per credit are still TBD, the value is a placeholder).
Related Issue(s)
Part of #9036
How to test
n
is the lowest number not yet used.usage
component to make it run more frequently:kubectl edit deploy/usage
usage
container'sargs
field to look like:Every time the reconciler runs, the invoice should be updated with another credit (assuming the above interval of
1m
for the reconciler).Release Notes