Skip to main content

02 Service и Host

Сервис

Сервис - это js класс наследуемый от Service, главный элемент системы.

Сервис

  • имеет уникальное имя, обычно запускается в одном экземпляре
  • может быть ограничен рабочим пространством(workspace), иначе он будет доступен во всех рабочих пространствах
  • имеет схему сервиса, через которую описывает свои возможности, как публичные, так и приватные, доступные только другим сервисам
  • запросы(request), могут вызваться из других сервисов или публично
  • события(event), на которые могут быть подписаны другие сервисы

Для выполнения инициализации своего сервиса нужно перегрузить метод start.

import {Service} from "@morphcluster/core"
export default class Test extends Service {
  async start() {
    console.log("Starting")
  }
}

stop работает по аналогии

Схема Сервиса

Схема используется для передачи между хостами, возможностей сервисов. Также, может использовтся для генерации клиентских и mock реализаций. Схема описывается через json такого вида:

{
    name:"MyService",
    requests: [
        {
            name:"run",
            http: 'POST',
            request:{
                "type": "object",
                "properties": {
                    "name": { "type": "string" },
                    "params": {},
                },
                "required": [ "name" ]
            },
            response:{},
            description:"Выполнить метод",
        }
    ]
}

Схему целиком можно установить через метод setSvcSchema(serviceSchema). Через метод getSvcSchema() можно получить текущую схему, вместе с добавленными изменениями отдельно.

Схема сервиса может содержать:

name

Имя сервиса, можно указать в сервисе через this.name = "NewName". По умолчанию высталяется автоматически имя класса.

requests

Массив, который описывает все запросы сервиса. Запрос состоит из:

  • name(string) - имя запроса, должно совпадать с именем метода, его реализующего
  • description(string) - короткое описание
  • request(object) - json schema параметров запроса, для валидации
  • response(object) - json schema ответа, для валидации
  • anonymous(boolean) - запрос можно вызвать без сессии, у авторизованного пользователя сессия будет приходить
  • needAdmin(boolean) - снаружи, запрос может вызвать только администратор
  • noLogs(boolean) - запрос не требует передавать ему логгер при вызове
  • http(string) - запрос будет опубликован по HTTP, значение (GET или POST)

Методы в схему можно добавить отдельно, через вызов addRequest. Неопубиликованные методы нельзя будет иcпользовать за пределами хоста.

this.addRequest({
  name : 'test',
  request: {},
  description:"..."
})

events

События вызываются внутри сервиса и на них могут быть подписаны другие сервисы, например для отслеживания изменений. Вызов события не имеют ответа.

Чтобы создать событие, надо объявить его в конструкторе сервиса и описать в схеме сервиса. Событие будет направлено в определенный workspace, указанный в первом параметре. События можно добавить в схему, аналогично addRequest, через addEvent, либо в общем json схемы.

import {Service, Event} from "@morphcluster/core"
...
export default class EvntSvc extends Service {
  constructor(host) {
    ...
    //Объявление собыия
    this.onChanged = new Event()
    //Добавление в схему
    this.addEvent({
      name: "onChanged",
      description: "Данные изменились",
    })
  }

  test() {
    //Вызов события
    this.onChanged.emit("myWorkspace", {"test":123})
  }
}

Подписаться на вызов события можно через on. Второй аргумент - workspace, в который нужно отслеживать или null, чтобы принять событие из всех рабочих пространств.

this.EvntSvc.onChanged.on((payload)=>console.log(payload), "myWorkspace")

Структура схемы:

  • name(string) - имя события, должно совпадать с именем поля
  • description(string) - короткое описание
  • request(object) - json schema параметров, передаваемых в событии

Хост

Каждый процесс nodejs формирует хост, внутри которого запускаются сервисы, которые, по отношению друг к другу будут локальные. Чтобы локальные сервисы могли найти друг друга, их нужно добавить в созданный объект ServiceHost, а его экземпляр передать в конструктор.

ServiceHost - коллекция экземпляров сервисов, через которую разные сервисы взаимодействуют друг с другом. Хранимые сервисы в ServiceHost можно добавлять как вручную, через addService, так и через ServiceFactory или другие сервисы. После добавления новый сервис автоматически запустится, если еще это не сделано.

 import {ServiceHost} from '@morphcluster/core'
 host = new ServiceHost()      
 host.addService(new HelloWorld(host))

Поучить запущенный сервис вручную из ServiceHost можно через метод requireService. Если сервис не закончил запуск, он не вернется.

ServiceRequire

Чтобы использовать сторонние сервисы в своем сервисе, можно наследовать свой класс от ServiceRequire. Перед запуском, ServiceRequire дождется запуска всех своих зависимостей.

import {ServiceRequire} from "@morphcluster/core"

export default class HelloWorlds extends ServiceRequire {
  constructor(host) {
    super(host)
    //Объявление поля для ссылки на зависимый сервис
    //Для работы подсказок внутри IDE и лучшей читаемости кода
    /** @type {Test} */
    this.HelloWorld = null
    //Список зависимостей
    this.requrements = [ "HelloWorld" ]
  }
  async start() {
    await super.start()
    //Вызов метода из другого сервиса, после super.start
    await this.Test.test({}, "common", null)
  }
}