Вызов функций
Вызов функций
Заголовок раздела «Вызов функций»Основной способ вызова других функций в Wippy. Выполнение зарегистрированных функций синхронно или асинхронно между процессами с полной поддержкой распространения контекста, учётных данных безопасности и таймаутов. Этот модуль центральный для построения распределённых приложений, где компоненты должны взаимодействовать.
Загрузка
Заголовок раздела «Загрузка»local funcs = require("funcs")Синхронный вызов зарегистрированной функции. Используйте, когда нужен немедленный результат и можете его ждать.
local result, err = funcs.call("app.api:get_user", user_id)if err then return nil, errendprint(result.name)| Параметр | Тип | Описание |
|---|---|---|
target | string | ID функции в формате “namespace:name” |
...args | any | Аргументы, передаваемые функции |
Возвращает: result, error
Строка target следует паттерну namespace:name, где namespace идентифицирует модуль, а name — конкретную функцию.
Запускает асинхронный вызов функции и немедленно возвращает Future. Используйте для долгих операций, где не хотите блокироваться, или когда хотите запустить несколько операций параллельно.
-- Запуск тяжёлых вычислений без блокировкиlocal future, err = funcs.async("app.process:analyze_data", large_dataset)if err then return nil, errend
-- Делаем другую работу пока вычисления идут...
-- Ждём результат когда готовыlocal ch = future:response()local payload, ok = ch:receive()if ok then local result = payload:data()end| Параметр | Тип | Описание |
|---|---|---|
target | string | ID функции в формате “namespace:name” |
...args | any | Аргументы, передаваемые функции |
Возвращает: Future, error
Создаёт новый Executor для построения вызовов с пользовательским контекстом. Используйте, когда нужно распространить контекст запроса, установить учётные данные безопасности или настроить таймауты.
local exec = funcs.new()Возвращает: Executor
Executor
Заголовок раздела «Executor»Builder для вызовов функций с опциями контекста. Методы возвращают новые экземпляры Executor (иммутабельная цепочка), так что можно переиспользовать базовую конфигурацию.
with_context
Заголовок раздела «with_context»Добавляет значения контекста, которые будут доступны вызываемой функции. Используйте для распространения данных уровня запроса: trace ID, пользовательских сессий, feature flags.
-- Распространение контекста запроса в downstream-сервисыlocal exec = funcs.new():with_context({ request_id = ctx.get("request_id"), feature_flags = {dark_mode = true}})
local user, err = exec:call("app.api:get_user", user_id)| Параметр | Тип | Описание |
|---|---|---|
values | table | Пары ключ-значение для добавления в контекст |
Возвращает: Executor, error
with_actor
Заголовок раздела «with_actor»Устанавливает актора безопасности для проверок авторизации в вызываемой функции. Используйте при вызове функции от имени конкретного пользователя.
local security = require("security")local actor = security.actor() -- Получить актора текущего пользователя
-- Вызов админской функции с учётными данными пользователяlocal exec = funcs.new():with_actor(actor)local result, err = exec:call("app.admin:delete_record", record_id)if err and err:kind() == "PERMISSION_DENIED" then return nil, errors.new("PERMISSION_DENIED", "User cannot delete records")end| Параметр | Тип | Описание |
|---|---|---|
actor | Actor | Актор безопасности (из модуля security) |
Возвращает: Executor, error
with_scope
Заголовок раздела «with_scope»Устанавливает область безопасности для вызываемых функций. Области определяют доступные разрешения для вызова.
local security = require("security")local scope = security.new_scope()
local exec = funcs.new():with_scope(scope)| Параметр | Тип | Описание |
|---|---|---|
scope | Scope | Область безопасности (из модуля security) |
Возвращает: Executor, error
with_options
Заголовок раздела «with_options»Устанавливает опции вызова: таймаут и приоритет. Используйте для операций, которым нужны временные ограничения.
-- Установить таймаут 5 секунд для вызова внешнего APIlocal exec = funcs.new():with_options({timeout = 5000})local result, err = exec:call("app.external:fetch_data", query)if err then -- Обработать таймаут или другую ошибкуend| Параметр | Тип | Описание |
|---|---|---|
options | table | Опции, специфичные для реализации |
Возвращает: Executor, error
call / async
Заголовок раздела «call / async»Версии Executor для call и async, использующие настроенный контекст.
-- Создать переиспользуемый executor с контекстомlocal exec = funcs.new() :with_context({trace_id = "abc-123"}) :with_options({timeout = 10000})
-- Несколько вызовов с тем же контекстомlocal users, _ = exec:call("app.api:list_users")local posts, _ = exec:call("app.api:list_posts")Возвращается вызовами async(). Представляет выполняющуюся асинхронную операцию.
response / channel
Заголовок раздела «response / channel»Возвращает базовый канал для получения результата.
local future, _ = funcs.async("app.api:slow_operation", data)local ch = future:response() -- или future:channel()
local result = channel.select { ch:case_receive(), timeout:case_receive()}Возвращает: Channel
is_complete
Заголовок раздела «is_complete»Неблокирующая проверка завершённости future.
while not future:is_complete() do -- делаем другую работу time.sleep("100ms")endlocal result, err = future:result()Возвращает: boolean
is_canceled
Заголовок раздела «is_canceled»Возвращает true если cancel() был вызван на этом future.
if future:is_canceled() then print("Operation was canceled")endВозвращает: boolean
Возвращает закэшированный результат если завершён, или nil если ещё выполняется.
local value, err = future:result()if err then print("Failed:", err:message())elseif value then print("Got:", value:data())endВозвращает: Payload|nil, error|nil
Возвращает ошибку если future завершился неудачей.
local err, has_error = future:error()if has_error then print("Error kind:", err:kind())endВозвращает: error|nil, boolean
Отменяет асинхронную операцию.
future:cancel()Возвращает: boolean, error
Параллельные операции
Заголовок раздела «Параллельные операции»Запуск нескольких операций конкурентно с async и channel.select.
-- Запуск нескольких операций параллельноlocal f1, _ = funcs.async("app.api:get_user", user_id)local f2, _ = funcs.async("app.api:get_orders", user_id)local f3, _ = funcs.async("app.api:get_preferences", user_id)
-- Ждём завершения всех через каналыlocal user_ch = f1:channel()local orders_ch = f2:channel()local prefs_ch = f3:channel()
local results = {}for i = 1, 3 do local r = channel.select { user_ch:case_receive(), orders_ch:case_receive(), prefs_ch:case_receive() } if r.channel == user_ch then results.user = r.value:data() elseif r.channel == orders_ch then results.orders = r.value:data() else results.prefs = r.value:data() endendРазрешения
Заголовок раздела «Разрешения»Операции с функциями подчиняются вычислению политики безопасности.
| Action | Resource | Описание |
|---|---|---|
funcs.call | ID функции | Вызов конкретной функции |
funcs.context | context | Использовать with_context() для установки контекста |
funcs.security | security | Использовать with_actor() или with_scope() |
| Условие | Kind | Повторяемо |
|---|---|---|
| Target пустой | errors.INVALID | нет |
| Отсутствует namespace | errors.INVALID | нет |
| Отсутствует name | errors.INVALID | нет |
| Разрешение отклонено | errors.PERMISSION_DENIED | нет |
| Подписка не удалась | errors.INTERNAL | нет |
| Ошибка функции | varies | varies |
См. Обработка ошибок для работы с ошибками.