'subscr' capability for WebSocket User API

Overview

The module is used to subscribe to system events. Events occurring in the system are categorized into classes, packaged into objects with event data, and sent to subscribers using filters.

Events are only sent within an existing subscription. If the same event qualifies for multiple subscriptions, a separate notification is sent for each subscription. Each feast may realize any reasonable number of subscriptions.

Inquiries and responses

To subscribe, you must submit a subscribe request, specifying the event class and associated identifying information.

A subscription has a lifetime. Regular subscription renewal is required to organize long cycles. The recommended mode is to subscribe with a unique identifier for a period of up to 3600 seconds, and then send a request with the same identifier and the same period in advance of the expiration of the previous subscription time. The other fields may be omitted. For 300-second subscriptions, it is optimal to resubscribe after 240 seconds. For 3600-second subscriptions, after 3000 seconds.

A subscription can contain filters. Depending on which event class it is, filters can be set and applied differently.

If the request is sent with the ID of an existing subscription, it is treated as either a renewal (with a non-zero 'expires' value) or an unsubscription (with a zero value 'expires'). Deleting a subscription is done by sending a "subscribe" request with the identifier of the subscription of interest in the 'id' field and the value 'expires': 0. No access rights check is performed during deletion.

If a subscription renewal request contains values of other fields ('events', 'objects', 'classpath', 'exargs') that differ from the original request, the subscription is modified according to the new data. This method of change is not recommended because it can cause transaction collisions when processing dense event streams.

General view of the request:
[
  "subscribe",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda09db22",
    "objects": ...,
    "events": ...,
    "expires": ...,
    "id": ...
    "exargs": ...
    ...
  }
]
  • events - event list for filtering event types. A list of strings is specified, each representing a different event type, e.g. "callevents.dlg_start". For some classes it is acceptable to specify "callevents.*".

  • objects - list of objects to filter events. The value "any" or a list of values can be specified, for example '["sipuser1","sipuser2"]'.

  • expires - subscription lifetime in seconds. If necessary, the subscriber should extend the subscription by resending the request with a non-zero value 'expires'.

  • id - subscription identifier. If not specified in the request, it is generated automatically and in any case returned in the response so that the subscription can be managed: renewal and deletion.

  • exargs - object with specific subscription settings. In particular, when subscribing to "modelevents.data_changed", a filter and masking can be set up (mask).

  • classpath - for events of class 'modelevents' can be specified instead of 'objects' and contain the full path (endpoint) of the class, e.g. "/rest/v1/model/my/Records" or "/rest/v1/uc/calls".

It is allowed to subscribe to several events of the same class at the same time and to several objects at the same time.

A general view of a successful response:
[
  "subscribe_result",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda09db22",
    "success": true,
    "id": ...,
    "msg": "subscribed",
    "domain": ...
  }
]
  • success - flag-an indication that the subscription is successful.

  • id - subscription identifier, which can be used to manage the subscription: renewal and deletion. It will also be indicated in the notifications of the corresponding notifications sent under this subscription.

  • msg - subscription result.

  • domain - the domain in which the subscription is made.

Notifications

Notifications are sent to subscribers taking into account the set objects, filters, masks. Contains a 'data' field with content corresponding to event type specification.

Notification Format:
[
  "notify",
  {
    "class": string,
    "eventts": integer,
    "sid": string,
    "type": string,
    "data": object
  }
]
  • class - Event Class.

  • type - event type.

  • eventts - event timestamp.

  • sid - subscription identifier (mandatory for notifications of class 'modelevents', may be absent in others).

  • data - event content according to the specification in Events.

Example Notice:
[
  "notify",
  {
    "class": "modelevents.data_changed",
    "type": "data_changed",
    "eventts": 1692042096897,
    "sid": "81edebaa-0189-f5cd-80e2-7cd30a921f58",
    "data": {
      "classname": "sipusers",
      "classpath":"/rest/v1/uc/sipusers",
      "eid": "57278625-5fa4-eb0c-fb53-f6fa26881f25",
      "operation": "update",
      "entity": {
        "id":"57278625-5fa4-eb0c-fb53-f6fa26881f25","iduser":"e7adf0aa-05b7-8163-948c-3392a9660db9","lic":{"devices":123456789},
        "login": "sip1",
"name": "SIP1Sip-{D}",
        "phonenumber": "11",
        "reg": 1,
        "opts":{
         "calltimesec": 37,
         "dlgtimesec": 300,
         "title": ""
        }
      },
      "modifier_type": "user",
      "modifier_id": "e7adf0aa-05b7-8163-948c-3392a9660db9"

    }
  }
]

