-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[usage] Lookup stripe customers for each team in a usage report #10674
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
Ignore `apikeys` file, used for local testing.
When the `run` subcommand is invoked, authenticate to the Stripe API using API keys.
Build and test the query that will be used to retrieve a list of stripe customers matching a given set of teamIds.
For each teamId in the usage report, query the Stripe API to find Stripe Customer records that correspond to those teamIds.
ac10292
to
2ec4500
Compare
started the job as gitpod-build-af-generate-test-invoice.9 because the annotations in the pull request description changed |
started the job as gitpod-build-af-generate-test-invoice.10 because the annotations in the pull request description changed |
Many thanks! Will take a look. 👀 |
@@ -0,0 +1 @@ | |||
apikeys |
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.
Interesting -- is placing an untracked, secret file next to the cmd
the recommended way to provide credentials to a Go component? 👀 (I haven't worked on Go component secrets before.)
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.
I think this way works well here. When the component runs in a pod it takes the credentials file in the same way (file on disk, location passed via --api-keys-file
).
How would you expect the necessary api keys to be provided when running the usage component locally?
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.
Thanks for the insight!
How would you expect the necessary api keys to be provided when running the usage component locally?
Hmm, I never run components locally -- only inside a complete Gitpod deployment (with secrets configured for Werft or staging/production)
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.
Makes sense. I think @easyCZ is keen to move away from requiring preview environments to develop components. When working on the usage component I think the intention is to run it locally, port forwarding to a database as necesary.
// It returns multiple queries, each being a big disjunction of subclauses so that we can process multiple teamIds in one query. | ||
// `clausesPerQuery` is a limit enforced by the Stripe API. | ||
func queriesForCustomersWithTeamIds(teamIds []string) []string { | ||
const clausesPerQuery = 10 |
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.
Interesting. I guess you found this limit by testing. Is the value 10
documented somewhere? 👀
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.
Not documented anywhere I could find. It appeared in an error message when trying larger queries.
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.
Thanks! No worries -- I asked for more references, because I also wonder whether the actual limit can be different between "test" and "live" mode. But 10 should work.
(I guess this will just potentially fire a lot of Stripe queries in production, because we have many teams there -- but let's see about that when it really happens.)
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, I wondered about differences between live vs staging too.
We will likely need to rate limit our Stripe API calls in production in general. For this search endpoint the rate limit is:
Rate limits
We apply a rate limit of up to 20 read operations per second which applies for all search endpoints in both live mode and test mode. Live mode and test mode limits are separate.
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.
Works like a charm, thanks! 🎉
Tested by setting up usage-based billing for a team, running a few workspaces, and checking the usage
component logs (it found the customer).
Description
Add a
stripe
package to the usage reconciler and use it to find all StripeCustomers
who have registered usage in the preceding month.By querying the Stripe API for all teamIds occurring in the usage report, we are able to find a list of Stripe
Customers
who should have their subscriptions updated to register usage.This PR just finds and logs the
Customers
occurring in the usage report. In a subsequent PR theseCustomers
will be updated to register their usage.Related Issue(s)
Part of #9036
How to test
Get a kube context for the staging cluster (
gcloud auth login
thengcloud container clusters get-credentials ...
) - the exact commands can be taken from the GCP console.Port forward to the staging database:
components/usage/apikeys
. The file should look like:(the env vars, including password, can be found in the
server
pod by running):After 1 minute the reconciler will run and display output like:
Showing the query that was run against the Stripe API and the 1 customer that was found with a matching teamId.
Release Notes