Class: Y::Awareness

Inherits:
Object
  • Object
show all
Defined in:
lib/y/awareness.rb

Overview

The Awareness class implements a simple shared state protocol that can be used for non-persistent data like awareness information (cursor, username, status, ..). Each client can update its own local state and listen to state changes of remote clients.

Each client is identified by a unique client id (something we borrow from doc.client_id). A client can override its own state by propagating a message with an increasing timestamp (clock). If such a message is received, it is applied if the known state of that client is older than the new state (clock < new_clock). If a client thinks that a remote client is offline, it may propagate a message with { clock, state: null, client }. If such a message is received, and the known clock of that client equals the received clock, it will clean the state.

Before a client disconnects, it should propagate a null state with an updated clock.

Awareness is an integral part of collaborative applications, you can read more about the concept here: https://docs.yjs.dev/getting-started/adding-awareness

Examples:

Instantiate awareness instance and encode update for broadcast

local_state = {
  editing: { field: "description", pos: 0 },
  name: "Hannes Moser"
}

awareness = Y::Awareness.new
awareness.local_state = local_state
awareness.diff # [1,227,245,175,195,11,1,65,123, …]

Two connected clients

local_state_a = { name: "User A" }

client_a = Y::Awareness.new
client_a.local_state = local_state

local_state_b = { name: "User B" }

client_b = Y::Awareness.new
client_b.local_state = local_state_b

client_a.sync(client_b.diff)
client_a.clients # {1242157267=>"{\"name\":\"User A\"}", 2401067547=>…

Instance Method Summary collapse

Instance Method Details

#attach(callback = nil, &block) ⇒ Integer

Subscribes to changes

Returns:

  • (Integer)

    The subscription ID



144
145
146
147
148
# File 'lib/y/awareness.rb', line 144

def attach(callback = nil, &block)
  return yawareness_on_update(callback) unless callback.nil?

  yawareness_on_update(block.to_proc) unless block.nil?
end

#clean_local_statevoid

This method returns an undefined value.

Clears out a state of a current client, effectively marking it as disconnected.



68
69
70
# File 'lib/y/awareness.rb', line 68

def clean_local_state
  yawareness_clean_local_state
end

#client_idInteger

Returns a globally unique client ID of an underlying Doc.

Returns:

  • (Integer)

    Returns the client_id of the local user



75
76
77
# File 'lib/y/awareness.rb', line 75

def client_id
  yawareness_client_id
end

#clientsHash

Returns a state map of all of the clients tracked by current Awareness instance. Those states are identified by their corresponding ClientIDs. The associated state is represented and replicated to other clients as a JSON string.

Examples:

Instantiate awareness instance and encode update for broadcast

local_state = {
  editing: { field: "description", pos: 0 },
  name: "Hannes Moser"
}

awareness = Y::Awareness.new
awareness.local_state = local_state
awareness.clients # {312134501=>"{\"editing\":{\"field\":\"descriptio …

Returns:

  • (Hash)

    All clients and their current state



95
96
97
98
99
100
# File 'lib/y/awareness.rb', line 95

def clients
  transform = yawareness_clients.map do |client_id, state|
    [client_id, JSON.parse!(state)]
  end
  transform.to_h
end

#diff::Array<Integer>

Returns a serializable update object which is representation of a current Awareness state.

Returns:

  • (::Array<Integer>)

    Binary encoded update of the local instance



163
164
165
# File 'lib/y/awareness.rb', line 163

def diff
  yawareness_update
end

#diff_with_clients(*clients) ⇒ String

Returns a serializable update object which is representation of a current Awareness state. Unlike Awareness::update, this method variant allows to prepare update only for a subset of known clients. These clients must all be known to a current Awareness instance, otherwise a Error::ClientNotFound error will be returned.

Parameters:

  • clients (::Array<Integer>)

    A list of client IDs

Returns:

  • (String)

    Binary encoded update including all given client IDs



175
176
177
# File 'lib/y/awareness.rb', line 175

def diff_with_clients(*clients)
  yawareness_update_with_clients(clients)
end

#local_stateString

Returns the state of the local Awareness instance.

Examples:

Create local state and inspect it

local_state = {
  editing: { field: "description", pos: 0 },
  name: "Hannes Moser"
}

awareness = Y::Awareness.new
awareness.local_state = local_state
awareness.local_state # {  editing: { field: "description", ...

Returns:

  • (String)

    The current state of the local client



115
116
117
118
# File 'lib/y/awareness.rb', line 115

def local_state
  json = yawareness_local_state
  JSON.parse!(json) if json
end

#local_state=(state) ⇒ void

This method returns an undefined value.

Sets a current Awareness instance state to a corresponding JSON string. This state will be replicated to other clients as part of the AwarenessUpdate.

Examples:

Set local state

local_state = {
  editing: { field: "description", pos: 0 },
  name: "Hannes Moser"
}

awareness = Y::Awareness.new
awareness.local_state = local_state

Parameters:

  • state (#to_json)


135
136
137
138
139
# File 'lib/y/awareness.rb', line 135

def local_state=(state)
  raise "state cannot be encoded to JSON" unless state.respond_to? :to_json

  yawareness_set_local_state(state.to_json)
end

#remove_state(client_id) ⇒ void

This method returns an undefined value.

Clears out a state of a given client, effectively marking it as disconnected.

Parameters:

  • client_id (Integer)

    Clears the state for given client_id



155
156
157
# File 'lib/y/awareness.rb', line 155

def remove_state(client_id)
  yawareness_remove_state(client_id)
end

#sync(diff) ⇒ void

This method returns an undefined value.

Applies an incoming update. This gets the local awareness instance in sync with changes from another client. i.e., updates the state of another user in the local awareness instance.

Examples:

Apply an incoming update

update = [1,227,245,175,195,11,1,65,123, ]

awareness = Y::Awareness.new
awareness.sync(update)

Parameters:

  • diff (Array<Integer>)

    A binary encoded update



60
61
62
# File 'lib/y/awareness.rb', line 60

def sync(diff)
  yawareness_apply_update(diff)
end