Перейти к содержанию

RadioService#

Наследник класса Service. Содержит функционал обмена сообщений в реальном времени.

Основное назначение сервиса - обеспечить получение клиентом сообщений, передача которых инициирована отправителем.

Маршрутизация сообщений#

Маршрутизация сообщений обеспечивается средствами каналов и типов. Перечень каналов в проекте указываются в настройках проекта (см ниже ).

Каналы#

Предполагается, что каждая библиотека и каждое конечное приложение должны иметь свой канал для обмена сообщениями. Чтобы избежать пересечения имён каналов, рекомендуется использовать в качестве названия канала имя npm-пакета, содержащего поставляемый функционал. Например, системные сообщения передаются по каналу "ecosoft-lexema8".

Обращение:

// в контексте класса формы
const coreChannel = this.services.radio.channels['ecosoft-lexema8'] // "системный" канал

Типы#

Каждый канал может иметь свой собственный набор возможных типов сообщений, названия которых должны быть уникальны только в рамках канала. Названия типов сообщений канала определяются командой, которая занимается разработкой пакета, содержащего поставляемый функционал. Таким образом, названия типов сообщений являются частью публичного API приложения / библиотеки.

В набор типов сообщений канала ecosoft-lexema8 входит тип с именем "legacy", предназначенный для обеспечения поддержки обратной совместимости с функционалом, задействованном в обмене нетипизированными сообщениями в версии 8.3 и ранее.

Для отправления и подписки на получение сообщений конкретного типа на клиенте используются экземпляры класса RadioSignal (для краткости далее именуемые "сигналами"), который является наследником класса Signal.

Отправка сообщения#

Отправка сообщения заданного типа осуществляется посредством вызова метода send экземпляра сигнала, представляющего соответствующий тип сообщений.

1
2
3
4
5
6
7
// в контексте класса формы
  // ...
  const chat = this.services.radio.channels['ecosoft-lexema8-chat']
  const chat.messageCreated.send({
    receivers: ['receiver1UserName', 'receiver2UserName'],
    payload: { text: 'hello, world' }
  })

Метод send принимает единственный аргумент - объект со следующими свойствами:

  • receivers - либо массив имён пользователей-получателей, либо строковая константа $:online (означающая, что сообщение должно быть доставлено всем пользователям, пребывающим онлайн)
  • payload - т.н. "полезная нагрузка", содержимое сообщения
  • options - объект, представляющий набор дополнительных параметров отправки сообщения (необязательное свойство)
    • durable - флаг, означающий, что до получения уведомления о доставке сообщение необходимо хранить в промежуточном хранилище
    • ttl - "time to live", время (в минутах) хранения сообщения в промежуточном хранилище (не используется, если durable = false)
    • enableReplacement - флаг разрешающий отправку сообщения замещающему пользователю(по умолчанию = false)

Получение сообщения#

Для получения сообщения заданного типа необходимо добавить функцию-обработчик к соответствующему сигналу:

1
2
3
4
5
6
// в контексте класса формы
// ...
const chat = this.services.radio.channels['ecosoft-lexema8-chat']
const chat.messageCreated.add(({ payload: { text = '' } }) => {
    console.log(text)
})

Единственный параметр, поступающий в функцию-обработчик события получения сообщения - объект со следующими свойствами:

  • id - уникальный идентификатор сообщения
  • timestamp - число, представляющее момент отправления сообщения
  • sender - логин отправителя
  • payload - т.н. "полезная нагрузка", содержимое сообщения

Конфигурирование#

Настройка списка используемых каналов и названий типов сообщений (сигналов) осуществляется через стандартный механизм конфигурирования 8.4:

// ...
applications: {
    // ...
    radio: {
        channels: {
            'ecosoft-lexema8-config': ['messageCreated', 'userIsTyping'],
            'ecosoft-lexema8-chocolate': ['kindCreated', 'kindSearched']
        }
    }
}

Отправка сообщения через сервис#

В Лексеме есть возможность глобального оповещения всех пользователей "с наружи", то есть без обращения к сервису radio на прямую.

Необходимо в rabbitmq отправить сообщение в очередь с именем ecosoft-lexema8:radio:systemNotification. Сообщение представляет собой json-строку следующей структуры:

{ text: 'Текст', type: 'error' }

, где

  • text - текст сообщения
  • type - необязательные параметр отвечающий за то, какой тип сообщения ('error', 'info') выведется пользователям (по умолчанию error)

Решение

Данный тип сообщения можно использовать для глобального оповещения всех пользователей.

Пример оповещения при деплое перед остановкой сайта: RestartNotification

Пример#

Пример из демо-проекта

Форма с приёмом и отправкой сообщений

import { Form } from 'ecosoft-lexema8'
import template from './simpleDemo.xml'

export default class RadioSimpleDemo extends Form {
    constructor (args) {
        super(args)

        const test = this.services.radio.channels['ecosoft-lexema8-config']
        this.controls.receivers.value = this.services.access.userName

        test.messageCreated.add(({ payload: { text = '' } }) => {
            console.log('ww', text)
            const existing = this.controls.messages.value
                ? `${this.controls.messages.value}\n`
                : ''
            this.controls.messages.value = `${existing}${text}`
        })

        test.userIsTyping.add(({ sender }) => {
            clearTimeout(this._typingTimeout)
            this.controls.typing.value = `${sender}...`

            this._typingTimeout = setTimeout(() => {
                this.controls.typing.value = ''
            }, 500)
        })
    }

    get receivers () {
        return this.controls.receivers.value.split(',').map((userName = '') => {
            return userName.trim()
        })
    }

    minute () {
        //this.services.radio.soon({ minute: 3 })
    }

    send () {
        const text = this.controls.text.value
        const receivers = this.receivers
        const test = this.services.radio.channels['ecosoft-lexema8-config']

        test.messageCreated.send({ receivers, payload: { text } })
    }

    sendWithTTL () {
        const text = this.controls.text.value
        const receivers = this.receivers
        const test = this.services.radio.channels['ecosoft-lexema8-config']

        test.messageCreated.send({ receivers, payload: { text }, options: { ttl: 1 } })
    }

    typing () {
        const test = this.services.radio.channels['ecosoft-lexema8-config']
        test.userIsTyping.send({ receivers: this.receivers, payload: { text: '' } })
    }

    static get template () {
        return template
    }
}