Froox Engine tries to manage most of the synchronization of session data in the background without users having to worry about what gets updated and when. For the most part, things just work. When session values are persistent (which most are by default), user can usually assume that the value they see is the same value that other users in the session see. This is a powerful abstraction that lifts a large cognitive burden from creators and users implementing systems in Resonite who don't want to deal with the problems of distributed and concurrent communications.
However, this abstraction hides a large amount of complexity that exists internally, and occasionally users may encounter edge cases where the abstraction is leaky and they do have to be aware of the true nature of the data model and how it stores, updates, and propagates data.
Data Model as Source of Truth
One of the core principles in the Froox Engine is that the data model is the single source of truth for the state of the program. This means that given the same data model, two users should observe the same behavior (assuming that there is no intentional de-synced behavior using things like local overrides). Using this model, the Froox Engine then just has to worry about ensuring that all the users in a session agree on the current state of the data model.
The data model state DOES NOT include dynamic events, impulses, or other time based behaviors; only data. To get 'synced' events, you update the data, the data change is propagated to other users, and those changes to the data can trigger local processes to run for each user.
Eventual Consistency
The engine attempt to always keep all the copies of the data model across the users identical, but due to the laws of physics this is not possible. While updates are being transmitted or when there are multiple users updating the same value, the data model will be not be identical; however, the data model should be eventually consistent, meaning that over time all the users will converge to the same data model state. Because this is a moving target, it may never actually occur, but for most applications in Resonite, eventual consistency provides a reasonable tradeoff between responsiveness and reliability.
Optimistic Concurrency
When reconciling the current data model state for users, the Froox Engine uses a type of optimistic concurrency to modify and propagate changes to other users in the session in a manner that is often often efficient and performant. This enables (in theory) any user in the session to modify any part of the data model at any time without worrying about things like who owns what data.
The common steps for propagating a change: when a value in the data model is changed locally, the client will share the update with the host who will then forward that update to the rest of the user in the session. In many scenarios, this is what happens and everything is fine. However, optimistic update gets more complicated when there is contention.
When there is contention among a resource (more than one user is trying to update a part the data model at the same time), the host has to decide which value will be kept as the new source of truth. This is what the version number is for. The version number is a piece of metadata that is sent along with every data model update, and each new update increments the version. If the host receives updates from more than one user for the same data with the same version number, the first one is kept as the authoritative version and the later data model updates are discarded. When an update is discarded, the host will re-sync the authoritative value for that piece of data with the client (effectively rolling back the 'optimistic' local change the client made).
Optimistic concurrency works best when most data writes are not contented (at most one user is trying to update a value at any given time). In most scenarios in Resonite, this is a reasonable assumption and results in very responsive behavior that is also efficient with minimal coordination overhead. If this assumption does not hold then there will be a degradation in the platform experience.
Atomic Operations
The optimistic concurrency control mechanism that is used by Froox Engine does not support concurrent atomic operations out of the box (in contrast to something like software transactional memory). This means that while the data model may be eventually consistent, intermediate states on local machine may not be correct and are not guaranteed to be committed. The local update, if the host chooses to discard it, will be reverted and lost. This can cause issues if you require tight guarantees that an updated value has actually been updated for everyone else.
At some point in the future, Resonite may support various atomic update primitives and transactions, but currently atomic updates need to be handled manually by the user by ensuring that there is no contention and checking that all users have received an update.