-
Notifications
You must be signed in to change notification settings - Fork 1.9k
StateFlow-like primitive for big states with delta updates #3316
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
Comments
We have use cases for this in IJ and would be very glad to see this in the library.
It would be great to have a capability to squash
I'll not list every use case here, but we do have a few with the same semantics: a collection + updates of it. It may be useful to receive custom data in updates, like Ironically, the closest interface we have for list + updates is |
@dovchinnikov Let me elaborate how I see your use-case 1 encoded in the strawman design I've sketched. Here I'd actually use In the end, you'll get
|
Looks good, I'd like to try this in real life |
What about |
I share this use case, but we need three kind of operations: |
A common problem often appears when writing applications with a state flow in cases when a state is quite a big object, for example some kind of a list of events or other entities, a map, or something similar. These kinds of states are usually transferred over network as a one-time snapshot followed by incremental updates, and there is no ready-to-use primitive to represent them as a
StateFlow
.A solution shall cleanly address two sides of the problem:
Ingress: turning a snapshot of the current state plus a sequence of updates into some kind of
Flow
representation.Egress: turning a
Flow
representation into a snapshot of a current state, plus a sequence of updates.A trivial solution is to use
StateFlow<State>
as a flow representation, which might be acceptable for moderately-sized state objects. In this representation, the ingress problem is solved like this:And the egress problem can be solved like this:
This implementation assumes that we have
fun State.diffFrom(other: State): Update
that computes a difference between two states and represents them as an update. This is usually possible and would work fine as long as the states are not very big. However, this does not scale easily. If state big (for example, a list of 100s of thousands of items), then typically-quadratic implementation ofapply
anddiffFrom
functions will make it too slow to be used in practice.An efficient design will work somewhat like a combination of
StateFlow<State>
andSharedFlow<Update>
. It will rely on theapply
function only and will internally maintain a current state snapshot to be delivered to the new subscribed, followed by the corresponding updates in sync. To make this kind of design representable as aFlow
I would suggest to limit ourselves to case whereState <: Update
(a value space of states is a subset of a value space of update) or, saying it another way, only to cases where sending a nState
snapshot is just one kind ofUpdate
operation. We will represent the result as aFlow<Update>
and will need a new kind of name for this primitive. Let's call it, tentatively,UpdateFlow
for now.A sketch of the corresponding API might look like this. On ingress side one writes:
On egress side one writes:
The text was updated successfully, but these errors were encountered: