diffusion
Version:
Diffusion JavaScript client
396 lines (383 loc) • 16.1 kB
JavaScript
var _interface = require('util/interface')._interface;
/**
*
* Diffusion Session. Handles a connection to Diffusion and exposes API features. Sessions can subscribe, add, remove
* and update topics, as well as perform remote operations on the server.
* <P>
* <br />
* A session represents a single connection to a single Diffusion server. A session begins connected and will remain
* so until until it is explicitly closed via {@link Session#close} or there is a connection error.
* <P>
* When a connected session loses its connection to the server, it will close if {@link Session.Options}
* <code>reconnect</code> is not enabled. If reconnect is enabled then the session will enter a
* <code>disconnected</code> state. Once disconnected, any API methods that involve the server will automatically fail.
* It is possible for a session to lose messages while disconnected.
* <P>
* The session will attempt to reconnect to the server on a regular basis. This will continue until the server responds;
* at which point the session will attempt to recover its previous connection.
* <P>
* If the reconnection is succesful the session will become connected again and emit a <code>reconnect</code> event.
* Any prior subscriptions will continue to receive data.
* <P>
* If the server rejects the reconnection, the session will be closed.
* <P>
* Sessions emit events to notify listeners of changes in state. Certain events will provide arguments to any callback
* functions that have been registered.
*
* <H3>Session properties</H3>
* <P>
* For each session, the server stores a set of session properties that describe
* various attributes of the session.
* <P>
* There are two types of session property. Fixed properties are assigned by the
* server. User-defined properties are assigned by the application.
* <>
* Many operations use session filter expressions (see section Session Filters)
* that use session properties to select sessions.
* <P>
* A privileged client can monitor other sessions, including changes to their
* session properties, using a {@link
* Session.clients#setSessionPropertiesListener session properties listener}.
* When registering to receive session properties, special key values of {@link
* diffusion.clients.PropertyKeys#ALL_FIXED_PROPERTIES ALL_FIXED_PROPERTIES} and
* {@link diffusion.clients.PropertyKeys#ALL_USER_PROPERTIES
* ALL_USER_PROPERTIES} can be used.
* <P>
* Each property is identified by a key. Most properties have a single string
* value. The exception is the $Roles fixed property which has a set of string
* values.
* <P>
* Fixed properties are identified by keys with a '$' prefix. The available
* fixed session properties are:
* <table border summary="">
* <tr>
* <td><b>Key</b></td>
* <td><b>Description</b></td>
* <tr>
* <tr>
* <td>`$ClientIP`</td>
* <td>The Internet address of the client in string format. See
* {@link ClientLocation}.address.</td>
* </tr>
* <tr>
* <td>`$ClientType`</td>
* <td>The client type of the session. One of `ANDROID`, `C`, `DOTNET`, `IOS`,
* `JAVA`, `JAVASCRIPT_BROWSER`, or `OTHER`. Equivalent to {@link
* ClientSummary}.clientType.</td>
* </tr>
* <tr>
* <td>`$Connector`</td>
* <td>The configuration name of the server connector that the client connected
* to. See {@link SessionDetails}.connector.</td>
* </tr>
* <tr>
* <td>`$Country`</td>
* <td>The country code for the country where the client's Internet address was
* allocated (for example, `NZ` for New Zealand). If the country code could not
* be determined, this will be a zero length string. See {@link
* ClientLocation}.details.country.</td>
* </tr>
* <tr>
* <td>`$Language`</td>
* <td>The language code for the official language of the country where the
* client's Internet address was allocated (for example, `en` for English). If
* the language could not be determined or is not applicable, this will be a
* zero length string. See {@link ClientLocation}.details.language.</td>
* </tr>
* <tr>
* <td>`$Latitude`</td>
* <td>The client's latitude, if available. This will be the string
* representation of a floating point number and will be `NaN` if not
* available. See {@link ClientLocation}.coordinates.latitude.</td>
* </tr>
* <tr>
* <td>`$Longitude`</td>
* <td>The client's longitude, if available. This will be the string
* representation of a floating point number and will be `NaN` if not
* available. See {@link ClientLocation}.coordinates.longitude.</td>
* </tr>
* <tr>
* <td>`$Principal`</td>
* <td>The security principal associated with the client session. Equivalent to
* {@link ClientSummary}.principal</td>
* </tr>
* <tr>
* <td>`$Roles`</td>
* <td>Authorisation roles assigned to the session. This is a set of roles
* represented as quoted strings (for example, `"role1","role2"`). The
* utility method {@link diffusion#stringToRoles} can be used to parse
* the string value into a set of roles.</td>
* </tr>
* <tr>
* <td>`$ServerName`</td>
* <td>The name of the server to which the session is connected. See
* {@link SessionDetails}.server.</td>
* </tr>
* <tr>
* <td>`$SessionId`</td>
* <td>The session identifier. Equivalent to {@link Session.sessionID}.</td>
* </tr>
* <tr>
* <td>`$StartTime`</td>
* <td>The session's start time in milliseconds since the epoch.</td>
* </tr>
* <tr>
* <td>`$Transport`</td>
* <td>The session transport type. One of `WEBSOCKET`,
* `HTTP_LONG_POLL`, or `OTHER`. Equivalent to
* {@link ClientSummary}.transportType.</td>
* </tr>
* </table>
* <p>
* All user-defined property keys must be alphanumeric, starting with an
* alphabetic character, and are case sensitive. Embedded whitespace is not
* allowed.
* <p>
* Session properties are initially associated with a session as follows:<br>
* <ol>
* <li>When a client starts a new session, it can optionally propose
* user-defined session properties (see {@link Session.Options}.properties).
* Session properties proposed in this way must be accepted by the
* authenticator. This safeguard prevents abuse by a rogue, unprivileged client.
* <li>The server allocates all fixed property values.
* <li>The new session is authenticated by registered authenticators. An
* authenticator that accepts a session can veto or change the user-defined
* session properties and add new user-defined session properties. The
* authenticator can also change certain fixed properties.
* </ol>
* <P>
* Once a session is established, its user-defined session properties can be
* modified by clients with `VIEW_SESSION` and `MODIFY_SESSION`
* permissions using {@link ClientControl#setSessionProperties}.
* A privileged client can also modify its own session properties.
* <P>
* If a session re-authenticates (see
* {@link Security#changePrincipal changePrincipal}), the
* authenticator that allows the re-authentication can modify the user-defined
* session properties and a subset of the fixed properties as mentioned above.
* <H3>Session filters</H3>
* <p>
* Session filters are query expressions for session properties. They can be
* used to address a set of sessions based on their session properties. For
* example, it is possible to send a message to all sessions that satisfy a
* specified filter. Session filters are parsed and evaluated at the server.
* <P>
* A session filter expression consists of either a single clause, or multiple
* clauses connected by the binary operators `and` and `or`. The
* `and` operator takes precedence over `or` but parentheses can be
* used to override the precedence. For example:
* * `Department is "Accounts"`
* * `hasRoles ["operator" "trading desk"]`
* * `Department is "Payroll" and Status is "Closed"}`
* * `(Department is "Accounts" or Department is "Payroll") and Status is "Closed"}`
*
* <P>
* The boolean <b>not</b> operator may be used to negate the following clause or
* an expression within parentheses:
* * `not Department is "Payroll"`
* * `not (Department is "Payroll" or Department is "Accounts")`
*
* <P>
* An equality clause has the form <em>key operator value</em> where
* <em>key</em> is the name of a session property and <em>value</em> is the
* property value. The supported operators are `is` or `eq`, both of
* which mean "equals", and `ne` which means "does not equal". Values are
* strings enclosed within single or double quotes. Special characters
* (`"`, `'` or `\`) can be included within the value by
* preceding with the escape character `\`. The utility method
* {@link diffusion#escape} can be used to insert escape characters into
* a value.
* <p>
* `hasRoles` is a special operator for querying the `$Roles`
* session property. A `hasRoles` clause has the form <em>hasRoles
* ["role1" "role2" ... "roleN"]</em>. The clause will match sessions that have
* all the specified authorisation roles. Each role is a string enclosed within
* either single or double quotes. Roles can be space or comma separated.
* <p>
* The `$Roles` session property can also be queried with an equality
* clause, for example, `$Roles eq '"admin","client"'`, but the
* `hasRoles` clause is usually more convenient. An equality clause will
* match sessions that have exactly the listed roles. In contrast, a
* `hasRoles` clause will match any sessions with the listed roles,
* regardless of whether they have other roles. The equality clause requires the
* value to be in the canonical form produced by the
* {@link diffusion#rolesToString} utility method.
* Supported operators are as follows:
* <P>
* <table border summary="">
* <tr>
* <td><b>Operator</b></td>
* <td><b>Description</b></td>
* </tr>
* <tr>
* <td><b>is</b> or <b>eq</b></td>
* <td>equals</td>
* </tr>
* <tr>
* <td><b>ne</b></td>
* <td>not equals</td>
* </tr>
* </table>
* <P>
* All operators are case insensitive.
* <P>
* The following are examples of valid expressions:
* <P>
* * `$Principal is "Alice"`
* * `Department is "Accounts" and $Country ne "US"`
* * `$Language EQ "en" and $Country NE "US"`
* * `not (Department is "Accounts" or`
* * `"Department is "Payroll") and $Country is "FR"`
* * `Text is "xyz\"\\"`
* * `hasRoles ["operator"]}`
* * `$Transport is "wss" and hasRoles ["accountancy" "administrator"]`
* * `hasRoles ["operator"] and not hasRoles ["administrator"]`
*
* @example
* // Establish a session
* diffusion.connect('diffusion.example.com').then(function(session) {
* // Attach state listeners
* session.on({
* disconnect : function() {
* console.log('Disconnected!');
* },
* reconnect : function() {
* console.log('Phew, reconnected!');
* },
* error : function(error) {
* console.log('Session error', error);
* },
* close : function(reason) {
* console.log('Session closed', reason);
* }
* });
*
* // Do something with session...
* });
*
*
* @class Session
*
* @fires Session#disconnect
* @fires Session#reconnect
* @fires Session#error
* @fires Session#close
*
* @property {Session.security} security - Exposes system authentication capabilities via a {@link Session.security}.
* @property {Session.topics} topics - Exposes topic control capabilities via {@link Session.topics}.
* @property {Session.topicUpdate} topicUpdate - Exposes topic update capabilities via {@link Session.topicUpdate}.
* @property {Session.messages} messages - Exposes messaging capabilities via {@link Session.messages}.
* @property {Session.notifications} notifications - Exposes topic notification capabilities via
* {@link Session.notifications}.
* @property {Session.clients} clients - Exposes client control capabilities via {@link Session.clients}.
* @property {Session.Options} options - The options used when connecting.
* @property {String} sessionID - The unique id assigned to this session by the server.
*
* @augments Stream
*/
module.exports = _interface('Session', [
/**
* @property {SessionId} sessionID - The unique id assigned to this session by the server.
*/
'sessionID',
/**
* @property {Options} options - The connection options used to establish this session
*/
'options',
/**
* Close this session's connection to the server.
* <P>
* Calling this repeatedly will have no effect.
*
* @function Session#close
* @return {Session} This session
*/
'close',
/**
* Indicates if this session is currently closed, or in the process of
* closing.
* <P>
* This will not return <code>true</code> if the session is disconnected
* but attempting to reconnect.
*
* @function Session#isClosed
* @return {boolean} Whether the session is currently closed.
*/
'isClosed',
/**
* Indicates if this session is currently connected.
* <P>
* This is orthogonal to {@link Session#isClosed}, as a session may
* be disconnected and attempting to reconnect.
*
* @function Session#isConnected
* @return {boolean} Whether the session is currently connected or not.
*/
'isConnected',
/**
* Returns the principal name that this session is associated with.
*
* @function Session#getPrincipal
* @return {String} The principal for this session
*/
'getPrincipal',
/**
* Attempt to acquire a {@link SessionLock session lock}.
* <P>
* This method returns a Promise that will resolve normally if
* the server assigns the requested lock to the session. Otherwise, the
* Promise will fail with an error indicating why the lock could not
* be acquired.
*
* @function Session#lock
* @param {String} lockName the name of the session lock
* @param {diffusion.locks.SessionLockScope} scope (optional) preferred scope, defaults to
* <code>UNLOCK_ON_SESSION_LOSS</code>. The scope of
* a lock controls when it will be released automatically. If a
* session makes multiple requests for a lock using different scopes,
* and the server assigns the lock to the session fulfilling the
* requests, the lock will be given the weakest scope
* (<code>UNLOCK_ON_SESSION_LOSS</code>).
* @return a Promise that resolves when a response is received
* from the server.
*
* <p>
* If this session has successfully acquired the session lock, or
* this session already owns the session lock, the Promise
* will resolve normally with a SessionLock result.
*
* <p>
* If the Promise resolves with an error, this session
* does not own the session lock.
* @since 6.2
*/
'lock'
/**
* Emitted when a connected session has lost connection to the server, and {@link Session.Options}
* <code>reconnect</code> is enabled. The provided reason will contain the specific cause of the
* session disconnect.
*
* @event Session#disconnect
* @property {diffusion.clients.CloseReason} reason - the cause of the session disconnect.
*/
/**
* Emitted when a disconnected session has successfully reconnected.
* @event Session#reconnect
*/
/**
* Emitted when a session error has occurred. A session error occurs when
* the client cannot parse communication from the server. This occurs if a component
* between the two - for example, a proxy or load balancer - alters the communication.
*
* @event Session#error
* @property {Error} error - the error that occured.
*/
/**
* Emitted when a session is closed. This can occur because it was closed by the user, closed by the server, failed
* to connect, or the session encountered an error. The provided close reason will contain the specific cause of the
* session close.
*
* @event Session#close
* @property {diffusion.clients.CloseReason} reason - the cause of the session close.
*/
]);