logux / logux

Issues and roadmap
https://logux.org/
103 stars 3 forks source link

treat filter subscription as a subscription to every store matching the filter #110

Open ngalaiko opened 2 years ago

ngalaiko commented 2 years ago

setup:

assume a client-server architecture where on SyncMap is used with createFIlter on the offline/remote client and addSyncMap +addSyncMapFilter on the backend

problem:

when creating a filter, client and server exchange a lot of messages to: 1) subscribe to a list. that's two messages 2) subscribe to every item of the list. that's one or two messages depending on if server subscribes a client, or client subscribes by iteself

that's a lot of pressure on the network and synchronisation for really no reason.

solution:

filter subscription is enough for the server to send actions related to every matching item of the channel

there seems no need to explicitly subscribe client to every matching store separately, or maybe I am missing something?

ai commented 2 years ago

Both client and server need IDs of each subscribed element.

If we can find a way to get find them without an action, it always will be a good idea.

Do you have an idea how to make PR?

ngalaiko commented 2 years ago

I haven't looked into it too much, but it seems possible.

on the client side:

  1. createFilter should be synchronously populated with initial data from the client's state
  2. for every new action, it it matches any existing filter, filter's value should be updated with an action

on the server side:

  1. for every new action, for every known filter, if an action matches the filter, it should be sent to the client
ai commented 2 years ago

createFilter should be synchronously populated with initial data from the client's state

It is impossible because log is an async store (for instance, IndexedDB has only async API).

for every new action, it it matches any existing filter, filter's value should be updated with an action

change action will not have all model’s fields. As the result it will be impossible to tell is it part of filter or not.

Imagine you have name: 'a' filter and see { type: 'users/changed', id: 'X', fields: { age: 50 } }. How you will tell that it is your or not item without a list of subscribed IDs?

for every new action, for every known filter, if an action matches the filter, it should be sent to the client

  1. Client A created filter { age: 50, name: 'a' }
  2. Client B changed user with ID X age to 50. You do not have information of the name to find did it matched the selection.
  3. Client C changed another user with ID Y to role: 'admin'. How do you know age and name of Y user?
ngalaiko commented 2 years ago

Imagine you have name: 'a' filter and see { type: 'users/changed', id: 'X', fields: { age: 50 } }. How you will tell that it is your or not item without a list of subscribed IDs?

given that I already have a full item in the scope (from the init step), I could simply merge it with it

same applies for the server side.

Client B changed user with ID X age to 50. You do not have information of the name to find did it matched the selection.

server does have the info. it keeps an index of elements matching the filter in memory for every connected client. when client B changes user with ID X age to 50, it sends an action to the server. server resends it to client A

Client C changed another user with ID Y to role: 'admin'. How do you know age and name of Y user?

when filter is created, all of the matching elements (from the initial function in the addSyncMapFilter) are used to create in-memory index.

It is impossible because log is an async store (for instance, IndexedDB has only async API).

either way it would be very fast, since it happens without communicating with other clients or servers on the client

ai commented 2 years ago

given that I already have a full item in the scope (from the init step)

Only if server already send the initial data.

same applies for the server side. all of the matching elements (from the initial function in the addSyncMapFilter) are used to create in-memory index.

Dangerous (server could have 1000 of client with 10 subscriptions with 1000 elements each). But we can try.