Potential refactor ideas for requests #1014
Labels
A-requester
Area: requester trait, bot adaptors
A-requests
Area: representation of telegram bot API requests/methods
C-core
crate: teloxide-core
K-proposal
Kind: proposal to add something new/change existing design
Motivation
The current design of the
Bot
/Requester
/requests is cool and is working, however it has a number of issues and I'm not sure it's the best one.Now thinking about it again, it seem like the design tries to put "performance" above usability/simplicity. I don't think that's generally a bad call, but I do think that for
teloxide
specifically it is a bad decision. My reasoning is that 1. performance is bound at IO/telegram anyway most of the time; 2. we already sacrifice performance for ease of use in dptree; 3. teloxide is used a lot by programmer beginners for whom it is often hard to learn, in some cases because of the currentBot
/... design.Would be nice to improve things here. Below are some problem with the current design:
API updates
API updates are currently extremely cumbersome, as they require changing a lot of things:
Defining new adaptors is painful
Related to the previous point: defining new adaptors requires overriding a lot of methods and is very painful.
Too many traits / trait items
We ended up with the following methods in traits (I include different monomorphizations):
Requester
methods:api_methods × adaptors
*Setters
methods:api_methods × parameters × adaptors
12Request
methods:2 × api_methods × adaptors
2Payload
methods:api_methods
HasPayload
methods:3 × api_methods × (adaptors + 1)
3Download
methods:2 × adaptors
I feel like this might be contributing to the relatively slow compilation time and bad r-a suggestions sometimes.
There is also the fact that
Requester
has a ton ofWrong bot type / long bot type
This is something that trips beginners all the time. When you are using things like
.parse_mode
, you getDefaultParseMode<Bot>
, which breaks dptree deps.type Bot = ...;
kind of alias mostly fixes the issue, but it still bad for beginners and in error messages.Goals / ideas of the refactor
Proposal
My main idea is to have concrete types
Bot
andRequest<P>
4 types. To accommodate the ability to have custom behavior via adaptors, bothBot
andRequest<P>
will store something likeArc<dyn BotEngine>
inside.Types implementing
BotEngine
can either wrap otherBotEngine
types or have type erasure themselves5, I don't think this matters much, as they only exist to the user while creatingBot
.Since
Bot
andRequest
are single types now, you can implement currentRequester
,*Setters
,Request
,HasPayload
methods on them directly.Since payloads are a closed set, we might also want to make
BotEngine
have just a singlefn execute<R>(&self, payload: Payload) -> impl Future<Output = Result<R, Error>>
wherePayload
is an enum of all payloads. Alternatively maybe accept a generic payload6.API / sage / implementation sketch
Creating a new bot with a custom engine:
Bot API methods78:
Setters:
Pros
Cons
Bot<E>
?Bot
always returns the same error type?)Alternatives
Do nothing
The always present: leave the status quo as-is.
I don't think it's a good approach, since it leaves all the problems described at the beginning intact. Causing problem to both users and maintainers.
Do this, but will less type erasure
With GATs being stabilized now, we could have
Bot<Engine>
with all the same interface I'm pretty sure. I don't think that we need that, but we could.Footnotes
api_methods × fields
signifies "total number of parameters of requests" ↩some adaptors don't count here, since they don't have their own request types ↩ ↩2
+1
for theHasPayload
implementations on payloads ↩P
for the payload, we still need to be generic over the return type :) ↩Or just implement the functionality themselves, obv ↩
Requires us to define a single trait that allows to send pretty much any payload (should be possible though, something like
Serialize + GetInputFiles + Any + ...
) ↩I want to suggest changing style guide and using APIT more since they make better documentation and the downsides are rare & unimportant (but it's a topic for another time) ↩
The lifetime can be removed from
Request
, but I don't think it's a big deal either way ↩The text was updated successfully, but these errors were encountered: