-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Server-side implementation of incremental subscription changes #2030
base: master
Are you sure you want to change the base?
Conversation
pub query: Box<str>, | ||
/// An identifier for a client request. | ||
/// This should not be reused for any other subscriptions on the same connection. | ||
/// TODO: Can we call this subscription_id? It feels odd that this request_id will be used for multiple messages (the Unsubscribe call). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's some confusion here due to a typo in the proposal. The intended design is:
- Each request/response pair has a unique
request_id
, assigned by the client. It is not an error for the client to re-userequest_id
s, as their only purpose is to correlate a request/response pair; they have no semantic meaning to the host. - This means that
Unsubscribe
gets a uniquerequest_id
distinct from the one inSubscribeSingle
. - The host looks at the
QueryId
included in theUnsubscribe
message to determine which query is being removed.
It looks like at some point, someone (almost certainly me) made a copy-paste error in the proposal:
/// Server response to a client `Unsubscribe` request.
struct UnsubscribeApplied {
/// Provided by the client via the `Subscribe` message.
request_id: u32,
This should say, "Provided by the client via the Unsubscribe
message." That is, the host treats it as an opaque nonce, and does not retain it or recognize it after sending its response.
Sorry for the confusion!
/// TODO: I assume this is just used for debugging? | ||
pub query_id: QueryId, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See previous comment. This query_id
is (supposed to be) the thing you want to call subscription_id
.
/// TODO: How are we supposed to handle errors without a request_id? | ||
/// Should we drop all subscriptions? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the SDK receives a
SubscriptionError
message:
- The client state is updated such that all
SubscriptionHandle
s are ended.- All rows are removed from the client cache.
on_delete
callbacks are invoked.on_error
callbacks are invoked.NOTE: If a
SubscriptionError
is returned in response to aSubscribe
,
only that particularSubscriptionHandle
is ended.
That is, all other active queries shall remain active.
Noon_delete
callbacks are invoked.
crates/core/src/error.rs
Outdated
@@ -103,6 +103,9 @@ pub enum SubscriptionError { | |||
SideEffect(Crud), | |||
#[error("Unsupported query on subscription: {0:?}")] | |||
Unsupported(String), | |||
// TODO: Is this correct? Check if you can have multiple queries for the same table in a single call. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can have multiple queries for the same table. They should be added in distinct SubscribeSingle
calls, but I suppose the legacy Subscribe
can still add several of them at once. Historically we have imposed that they must be disjoint, but the new design as proposed includes client-side handling to allow overlapping queries.
Description of Changes
This adds the new message types for being able to subscribe and unsubscribe to individual queries without affecting other subscriptions. Much of this was taken from #1997, but this version does not remove the existing way of subscribing to a set of queries. This renames that to
legacy_
in many places, and we eventually want to get rid of it, but by making this an additive change we don't need to update all the clients at the same time.This biggest changes are in the
SubscriptionManager
code. Previously we just stored two mappings:Now we also store a mapping from client to the set of subscriptions for that client (which is useful for unsubscribing), and we keep track of both legacy subscriptions (which have a set of subscriptions per client), and the new subscriptions (which are identified by a
(ClientId, RequestId)
pair).API and ABI breaking changes
This is additive, and only adds new enum types to existing messages, so this is not breaking. In the future we will want to make a breaking change to remove the legacy versions.
Expected complexity level and risk
Testing
This passes existing tests (which exercise the legacy versions), and there are a few basic tests for the new version.
More unit test coverage for incremental subscription changes would be good, but I will probably add that when I start adding client support for it.
Follow-up work
We still need: