`ActyxClient` subscribe methods are too verbose
jmg-duarte opened this issue · comments
There's a bunch of reasons the API is verbose:
- Requires
String
s instead of&str
(taking ownership inside the function) - Methods require structures with the same name as the method, leading to the repetition of names through out
Example:
client
.subscribe_monotonic(SubscribeMonotonicRequest {
session: SessionId::from("me"),
query: "FROM appId(com.example.chat) & 'message'".to_owned(),
from: StartFrom::LowerBound(OffsetMap::empty()),
})
.await
.expect("failed to subscribe to messages")
From here, the only truly required field is query
.
One option is changing the subscribe_monotonic
to receive just query
instead:
client
.subscribe_monotonic("FROM appId(com.example.chat) & 'message'")
.await
.expect("failed to subscribe to messages")
This would initialize the request inside the method instead of requiring the user to do so.
Another option would be to use Default
and allow the user to write:
client
.subscribe_monotonic(SubscribeMonotonicRequest {
query: "FROM appId(com.example.chat) & 'message'".to_owned(),
Default::default()..
})
.await
.expect("failed to subscribe to messages")
Yet another (more generic) option would be to create a public request
method, that receives these Request
objects:
enum Request { SubscribeMonotonic(SubscribeMonotonicRequest), ... }
fn request(request: Request) {
match request {
SubscribeMonotonic(request) => { ... }
}
}
We could even make the SubscribeMonotonic
inside the enumeration a structure instead of an anonymous tuple (apologies if the name is wrong). Serialization could be made untagged
so the underlying representation stays the same too.
The main argument to subscribe
(both variants) is the query string, which we should take as impl Into<String>
(people know what that means). The ability to specify a lower bound (or other options) should be discoverable, which means we cannot use “method overloading by trait” (e.g. taking an impl Into<SubscribeMonotonicRequest>)
. This implies that a second method like subscribe_monotonic_opts
might be a good way, what do you think?
This implies that a second method like subscribe_monotonic_opts might be a good way, what do you think?
I like the Opts
approach but instead of a second method, maybe we could once more either provide a Default
or make it Option<SubscribeOpts>
.
In the end, I see the "simple" version (i.e. fn publish<S: Into<String>>(&self, query: S)
) calling the opts
version with some sort of defaults — for example, the session ID: SessionId::from("me")
or some similar mechanism as we can't run away from providing those other arguments.
Right, some method needs to supply all the arguments. The main difference is
ax.subscribe("FROM 'message'");
ax.subscribe_opts("FROM 'message'", SubscribeOpts { lower_bound, Default::default().. });
// vs
ax.subscribe("FROM 'message'", None);
ax.subscribe("FROM 'message'", Some(SubscribeOpts { lower_bound, Default::default().. }));