ably / spaces

The Spaces SDK enables you build collaborative spaces for your application and enable features like Avatar stack, Live cursors, Member location, Component locking and more.
https://space.ably.dev/
Apache License 2.0
44 stars 8 forks source link

Locking inconsistencies #335

Open bastiankistner opened 2 weeks ago

bastiankistner commented 2 weeks ago

Hi there,

I am in high demand for a realtime locking solution so I went on giving ably a try. I've been using channels previously, which works ok as long as I don't rely on events but continuously run certain checks (e.g. with requestAnimationFrame or requestIdleCallback). I also moved away from using the react integration because error handling is really badly implemented!

I thought I'd give spaces a chance but already after a few nights playing with it, I'm facing inconsistent situations with a probability of at least 10 to 20%. After I simulate connection issues, locks are not properly being released on all clients and I can even kind of reproducibly trigger situations where more than one client holds a lock for the same id.

The internals of the SDK reflect an inconsistent state. Even though, my clients reconnect and I'm not maintaining state information about locks but instead always call the getAll, getOthers and getSelf methods as described in the docs, the SDK instances seem to hold outdated and invalid data. They don't update unless I re-acquire and release the within a client that carries the correct state or disconnect a client so that certain updates seem to be triggered.

Am I doing something wrong? Or is version 0.4 (internally) known to be unreliable?

Ably could be such a great product for far more than 500 customers, if only developer experience would be improved.

I attached a screenshot. You would certainly need the sources to understand what's going on. But it's the exact same application, running in two different tabs, using the public api key, a client id generated with crypto.randomUUID() and nothing fancy but a few react components and a singleton class handling ably realtime with members and locks and a store that can be used in combination with react's useSyncExternalStore. And it shows that each client holds a lock for id dummy1. Members shows self and others and the Lockable Item's purpose is to provide two buttons for lock/unlock.

I could provide a repo with it if it helps. image

bastiankistner commented 2 weeks ago

Here is another flaw I just discovered

image

As you can see in the console logs, my clientId and the connectionId match the ones listed as other, which is being pulled by calling space.members.getOthers()

However, spaces seems unable to match my own client and connection id against the members and therefore marks myself as other.

This happened after going into hibernation and waking up my machine again.

lmars commented 2 weeks ago

@bastiankistner thanks for the detailed report, I've raised this internally, we'll review and get back to you.

bastiankistner commented 1 week ago

@lmars I created a pull request to fix the self/others bug. Reason seems to be that the ably client's connectionId is being assigned internally in the Space constructor. This id becomes stale when a new ID is being assigned e.g. when the client disconnects.

see here https://github.com/ably/spaces/pull/336

bastiankistner commented 1 week ago

Regarding the locking inconsistencies: It seems that when I decrease the disconnectedRetryTimeout it becomes less likely that I have more than one lock for the same id.

VeskeR commented 6 days ago

Hi @bastiankistner ! Thank you for openinig a PR for connectionId issue, I replied there.

I will be looking into the locking inconsistency issues. You mentioned you could provide a repo with a reproducible setup - this would be really helpful, so please send it if you have it around.