Skip to content
This repository has been archived by the owner on Nov 24, 2022. It is now read-only.

respect the rate limit from cid gravity #66

Merged
merged 2 commits into from
Oct 27, 2021

Conversation

merlinran
Copy link
Contributor

the API will be live in one day or two.

@merlinran merlinran force-pushed the merlin/cid-gravity-rate-limit branch from 6990b70 to 9dc50c2 Compare October 25, 2021 22:10
Signed-off-by: Merlin Ran <merlinran@gmail.com>
@merlinran merlinran force-pushed the merlin/cid-gravity-rate-limit branch from 9dc50c2 to e381b84 Compare October 25, 2021 22:26
@merlinran merlinran marked this pull request as ready for review October 26, 2021 12:49
@merlinran merlinran requested a review from jsign October 26, 2021 12:49
Copy link
Contributor

@jsign jsign left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice 💯
More things coming from cid-gravity.

rules = r.(*rawRules)

if rules.DealRateLimit > 0 && rules.CurrentDealRate >= rules.DealRateLimit {
return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: How does the caller know if prices has a correct value? In this line valid = true and prices seems to have the default struct values. Maybe the default struct ResolvedPrices is interpreted as "Do not bid?"

(Same question applies to Maintenance Mode, etc; so probably making a dumb question).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gosh I think you found a bug. valid==true means the result is valid, and https://github.com/textileio/bidbot/blob/main/service/service.go#L361 just uses the default prices if the VerifiedPriceValid or UnverifiedPriceValid is false, rather than stop bidding. huge huge bug. will fix

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, nice that was caught.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 27c5850. I tested via make up with a real CID gravity token, and made sure that bidbot didn't bid if in maintenance mode. good catch! wonder why I didn't test that in the first place.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@merlinran, one question left here: how does rules.DealRateLimit work here? I don't see this variable set anywhere but only in tests; maybe missing something? Shouldn't be updated when bidbot wins an auction?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe is automatically fed by Lotus into cid-gravity.. so mostly outside of bidbot scope.
In theory whenever it wins a deal, we should propose a deal.. so that is fed by some Lotus cid-gravity plugin, and it would be updated that way?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DealRateLimit is configured by the provider on the cid gravity console, and yeah, CurrentDealRate is updated by cid gravity server when it accepts a new deal by the lotus cid-gravity plugin.

image

It may be helpful to register one account on https://app.cidgravity.com to have a sense what it looks like.

Comment on lines +192 to +203
case http.StatusTooManyRequests:
reset := resp.Header.Get("X-Ratelimit-Reset")
ts, err := strconv.ParseInt(reset, 10, 0)
if err != nil {
return fmt.Errorf("parsing X-Ratelimit-Reset: %v", err)
}
t := time.Unix(ts, 0)
cg.apiRateLimitReset.Store(t)
return fmt.Errorf("CID gravity API rate limit is hit: %s/%s, won't reset until %v",
resp.Header.Get("X-Ratelimit-Remaining"),
resp.Header.Get("X-Ratelimit-Limit"),
t)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite impressed they already set a rate-limiting strategy; which is totally fine and good practice. 👍

I think would simply rate limit from our side to some safe limit like once per minute or similar since I wouldn't expect finer than that would be much relevant and maybe could simplify impl a bit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah cidGravityCachePeriod is set to one minute so the API is hit at most once per minute. Mostly try to good behaving and log something if rate limit happens.

Copy link
Contributor Author

@merlinran merlinran left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh I forgot to submit my comments!

// Use cached rules if they are loaded no earlier than this period.
cidGravityCachePeriod = time.Minute
)

type rawRules struct {
Blocked bool
MaintenanceMode bool
DealRateLimit int
CurrentDealRate int
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cid gravity allows the deal as long as CurrentDealRate <= DealRateLimit on the server side.

rules atomic.Value // *CIDGravityRules
rulesLastUpdated atomic.Value // time.Time
rulesETag atomic.Value // string
apiRateLimitReset atomic.Value // time.Time
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not to be confused with the deal rate limit. It's the limit hitting CID gravity API.

if rules.(*rawRules).Blocked {
rules = r.(*rawRules)

if rules.DealRateLimit > 0 && rules.CurrentDealRate >= rules.DealRateLimit {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note >= here. Because the deal rate check happens on CID gravity server, if rules.CurrentDealRate is already rules.DealRateLimit, the next check by the lotus node would fail.

@@ -127,48 +140,17 @@ func (cg *clientRules) maybeReloadRules(url string, timeout time.Duration, cache
if time.Since(lastUpdated) < cachePeriod {
return true
}
if t := cg.apiRateLimitReset.Load(); t != nil {
reset := t.(time.Time)
if time.Now().Before(reset) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

slight optimization to avoid hitting API server if API rate limit is hit.

// proceed
case http.StatusNotModified:
return nil
case http.StatusTooManyRequests:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The status code and headers are confirmed with Florian.

Signed-off-by: Merlin Ran <merlinran@gmail.com>
@merlinran merlinran merged commit 2b4218e into main Oct 27, 2021
@merlinran merlinran deleted the merlin/cid-gravity-rate-limit branch October 27, 2021 17:28
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants