The Cavrnus system primarily consists of a set of spaces, each an individual environment a user can join, participate within, create, or modify.
The Journal
The data that defines a space is called its Journal.
The Journal consists of a linear sequence of Operations. Operations are never deleted, the journal only ever moves forward. Think of the journal as a log of everything that ever occurred within the space, which when replayed, reconstructs the space in its current state.
When connected to a space, a user can submit an Operation to be included in the journal. These become part of the permanent journal. Common operations include:
...
Instantiating objects
...
Updating property values
...
Cancelling previous operations
...
At the core of the Cavrnus platform are the Operations and Transients that are written to the Journal.
Operations
Operation are the updates performed within a Cavrnus Space that are synchronized to all connected users. These operations can be triggered by multiple commands and functions within the Cavrnus Spatial Connector, for example:
Post X Property
Bind X Property Value
Begin Transient X Property Update
Finalize (X)
The above examples are function calls specific, with multiple overloaded examples for the various datatypes that Cavrnus supports. In each example, the X refers to the specific data type supported by the overloaded function.
Transform
Boolean
Float
Integer
String
etc.
Color Vector
Transients
A Transient, is a communication sent by a user which is not permanently stored in the journal. Transient communications involve either temporary or unsynchronized state changes. When a new user joins the space, they will not be transmitted updated with any historical transient information; they only receive and process the permanent journal. This simplifies the data history in the Journal
Common transients include:
...
Lastly, transient events are often echoed locally; they take effect immediately within the executing client’s application. Operations require guaranteed ordering, so they only ever are applied after a round trip to the Cavrnus API server. Since latency makes for bad UX, transients are applied locally immediately. The journalling system will ensure that the correct synchronized state is reached despite a potential order difference when multiple users manipulate the same fields simultaneously.
In short:
Operations are permanent changes.
Transients are temporary state transmissions and coordination systems.
An journal example:
For example, consider the following sequence of abstract operations:
Create a Sphere called 'A'.
Move 'A' to (10,1,0).
Create a Box called 'B'.
This results in a space with two objects, A and B. If we wish to remove 'B' from the space, rather than delete anything from the journal, we instead:
4. Cancel operation #3.
Which will result in 'B' not being present, as its creation is now ignored.
Consider a user wishing to ‘Undo’ the move of 'A', operation #2. In this case, we just:
5. Cancel operation #2.
Rather than track previous location and update it, we simply mark the operation as ‘cancelled’.
Oops, now we want to redo that operation!
6. Cancel operation #5.
Now the cancellation is cancelled. Operation #2 is now live once again.
...
In the Cavrnus Spatial Connector, transients are temporary or ephemeral objects that exist in a shared scene only as long as they’re needed, without permanently altering the persistent state of that environment. Below is an overview of how they work and why they’re used:
Example Transient Sequence:
Consider a user ‘A' dragging a slider for ‘x' from 0, through 1, X to update a float value starting at 0 then releasing on 2. What events occur for user 'A’ and 'B’?
...
'A': Local transient: Update 'x' to 0
...
'A': Send transient: Update 'x' to 0
...
‘B' only: Recv and apply transient: Update 'x' to 0 (client 'A’ will ignore this update as it knows it has already been applied)
...
'A': Local transient: Update 'x' to 1
...
'A': Send transient: Update ‘x' to 1
...
‘B' only: Recv and apply transient: Update 'x' to 1. Client 'A’ will ignore this update as it knows it has already been applied.
...
'A': Local transient: Update 'x' to 2
...
'A': Send transient: Update ‘x' to 2
...
‘B' only: Recv and apply transient: Update 'x' to 1. Client 'A’ will ignore this update as it knows it has already been applied.
...
'A': Send operation: Update 'x' to 2, noting this operation concludes the above transient sequence
...
User A: The local value of their interface changes consistently from 0 to 2 at the refresh rate of the application.
The Journal: Update operations are posted to the Journal from 0 to 2. This update occurs as fast as the network can handle, posting transient updates to the Journal. These values are marked in the Journal with a “T”.
User B: While the change is occuring, User B witnesses the updates live while connected to the Space copresent to User A.
User A: Releases the controller, and no longer actively changes the value. At this point, the system “Finalizes” the value at 2.
User B: Sees the final state of the value at 2.
User C: Logs into the Space after the property value is finalized. The Transient values are not visible. Only the final state of the property is visible.
Client applications will mark the transient events completed and reorder them to match the operation’s ordering, determined by the API server. In most cases, the live state will not need to be updated, as it is already correct.
Implementing Transient Updates in Unreal Blueprints: