glacasa / Mastonet

C# Library for Mastodon
MIT License
225 stars 36 forks source link

Expose rate-limiting headers #85

Closed instantiator closed 1 year ago

instantiator commented 1 year ago

Hey there - I love the library, and I'm making use of it at the moment in a personal project. Thanks so much for your work on it.

It'd be super if the headers with rate-limiting information could be exposed through Mastonet, or if rate limiting could be managed within the library (although I appreciate that would require it to keep state, etc.)

Rate-limiting headers from the Mastodon API are defined here: https://docs.joinmastodon.org/api/rate-limits/

instantiator commented 1 year ago

For anyone interested, I'm using a workaround at the moment: instantiator/consensus-chess-engine/.../RateLimiter.cs.

It'll delay activity to stay under a pre-defined threshold. Obviously it's not perfect as it's operating without knowledge of the rate limiting headers from the API, but it'll do (for me) for now.

glacasa commented 1 year ago

Hi ! I'm gonna look at that. I can definitely expose the rate-limiting info in Mastonet, but I'm not sure if I should add code to manage it automatically, or how it should be handled.

I'm afraid automatic delay without notification to the developer may cause confusion.

If you have any ideas on you would it be done tell me (no promise I will do it this way, though 😉)

instantiator commented 1 year ago

It'd be good to also understand/document how streaming consumes the rate limits. ie.

var streaming = client.GetUserStreaming();

Streaming is documented here: https://docs.joinmastodon.org/methods/streaming/ - but I don't think I've really grasped the implications. (Appreciate it's not really your problem to solve, but as I'm hoping to be a responsible consumer of the APIs, it'd be good if there were a spot of advice.)

instantiator commented 1 year ago

I can definitely expose the rate-limiting info in Mastonet, but I'm not sure if I should add code to manage it automatically, or how it should be handled.

Thanks so much! This would be really cool - and I appreciate that exposing the info is probably the better choice as it means developers can implement their own strategies.

If you have any ideas on you would it be done

I gave it a little thought - see below. It seems like maybe option 2 would be the preferred option, as it's the simplest to implement, and it's not a breaking change.

option 1

At the moment, Mastonet returns the type that the user requested through the API. It's really neat:

public Task<Status> GetStatus(long statusId);

How about if it returned a new class, eg. MastodonResponse<T> and then that class could contain:

public T Data { get; set; }
public Dictionary<string,string> Headers { get; set; }

and maybe some other metadata about the response? The API would look like:

public Task<MastodonResponse<Status>> GetStatus(long statusId);

A drawback I recognise is that it's a breaking change. I understand if it's not quite right for you.

option 2 (preferred?)

Perhaps instead you could track the latest rate-limiting info in a static field on the client. It could even be observable. A side-effect of each call to the client would be to update that info. eg.

var status = await client.GetStatus(statusId);
var rateLimits = MastodonClient.LatestRateLimitHeaders;

I'm starting to think this is the simplest option - as it makes the headers visible, but it's not a breaking change.

Update: Actually, thinking about it, it probably shouldn't be static - as I can imagine there are people who need to open up multiple instances of MastodonClient to different servers. So instead, it could be a non-static member on the client, eg.

var status = await client.GetStatus(statusId);
var rateLimits = client.LatestRateLimitHeaders;
glacasa commented 1 year ago

I've started working on it, and I used an event at first because it was the fastest way to test it And actually, it looks like a good API design :) with a bonus : no need to keep the data in the MastodonClient

If you want to know about Rate limits, you just subscribe to the event and you get the last data every time I have some to give you

Get this Nuget package : https://www.nuget.org/packages/Mastonet/2.1.0-preview-ratelimiting-1 You can try subscribing to RateLimitsUpdated, and tell me if that works for you.

instantiator commented 1 year ago

Oh this is really cool. Thank you I'll check it out.

glacasa commented 1 year ago

Closing this issue - code has already been merged