Cosmopolite

Client/server publish/subscribe, presence and key/value storage for AppEngine

Cosmopolite Reference

Terms

Profile

A profile is a collection of clients that all speak as the same user, and so should appear as the same to subscribers. Profiles are identified by a string key assigned by the server. Clients can fetch their own profile by calling getProfile() or currentProfile(). Profile information for other users is provided in the sender field of a Message.

A client keeps its profile when it logs in to a Google account, accept if that account is already associated with a different profile. In that case, messages that were sent using the old profile are re-assigned to the profile associated with the logged in user.

Logging out changes profiles.

The profile key is passed to Google Analytics (if enabled) as the userId, so sessions from different clients across different browsers are associated with the same user for analytics purposes.

Client

A client is a persistent identifier for a given browser. It is identified by a string key generated by the client and stored in localStorage, so it is persistent across restarts (except in incognito mode or the like). A client is associated with exactly one profile at any time, but may change associated profiles on log in.

Logging out generates and stores a new client key.

Instance

An instance is a persistent identifier for a single connection to the server. It is generated when a new Cosmopolite instance is constructed or whenever the server -> client channel connection is interrupted.

Instances are used to track Subscriptions and Pins which cease to exist (from the server perspective) when a client disconnects.

Channel

A channel is the message push connection from the server to the client used to send updates. It uses Google AppEngine's Channel service.

In addition to message passing, the channel library also provides notification of connection state to the server. This is passed to the application code using the onConnect and onDisconnect callbacks.

Subject

A subject is a topic that clients publish and subscribe to. Subjects may be strings, numbers or objects with access control information embedded. The follow are all valid and different subjects:

(where XXXprofileXXX and YYYprofileYYY are profile keys)

Subscription

A subscription ties an instance to a subject and requests that the client be kept informed of changes to that subject. Changes that cause notification are:

When a new subscription is established, the server sends all active pins and a client-specified subset of historical messages to the client.

Subscriptions are automatically destroyed on the server side when an instance disconnects. The client library keeps lists of subjects and the last messages seen from them and automatically re-subscribes after reconnection. This process is transparent to application code.

Subscriptions are created by the application using the subscribe() method.

Message

A message is a piece of information sent by a client to a subject. It is stored by the server and transmitted to any clients currently subscribing to that subject.

A message can consist of any type that is serializable in JSON: numbers, booleans, strings, null, arrays and objects composed of these values (or of other arrays and objects). Serialization and deserialization is handled by Cosmopolite.

When a message is received (via the onMessage callback or the return result from getMessages() or getLastMessage()), metadata is attached, packaged into an object with the message data itself:

{
  // Server-assigned sequence number
  "id": 1,

  // Type may also be "pin"
  "event_type": "message",

  // Sender-assigned UUID
  "sender_message_id": "cbdae48d-7a02-4850-208c-986b18121b9c",

  // Canonical subject that message was sent to
  "subject": {
    "name": "foobar"
  },

  // Server-recorded UNIX timestamp that the server received the message
  "created": 1402212355.0,

  // Deserialized message data
  "message": "test",

  // Profile key of sender
  "sender": "XXXprofileXXX"
}

Messages are sent by the application using the sendMessage() method.

Pin

A pin is a message that is deleted when the instance that sent it disconnects. Subscribers to the pin's subject are notified (via the onPin and onUnpin callbacks) when it is added and deleted. This allows pins to be used for presence detection.

Pins are added and deleted by the application using the pin() and unpin() methods.

Callbacks

Callbacks are used by the Cosmopolite client library to notify the application of events. Callbacks are passed to the Cosmopolite constructor in an object. The object itself and all callbacks are optional.

onConnect

Arguments: none

The onConnect callback is called when the channel is established to the server. It is paired with the onDisconnect callback except when shutdown() is called.

onDisconnect

Arguments: none

The onDisconnect callback is called when the channel is disconnected. This can happen due to connectivity problems, server outages or periodically when the channel expires.

onLogin

Arguments:

  1. username: The user's Google username string.
  2. logout_url: A URL that the user can load to terminate their session. This should be opened in a new window (using target="_blank").

The onLogin callback is called when the user logs in. It is also called after the first RPC to the server succeeds if the user was already logged in. It is guaranteed that either onLogin or onLogout is called after the first RPC succeeds.

onLogout

Arguments:

  1. login_url: A URL that the user cna load to log in to their Google account. This should be opened in a new window (using target="_blank").

The onLogin callback is called when the user logs out or is logged out by Google. It is also called after the first RPC to the server succeeds if the user was not already logged in. It is guaranteed that either onLogin or onLogout is called after the first RPC succeeds.

onMessage

Arguments:

  1. message: A message object including metadata and message content.

The onMessage callback is called when a historical or new message is received from the server. It is only called for subjects that the client is currently subscribed to.

After a call to subscribe(), onMessage fires once for each historical message received from the server. After all historical messages have been processed, the resolve callback for the Promise returned by subscribe() is called. Any onMessage events after that point are for new messages.

Calling subscribe() more than once may lead to additional historical messages being retreived. onMessage will not fire twice for the same message unless unsubscribe() is called in the interim.

onMessage fires for messages sent by our own profile and client. You can filter messages by comparing their sender field to the return value of currentProfile() to avoid processing your own messages.

onPin

Arguments:

  1. message: A message object including metadata and message content.

The onPin callback is called when a new pin is received from the server. It is only called for subjects that the client is currently subscribed to.

After a call to subscribe(), onPin fires once for each pin already present in the subject. After all standing pins have been processed, the resolve callback for the Promise returned by subscribe() is called. Any onPin events after that point are for new pins.

onPin callbacks are paired with onUnpin callbacks except when shutdown() is called.

onPin fires for pins from own profile and client. You can filter pins by comparing their sender field to the return value of currentProfile() to avoid processing your own pins.

onUnpin

Arguments:

  1. message: A message object including metadata and message content.

The onUnpin callback is called when a pin is deleted on from the server. It is also called when the channel disconnects from the server, hence the server state of pins is unknown.

onUnpin callbacks are paired with onPin callbacks except when shutdown() is called.

onUnpin fires for pins from own profile and client. You can filter pins by comparing their sender field to the return value of currentProfile() to avoid processing your own pins.