-
Notifications
You must be signed in to change notification settings - Fork 5
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
feat: rate limiter + unit tests + readme #115
Conversation
Add a new middleware that checks a rate limiting service and returns a 429 if the CID is over a rate limit. This sketches out an API for the rate limiting and accounting services suggested in storacha/RFC#28 This is not ready to merge, but should probably be the starting point for this work once we all agree that this is the right shape.
introduce a KV namespace for caching token metadata - for now the "invalid" boolean is the most important thing, as that's how we decide whether a token is valid. I thought we'd be able to serve tokened requests when in doubt, but I'm a bit worried about people generating random tokens if we go that route - sending a different random token with each request would theoretically allow them to make infinite unbilled requests. instead I went with a pattern that will likely require us to warm the cache before a token-based request achieves hot-storage level performance - we cache auth token metadata in KV and wait for the accounting service to return it if we don't find it in the cache. Using a "Stale While Revalidate" pattern to update the cache will allow us to maintain performance and the ability to disable tokens.
5a21d18
to
5326ae8
Compare
Could you say more about why Jest is useful here? We've typically used |
sure thing @travis I don’t have super strong opinions on this either, but Jest does give you some nice built-in features like mocking, spies, and coverage reports right out of the box. With Mocha (or node:test), you’d need to add additional libraries like Sinon for mocks and nyc for coverage, which Jest handles natively. That said, if we can use Mocha alongside node:test, it should work fine, even though Mocha isn't as feature-rich in those areas. Totally open to whichever approach the team prefers! 😊 |
ok cool - I lean toward Mocha, but tbh I'd like @alanshaw to weigh in since he's written a lot more of this code (like, infinitely more, as this is really my first freeway contribution as well!) - Alan any preferences/thoughts on testing frameworks here? |
b55ce9a
to
1a31dee
Compare
35e6793
to
6ca4fee
Compare
6ca4fee
to
0cb41c4
Compare
0cb41c4
to
5e9213f
Compare
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've added a few comments, some of them blocking - I took https://conventionalcomments.org/ for a spin on this review, curious if you like it!
I probably won't Approve this PR in general since I've never contributed to Freeway myself - @alanshaw could you take a look at this when you get a chance?
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.
Love the docs updates 🙏 thank you.
Slightly my bad here, I tried I'm mildly against having 2 testing frameworks in the same repo, but at the same time I don't want to waste time here - there's a bunch of tests written now using it so...meh. The point is more that testing exists at all - I don't mind which framework we use. People like consistency though (thinking about the team mostly here as I have a high tolerance for chaos), and using the same framework(s) everywhere allows us to work more quickly and without context switches. We should establish a single/set of frameworks we're comfortable using as a team. I realise that may have changed now. @travis this is something needed to be decided for team norms. Just a couple of notes: 1) I though jest was legacy/unmaintained? 2) We don't use jest anywhere else. |
FWIW, I'm highly in favor of Jest. It's not legacy; quite the opposite, AFAIK it's where the community primarily is right now. Granted I'm biased by being used to Jest, but I'd love to decide to (in the long run) move everything to Jest. |
8c1eca1
to
3518909
Compare
43e5fa4
to
e37c45c
Compare
src/middleware.js
Outdated
if (cachedValue) { | ||
return deserializeTokenMetadata(cachedValue) | ||
} else { | ||
const accounting = Accounting.create({ serviceURL: env.ACCOUNTING_SERVICE_URL }) |
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, understood but I'm not convinced it'll be a performance problem.
Related, I'd probably implement the cache as a transparent wrapper around the accounting service and pass the accounting service as a dependency to the rate limiting service.
i.e. something like:
const accounting = Accounting.create({ serviceURL: env.ACCOUNTING_SERVICE_URL })
const cachedAccounting = Accounting.withCache(accounting, env.AUTH_TOKEN_METADATA)
const rateLimiter = RateLimiter.create(cachedAccounting)
const status = await rateLimiter.check(cid, request)
if (status === RATE_LIMIT_EXCEEDED.YES) {
// ...
So then it should be easier to test the rate limiter, since the rate limiter is not importing a function that requires a KV and an accounting service. Also easier to test the caching logic in isolation.
...anyways...just a suggestion - non blocking.
@alanshaw I've applied pretty much all the suggestions, however, I left some of them to be done in different PRs to minimize the number of changes here.
|
🤖 I have created a release *beep* *boop* --- ## [2.21.0](v2.20.2...v2.21.0) (2024-11-06) ### Features * **blob-fetcher:** use updated blob fetcher ([#124](#124)) ([90bb605](90bb605)) * egress tracker middleware ([#120](#120)) ([847829b](847829b)) * rate limiter + unit tests + readme ([#115](#115)) ([7bc4c6d](7bc4c6d)) ### Bug Fixes * **test:** enable nodejs compat for miniflare ([#127](#127)) ([0165521](0165521)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This PR add tests for the Rate Limiter middleware, the main changes include: