Функции
Функции — синхронные точки входа без состояния. Вызываете их, они выполняются, возвращают результат. При выполнении функция наследует контекст вызывающего — если вызывающий отменяется, функция тоже. Это делает функции идеальными для HTTP-обработчиков, API-эндпоинтов и любых операций, которые должны завершиться в рамках жизненного цикла запроса.
Вызов функций
Вызывайте функции синхронно через funcs.call():
local funcs = require("funcs")
local result, err = funcs.call("app.api:get_user", user_id)
Для неблокирующего выполнения используйте funcs.async():
local future = funcs.async("app.process:analyze", data)
local ch = future:response()
local result, ok = ch:receive()
См. модуль funcs для полного API.
Распространение контекста
Каждый вызов создаёт фрейм со своей областью контекста. Дочерние функции наследуют родительский контекст без явной передачи:
local ctx = require("ctx")
local trace_id = ctx.get("trace_id")
local user_id = ctx.get("user_id")
Добавляйте контекст при вызове:
local exec = funcs.new()
:with_context({trace_id = "abc-123"})
:call("app.api:process", data)
Контекст безопасности распространяется так же. Вызываемые функции видят актора вызывающего и могут проверять разрешения. См. модуль security для API контроля доступа.
Определение в реестре
На уровне реестра запись функции выглядит так:
- name: get_user
kind: function.lua
source: file://handlers/user.lua
method: get
pool:
type: lazy
max_size: 16
Функции могут вызываться другими компонентами среды исполнения — HTTP-обработчиками, потребителями очередей, запланированными задачами — и подчиняются проверкам разрешений на основе контекста безопасности вызывающего.
Пулы
Функции работают на пулах, управляющих выполнением. Тип пула определяет поведение масштабирования.
Inline выполняется в горутине вызывающего. Никакой конкурентности, нулевой оверхед аллокаций. Используется для встроенных контекстов.
Static поддерживает фиксированное число воркеров. Запросы ставятся в очередь, когда все воркеры заняты. Предсказуемое использование ресурсов.
pool:
type: static
workers: 8
buffer: 512
Lazy стартует пустым и создаёт воркеров по запросу. Простаивающие воркеры уничтожаются по таймауту. Эффективен для переменной нагрузки.
pool:
type: lazy
max_size: 32
Adaptive масштабируется автоматически на основе пропускной способности. Контроллер измеряет производительность и подстраивает число воркеров под текущую нагрузку.
pool:
type: adaptive
max_size: 256
workers для static, max_size для lazy, или явно задайте type для полного контроля.
Интерсепторы
Вызовы функций проходят через цепочку интерсепторов. Интерсепторы обрабатывают сквозную функциональность, не затрагивая бизнес-логику.
- name: my_function
kind: function.lua
source: file://handler.lua
method: main
meta:
options:
retry:
max_attempts: 3
initial_delay: 100
backoff_factor: 2.0
Встроенные интерсепторы включают retry с экспоненциальным backoff. Можно добавить свои интерсепторы для логирования, метрик, трассировки, авторизации, circuit breaking или трансформации запросов.
Цепочка выполняется до и после каждого вызова. Каждый интерсептор может модифицировать запрос, прервать выполнение или обернуть ответ.
Контракты
Функции могут предоставлять схемы ввода/вывода как контракты. Контракты определяют сигнатуры методов, обеспечивая валидацию во время выполнения и генерацию документации.
local contract = require("contract")
local email = contract.get("app.email:sender")
email:send({to = "user@example.com", subject = "Hello"})
Эта абстракция позволяет подменять реализации без изменения вызывающего кода — полезно для тестирования, мультитенантных деплоев или постепенных миграций.
Функции vs Процессы
Функции наследуют контекст вызывающего и привязаны к его жизненному циклу. Когда вызывающий отменяется, функции отменяются. Это обеспечивает edge-выполнение — работу прямо в HTTP-обработчиках и потребителях очередей.
Процессы работают независимо с контекстом хоста. Они переживают своего создателя и общаются через сообщения. Используйте процессы для фоновой работы; используйте функции для операций в рамках запроса.