Middleware Plugins in RiotBlossom
RiotBlossom uses pluggable middleware as part of the HTTP request-response cycle. Creating a middleware plugin requires implementing from any of the following interfaces:
IRequestMiddleware
IResponseMiddleware
IRetryMiddleware
As part of the HTTP request-response lifecycle:
- Before the request is sent (request information goes through request middleware
IRequestMiddleware[]
) - On request (request function reference is passed to single retry middleware
IRetryMiddleware
) - After the response is received (response information goes through response middleware
IResponseMiddleware[]
)
Knowing this lifecycle, MiddlewareStack
is the system composition of IRequestMiddleware[]
, IRetryMiddleware
, and IResponseMiddleware[]
.
A middleware stack is encapsulated to the APIs it is assigned to.
RiotBlossom client builder currently does the following:
AddRiotMiddlewareStack
- the Riot middleware stack for Riot APIsAddDataMiddlewareStack
- the Data middleware stack for CommunityDragon and DataDragon APIs
Each request processed under the Riot MiddlewareStack
is asynchronously locked per routing value to maintain data synchronization.
Having separate middleware systems offers more user configuration and flexibility in doing thingies. As an example, Riot MiddlewareStack
is created with an AlgorithmicLimiter
whereas Data `MiddlewareStack`` does not.
Hopefully, the system design was straightforward to understand...
if I had lost you, I am very sorry...
Request interface
public interface IRequestMiddleware
{
Task UseRequestAsync(ExecuteInfo info, HttpRequestMessage req, Action next, Action<byte[]> hit);
}
info
, routing information of requestreq
, the raw HTTP request messagenext
, action to invoke for continuing to the next request middleware. Not invoking will end the request middleware chain.hit
, action to invoke for sending cached data
Example plugins:
- AlgorithmicLimiter
- InMemoryCache
Response interface
public interface IResponseMiddleware
{
Task UseResponseAsync(ExecuteInfo info, HttpResponseMessage res, Action next);
}
info
, routing information of requestres
, the raw HTTP response messagenext
, action to invoke for continuing to the next response middleware. Not invoking will end the response middleware chain.
Example plugins:
- AlgorithmicLimiter
- InMemoryCache
Retry interface
public interface IRetryMiddleware
{
Task<HttpResponseMessage> UseRetryAsync(Func<Task<HttpResponseMessage>> resFunc);
}
resFunc
, function to invoke for receiving an HTTP response
Example plugins:
- Retryer
Out-of-the-box Middleware Plugins
AlgorithmicLimiter
AlgorithmicLimiter limiter = new(new()
{
CanThrowOn429 = true,
CanThrowOnLimit = true,
ShaperType = LimiterShaper.Burst
});
More documentation can be found in the AlgorithmicLimiter class.
InMemoryCache
InMemoryCache riotCache = new("rb-riot-cache");
InMemoryCache dataCache = new("rb-data-cache")
{
Expiration = TimeSpan.FromHours(24),
Size = 10000
};
More documentation can be found in the InMemoryCache class.
Retryer
Retryer retryer = new()
{
CanThrowOn429 = true,
RetryCount = 10,
RetryDelay = TimeSpan.FromSeconds(10d)
};
More documentation can be found in the Retryer class.