Сервис-функции | Tdg

Сервис-функции

Сервис-функции (services) – это хранимые процедуры, реализующие бизнес-логику решения и доступные для вызова извне. В TDG такие процедуры представляют собой функции на языке Lua.

Чтобы добавить в TDG вызываемый сервис, нужно:

  1. Задать конфигурацию сервиса в формате YAML: его имя, аргументы вызова, возвращаемое значение.

  2. Реализовать необходимую логику на языке Lua с использованием Lua API TDG.

  3. Загрузить файлы с исходным кодом и конфигурацией сервиса в TDG.

После этого TDG автоматически сгенерирует API для вызова сервиса через GraphQL, REST API и iproto (бинарный протокол Tarantool).

В этом руководстве рассмотрим пример создания нового сервиса в TDG и способы его вызова.

Для выполнения примера требуются:

  • настроенный кластер TDG;

  • модель данных, сохраненная в файле model.avsc. В примере используется модель из раздела по настройке модели данных;

  • HTTP-клиент, например, curl.

Пример сервиса будет возвращать список всех городов страны, загруженных в хранилище, по её имени.

Руководство включает в себя следующие шаги:

Подготовка конфигурации сервиса

Чтобы добавить в TDG сервис, необходимо добавить соответствующую секцию в конфигурацию TDG. Сервисы можно описывать либо в общем конфигурационном файле (секция services в файле config.yml), либо в отдельном файле services.yml.

Конфигурация сервиса включает такие параметры, как его уникальное имя, вызываемая функция, аргументы вызова, тип возвращаемого значения и другие. Полная информация о параметрах конфигурации сервисов приведена в справочнике по конфигурации бизнес-логики.

Пример минимальной конфигурации сервиса без аргументов:

# config.yml

services:
  hello_world:
    doc: "Hello World script"
    function: hello.hello
    return_type: string

Создадим конфигурацию сервиса для получения всех городов по названию страны:

# config.yml

services:
  get_cities:
    doc: "Get cities by country name"
    function: cities.get_cities
    return_type: {"type":"array", "items":"City"}
    args:
      country: string

types:
   __file: model.avsc

Эта конфигурация задаёт следующее поведение:

  • Сервис будет доступен для вызова через GraphQL по имени get_cities и через REST API по адресу http://localhost:8081/service/get_cities;

  • При вызове будет выполняться функция get_cities из файла cities.lua;

  • Сервис будет возвращать массив объектов пользовательского типа City;

  • Сервис будет принимать один строковый аргумент – название страны.

Реализация логики на Lua

Как указано в конфигурации сервиса, его код должен храниться в файле cities.lua в функции get_cities. Этот файл может выглядеть следующим образом:

-- cities.lua

local repository = require('repository')
local log = require('log')
local json = require('json')

function get_cities(arg)
  log.info('Getting cities of: %s', json.encode(arg))
  local result = repository.find("City", {{'country', '==', arg["country"]}})
  return result
end

return {
    get_cities = get_cities
}

Использование аргументов сервиса

Все аргументы сервиса передаются в первый аргумент функции в виде Lua-таблицы. Ключами в этой таблице являются имена аргументов, объявленные в конфигурации сервиса. Таким образом, для обращения к конкретному аргументу необходимо получить элемент таблицы по имени из конфигурации сервиса, например, arg["country"].

Использование модулей

TDG предоставляет набор Lua-модулей для реализации бизнес-логики. Набор включает как модули для работы с хранилищем Tarantool и подсистемами TDG, так и модули для работы с распространёнными технологиями, такими как различные СУБД или JSON.

В этом примере используются модули:

  • repositoryинтерфейс репозитория TDG. Содержит функции для работы с данными в хранилище Tarantool. В примере используется repository.find для поиска подходящих объектов типа City.

  • log – запись в журнал TDG. В примере используется log.info для записи в журнал информации о вызовах сервиса.

  • json – работа с JSON. В примере используется json.encode для формирования строкового JSON представления переданного аргумента.

Загрузка сервиса

Чтобы выполнить пример, нужно загрузить архив с моделью данных, файлом конфигурации и функцией сервиса в TDG:

  1. Поместите Lua-файл с кодом сервиса в папку src.

  2. Упакуйте в zip-архив:

    • папку src, внутри которой лежит файл с кодом сервиса;

    • модель данных model.avsc;

    • файл конфигурации config.yml.

  3. Загрузите архив в TDG согласно инструкции.

Вызов сервиса

GraphQL

Чтобы вызвать сервис через GraphQL, укажите в запросе имя сервиса и аргументы в формате name:value:

query {
  get_cities(country: "Germany")
}

Как и в случае запросов к данным, GraphQL позволяет получать отдельные поля возвращаемых объектов:

query {
  get_cities(country: "Germany") {
    title,
    capital
  }
}

Ответ:

{
  "data": {
    "get_cities": [
      {
        "title": "Berlin",
        "capital": true
      },
      {
        "title": "Dresden",
        "capital": false
      },
      {
        "title": "Munich",
        "capital": false
      }
    ]
  }
}

REST API

Сервисы доступны для вызова через REST API на HTTP-адресах (endpoint) вида /service/<service_name>. Для вызова сервисов используются POST-запросы.

Для вызова сервиса без аргументов отправьте POST-запрос на соответствующий адрес, например:

curl -X POST http://localhost:8081/service/hello_world

Если у сервиса есть аргументы, передайте их одним из двух способов:

  • в параметрах запроса с соответствующими именами:

    curl -X POST http://localhost:8081/service/get_cities?country=Russia
    
  • в теле запроса в формате JSON:

    curl -d '{"country":"Russia"}' -H "Content-Type: application/json" \
    -X POST http://localhost:8081/service/get_cities
    

Ответ:

{
  "result": [
    {
      "cursor": "gaRzY2FukqZSdXNzaWGmTW9zY293",
      "country": "Russia",
      "title": "Moscow",
      "population": 12655050,
      "postcodes": [
        101000,
        119021,
        115035,
        109028,
        109004
      ],
      "capital": true
    },
    {
      "cursor": "gaRzY2FukqZSdXNzaWGwU2FpbnQgUGV0ZXJzYnVyZw",
      "country": "Russia",
      "title": "Saint Petersburg",
      "population": 5384342,
      "postcodes": [
        191193,
        191040,
        195275,
        983002,
        983015
      ],
      "capital": false
    },
    {
      "cursor": "gaRzY2FukqZSdXNzaWGkVHZlcg",
      "country": "Russia",
      "title": "Tver",
      "population": 424969,
      "postcodes": [
        170006,
        170100,
        170037,
        170028
      ],
      "capital": false
    }
  ]
}

Полная информация о REST API сервисов TDG приведена в справочнике по REST API.

Found what you were looking for?
Feedback