Вызовите правило Лиспекса из приложения на Топазе и обработайте результат при исчерпании лимита работы. Вы создадите шесть файлов и выполните одно правило с двумя разными лимитами.
Установите Топаз. Если вы ещё не работали с пакетами, пройдите Первое приложение. Вычислитель входит в Топаз, поэтому отдельно устанавливать Лиспекс не нужно. Эта интеграция использует Лиспекс 1.20.0.
Правило не может читать файлы, обращаться к системным часам или сети. Топаз подготавливает правило один раз. Каждое вычисление получает новую память, глобальные переменные, счётчики ресурсов и журнал выполнения.
Создайте правило и файлы лимитов
Создайте каталог lispex-first-call, а в нём каталоги rules и src. Сохраните в них следующие шесть файлов. Все команды ниже выполняйте из lispex-first-call.
Сохраните правило в rules/approve.lspx.
(if (< 10 15) "allow" "deny")Правило сравнивает константы 10 и 15 и возвращает "allow". Входное значение оно не использует. Фиксированное решение позволяет сравнить завершённое вычисление с исчерпанием ресурсов.
Сохраните полный файл лимитов как rules/approve.limits.json.
{
"schema": "topaz.lispex-embed-limits/v1",
"prepare": {
"raw_source_bytes": 4096,
"prepare_work": 1000000,
"logical_allocation": 1000000,
"syntax_depth": 64
},
"evaluate": {
"canonical_input_bytes": 4096,
"eval_work": 10000,
"logical_allocation": 1000000,
"semantic_frames": 1000,
"traversal_depth": 256,
"output_bytes": 4096,
"diagnostic_bytes": 4096,
"transcript_bytes": 4096,
"transcript_events": 100,
"result_bytes": 4096
}
}Сохраните второй файл лимитов как rules/semantic-limit-probe.limits.json.
{
"schema": "topaz.lispex-embed-limits/v1",
"prepare": {
"raw_source_bytes": 4096,
"prepare_work": 1000000,
"logical_allocation": 1000000,
"syntax_depth": 64
},
"evaluate": {
"canonical_input_bytes": 4096,
"eval_work": 1,
"logical_allocation": 1000000,
"semantic_frames": 1000,
"traversal_depth": 256,
"output_bytes": 4096,
"diagnostic_bytes": 4096,
"transcript_bytes": 4096,
"transcript_events": 100,
"result_bytes": 4096
}
}Во втором файле eval_work равен 1. Этого недостаточно для завершения правила. Сохраните все поля обоих файлов. Значения можно уменьшать, но добавление или удаление полей делает документ недопустимым.
prepare_work учитывает работу при подготовке правила, а eval_work при его вычислении. Одинаковые правило, вход и настройки вычислителя расходуют одинаковое число единиц работы. Прошедшее время ограничивается отдельно.
Задайте квоты приложения
Сохраните этот файл как rules/application.quotas.json.
{
"schema": "topaz.lispex-application-quotas/v1",
"concurrent_evaluations": 2,
"queued_evaluations": 2,
"total_evaluations": 64,
"aggregate_input_bytes": 262144,
"aggregate_result_bytes": 262144,
"aggregate_output_bytes": 262144,
"aggregate_transcript_bytes": 262144,
"aggregate_safety_fuel": 64000000000,
"prepared_bytes": 3000000,
"wall_millis": 5000
}Квоты действуют на всё приложение. Этот файл разрешает два одновременных вычисления, два ожидающих вызова и 64 вычисления в сумме. wall_millis отводит на вычисление 5 000 миллисекунд. Поля в байтах ограничивают суммарный объём входов, результатов, вывода и журналов выполнения.
Объявите пакет
Сохраните этот файл как topaz.toml.
[package]
name = "complete_lispex_decision_application"
version = "0.1.0"
language = "5.20"
entry = "src/main.tpz"
[build]
target = "native"
deterministic = true
[dependencies]
std = "5.20"
[lispex]
profile = "lispex/r7rs-rule-current-profile-bounded/1"
application = "topaz/lispex-decision-application/2"
application_quotas = "rules/application.quotas.json"
[[lispex.rule]]
name = "approve"
source = "rules/approve.lspx"
limits = "rules/approve.limits.json"
[[lispex.rule]]
name = "semantic_limit_probe"
source = "rules/approve.lspx"
limits = "rules/semantic-limit-probe.limits.json"Оба имени правила используют один исходный файл. approve получает обычные лимиты, а semantic_limit_probe получает лимит работы 1.
Для этого контракта приложения оставьте language и std равными 5.20. Сохраните идентификаторы profile и application точно как в примере. Профиль задаёт поддерживаемые возможности языка и правила выполнения. Слово bounded входит в идентификатор профиля и обозначает его лимиты ресурсов.
Каждая запись [[lispex.rule]] задаёт name и пути source и limits. Топаз предоставляет объявленные имена как функции в std.lispex.rules. Например, approve вызывается через rules.approve().
Вызовите правило
Сохраните эту программу целиком в src/main.tpz.
import std.lispex { canonicalBytes, defaultLimits, evaluate, valueFromCanonical }
import std.lispex.rules as rules
export function main(аргументы: Array<string>, стандартныйВвод: string) -> Result<int, string> {
let байты = Bytes.fromArray([0])?
let вход = match valueFromCanonical(байты) {
case Ok(значение) => значение
case Err(_) => return Err("invalid input")
}
let сценарий = if аргументы.length == 0 { "approve" } else { аргументы[0] }
let правило = if сценарий == "approve" {
rules.approve()
} else if сценарий == "semantic-limit" {
rules.semantic_limit_probe()
} else {
return Err("use approve or semantic-limit")
}
match evaluate(правило, вход, defaultLimits(правило)) {
case Ok(исход) => match исход {
case Complete(значение) => print("complete:{canonicalBytes(значение).toHex()}")
case LimitExhaustion(причина) => print("limit:{причина}")
case SemanticFailure(причина) => return Err("rule failed: {причина}")
case RequestRefusal(причина) => return Err("request refused: {причина}")
}
case Err(ошибка) => match ошибка {
case DeadlineExceeded => return Err("application deadline exceeded")
case TotalEvaluationsExceeded => return Err("application evaluation quota exceeded")
case _ => return Err("operational fault")
}
}
Ok(0)
}Bytes.fromArray([0]) создаёт однобайтовое представление пустого значения Лиспекса, nil. valueFromCanonical проверяет соответствие байтов общему формату значений lispex.embed-value/v1. Программа передаёт это значение как вход.
defaultLimits читает объявленные лимиты вычисления для правила. evaluate возвращает результат LispexSettlement или операционную ошибку. Результат описывает завершение, ошибку правила, отказ в запросе или исчерпание ресурсов. Программа обрабатывает исчерпание работы как результат, а превышение квоты или времени как ошибку.
Создайте файл блокировки, проверьте и запустите пакет
Выполните команды из каталога с topaz.toml.
topaz lock --root .
topaz check --root . --locked
topaz run --root . --lockedlock записывает topaz.lock и подготавливает правила в .topaz/lispex. check завершается с кодом 0 без вывода. run печатает следующую строку и завершается с кодом 0.
complete:090000000000000001080000000000000005616c6c6f77Программа печатает канонические байты результата в шестнадцатеричном виде. Они кодируют список со строкой "allow". Complete означает, что вычислитель завершил правило.
Теперь выберите правило с меньшим лимитом работы.
topaz run --root . --locked -- semantic-limitlimit:eval_workПрограмма завершается с кодом 0, поскольку обработала LimitExhaustion. Правило остановилось на лимите eval_work. Чтобы оно завершилось, измените это поле в rules/semantic-limit-probe.limits.json с 1 на 10000. Повторите команды блокировки, проверки и запуска. Вы получите строку complete, показанную выше.
Для следующих примеров верните eval_work значение 1 в этом файле и снова выполните topaz lock --root .. Файл блокировки обновится, а semantic-limit снова выведет limit:eval_work.
Проверьте topaz.lock перед коммитом. Он фиксирует вычислитель, профиль, кодирование, лимиты, квоты, исходники правил, подготовленные правила и их дайджесты. Дайджест определяет точные байты. Эти значения должна записывать команда topaz lock.
После изменения манифеста, правил, лимитов, квот, вычислителя или профиля обновите файл блокировки. Команды с --locked отклоняют несовпадения. Подробнее о блокировке читайте в разделе Пакеты и распространение, об установке в разделе Состояние инструментария.
Сохраните и проверьте запись вычисления
Для сохранения записи вычисления используйте evaluateWithEvidence. Для подходящих детерминированных исходов функция возвращает артефакт потребителя, запись, созданную вызывающим приложением.
| Функция | Назначение |
|---|---|
consumerArtifactBytes | Преобразовать запись в байты для хранения |
consumerArtifactFromBytes | Прочитать сохранённые байты и проверить формат |
inspectConsumerArtifact | Прочитать метаданные и идентификаторы без запуска правила |
verifyConsumerArtifact | Проверить структуру, дайджесты и связь с параметрами вычисления |
portableCoreBytes | Извлечь вложенную запись в формате Лиспекса, если она есть |
freshReplay | Выполнить записанные правило и вход с записанными лимитами в новом экземпляре и сравнить полученный артефакт |
Запись и её ядро в формате Лиспекса создаются вызывающей стороной без подписи и аутентификации. Они не указывают издателя и не дают одобрения поставщика, полномочий подписи, допуска компонента или разрешения на внешние действия. Проверяйте содержимое записи и разрешения на внешние действия отдельно.
Локальный отказ в запросе, отмена, переполненная очередь, защитная остановка и сбой движка не создают переносимого ядра. freshReplay завершается успешно, когда новый артефакт совпадает с сохранённым.
Поддерживаемый пример docs/samples/guides/lispex-application/first-call содержит шесть файлов выше. Пример в родительском каталоге также проверяет повторные вычисления, хранение и проверку записей, повторное выполнение, изоляцию состояния и общую квоту. Его сценарий all завершается после отказа в 65-м вызове. Программа первого вызова на этой странице принимает approve и semantic-limit.
Соберите нативный продукт
Установив инструменты сборки Rust, создайте релизную сборку вне каталога пакета.
topaz build --root . --locked --release --out-dir ../complete-productВ Linux или macOS запустите полученную программу.
../complete-product/target/release/program
../complete-product/target/release/program semantic-limitВ Windows используйте следующие команды.
..\complete-product\target\release\program.exe
..\complete-product\target\release\program.exe semantic-limitПервая команда печатает строку complete, вторая печатает limit:eval_work. Обе завершаются с кодом 0. Используйте исполняемый файл в той ОС и на той архитектуре, для которых он собран.
Выберите среду выполнения
| Маршрут | Поведение |
|---|---|
interpreter | Запускает приложение с файлом блокировки через topaz run |
native | Выполняется на поддерживаемых нативных релизных платформах |
raw-web и worker-web | Отклоняются до записи выходных файлов |
no-capability | Отклоняется до выполнения или записи выходных файлов |
mcp-empty-component-set | Отклоняется до выполнения |
Нативные релизные платформы включают Windows x64, Linux x64 и arm64, macOS x64 и arm64. Неподдерживаемый маршрут завершается ошибкой без перехода к другой среде выполнения.
Существующие пакеты Топаза 5.18 используют профиль совместимости embedded-core со своими идентификаторами вычислителя, профиля, контракта и подготовленных правил. Приложение выше использует lispex/r7rs-rule-current-profile-bounded/1. Выбор одного профиля не подменяет его другим.
Связанные разделы
- Вычислитель Лиспекса и LIT для одного запроса из CLI без пакета
- Границы интеграции для выбора способа подключения приложения