Event classes

The following categories of events are distinguished:

Notifications are also possible for project events generated in scenarios.

Class events modelevents

Events of this type are generated immediately when changes are made to the data model, both static (dc) and dynamic models (dms). There is a single event "data_changed" in the class. Detailed description of class events here.

When the "subscribe" request is processed, authorization for the operation of reading collection items is performed. Accordingly, a user must be added a role that has permission to route to the endpoint of a collection item by method 'GET'.

The "notify" event delivers data about the operation performed, as well as the current value of the changed entity with correction for the mask ('exargs.mask'). When creating a subscription with a filter ('exargs.filter'), events can be filtered. The filter and mask are set in a form similar to the parameters of the REST request GET parameters of an item collection (Read more).

Deliverable events on a particular entity are always driven to "create", "update" and "delete" based on a comparison of the previous value and the new value with the filter. So, if the previous value did not fall under the filter, but after the change it does, then the event will be delivered and have a "create" operation despite the fact that the actual operation "update" or "replace".

Types of operations:

  • create - an entity is created and falls under the filter, or is modified so that it now falls under the subscription filter.

  • update - entity is changed, and both the past and current values fall under the subscription filter.

  • delete - the entity has been deleted or modified so that it is no longer subject to the subscription filter.

  • reload - the queue for processing requests by class is reloaded. To ensure integrity, a repeated REST request to select items from the collection with a filter is required.

  • clear - the collection has been cleared.

  • corrupt - when processing a request for an entity, a storage problem has occurred, the current state of the entity may be mismatched, and the entity needs to be updated with a REST request.

A correct subscription request must contain exactly one object (class name or class path in REST-API) and exactly one event type — "modelevents.data_changed".

To specify a particular collection, the 'classpath' field is mostly used, in which case the 'objects' field is ignored.

In case of large event streams, the use of masks and filters can significantly reduce the load on the system.

A large number of simultaneous subscriptions with different filters for the same collection can significantly increase the load on the system.

The following approaches can be used to handle class events: * subscription to a collection with a mask leaving only one or two fields, and a request to read the object when an event arrives. * subscribe without mask and use the object directly from the event body. * subscription for a short period of time while the data is being processed. For example, subscription to changes of the object-query with filtering by identifier and state, creation of the object-query with this identifier, tracking of the event about transition of the object-query to the state of interest, deletion of the subscription. * object caching: subscribing to a collection and following it by proofreading the data into the cache; then modifying the data in the cache when events arrive; periodic full proofreading of the data into the cache at long intervals.

Request example:
[
  "subscribe",
  {
    "qid": 0.15994723,
    "id": "abcdabcd-abcd-abcd-abcd-abcdabcdabcd",
    "events": ["modelevents.data_changed"],
    "classpath": "/rest/v1/model/my/Records",
    "expires": 300,
    "exargs": {
      "filter": ["==",["property","code"],"aaa"],
      "mask": ["id","name"]
    }
  }
]

Class events callevents

Telephony events. Detailed description of class events here.

The 'events' field may list the callevents class events of interest, or it may specify a full mask: "callevents.*".

The filter by dialog participants mentioned in the event can be specified in the field 'objects'.

Request example:
[
  "subscribe",
  {
    "qid": 0.105938272,
    "id": "bcdebcde-bcde-bcde-bcde-bcdebcdebcde",
    "events": ["callevents.*"],
    "objects": ["11"],
    "expires": 300
  }
]

Class events ivrevents

Scenario Events IVR. Detailed description of class events here.

The 'events' field may list the callevents class events of interest, or it may specify a full mask: "ivrevents.*".

Practical use can be made of the ivrevents.api_start and ivrevents.api_stop events, which are used to notify when the script is ready to hand over control to an external module.

Request example:
[
  "subscribe",
  {
    "qid": 0.105938272,
    "id": "cdefcdef-cdef-cdef-cdef-cdefcdefcdef",
    "events": ["ivrevents.api_start", "ivrevents.api_stop"],
    "objects": ["any"],
    "expires": 300
  }
]