mirror of
https://github.com/gorules/zen.git
synced 2026-10-03 16:02:27 +00:00
chore: add benchmarks (#459)
* chore: add benchmarks for tier 1 languages * improve fixtures * fix cargo fmt
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
name: Benchmark
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [ published ]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
BENCH_ITERS: '500'
|
||||
|
||||
jobs:
|
||||
rust:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Rust
|
||||
run: rustup update stable
|
||||
- uses: ./.github/actions/setup-rust
|
||||
with:
|
||||
shared-key: benchmark-rust
|
||||
sccache: 'false'
|
||||
- name: Build
|
||||
run: cargo build --release -p zen-benchmark
|
||||
- name: Run
|
||||
run: ./target/release/zen-benchmark benchmark/manifest.json "$GITHUB_WORKSPACE/bench-rust.json"
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: bench-rust
|
||||
path: bench-rust.json
|
||||
if-no-files-found: error
|
||||
|
||||
node:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: bindings/nodejs
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 22
|
||||
cache: yarn
|
||||
cache-dependency-path: 'bindings/nodejs/yarn.lock'
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: stable
|
||||
targets: x86_64-unknown-linux-gnu
|
||||
- uses: ./.github/actions/setup-rust
|
||||
with:
|
||||
shared-key: benchmark-node
|
||||
sccache: 'false'
|
||||
- run: yarn install --immutable --mode=skip-build
|
||||
- run: yarn build
|
||||
- name: Run
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: node benchmark/node/bench.mjs "$GITHUB_WORKSPACE/bench-node.json"
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: bench-node
|
||||
path: bench-node.json
|
||||
if-no-files-found: error
|
||||
|
||||
python:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.13'
|
||||
- name: Install Rust
|
||||
run: rustup update stable
|
||||
- uses: ./.github/actions/setup-rust
|
||||
with:
|
||||
shared-key: benchmark-python
|
||||
sccache: 'false'
|
||||
- run: pip install maturin
|
||||
- name: Build + install wheel
|
||||
run: |
|
||||
maturin build --release --out dist -m bindings/python/Cargo.toml
|
||||
pip install dist/*.whl
|
||||
- name: Run
|
||||
run: python benchmark/python/bench.py "$GITHUB_WORKSPACE/bench-python.json"
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: bench-python
|
||||
path: bench-python.json
|
||||
if-no-files-found: error
|
||||
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [ rust, node, python ]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: results
|
||||
merge-multiple: true
|
||||
- name: Merge results
|
||||
run: |
|
||||
node -e '
|
||||
const fs = require("fs");
|
||||
const out = [];
|
||||
for (const lang of ["rust", "node", "python"]) {
|
||||
const r = JSON.parse(fs.readFileSync(`results/bench-${lang}.json`, "utf8"));
|
||||
for (const e of r) out.push({ ...e, name: `${lang} · ${e.name}` });
|
||||
}
|
||||
fs.writeFileSync("bench-all.json", JSON.stringify(out, null, 2));
|
||||
'
|
||||
- name: Store + publish
|
||||
uses: benchmark-action/github-action-benchmark@v1
|
||||
with:
|
||||
name: ZEN cross-language
|
||||
tool: customSmallerIsBetter
|
||||
output-file-path: bench-all.json
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
auto-push: true
|
||||
alert-threshold: '150%'
|
||||
comment-on-alert: true
|
||||
fail-on-alert: false
|
||||
Generated
+11
@@ -4933,6 +4933,17 @@ dependencies = [
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zen-benchmark"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"zen-engine",
|
||||
"zen-expression",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zen-engine"
|
||||
version = "0.55.1"
|
||||
|
||||
+2
-1
@@ -2,7 +2,8 @@
|
||||
resolver = "2"
|
||||
members = [
|
||||
"core/*",
|
||||
"bindings/*"
|
||||
"bindings/*",
|
||||
"benchmark/rust"
|
||||
]
|
||||
|
||||
[workspace.dependencies]
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
.venv/
|
||||
.dist/
|
||||
@@ -0,0 +1,41 @@
|
||||
BENCH_ITERS ?= 500
|
||||
export BENCH_ITERS
|
||||
|
||||
ROOT := $(CURDIR)/..
|
||||
VENV := $(CURDIR)/.venv
|
||||
PY := $(VENV)/bin/python
|
||||
BIN := $(ROOT)/target/release/zen-benchmark
|
||||
|
||||
.PHONY: all compare fixtures rust node python build-rust build-node build-python
|
||||
|
||||
all: rust node python
|
||||
|
||||
fixtures:
|
||||
@node gen.mjs
|
||||
|
||||
compare:
|
||||
@node compare.mjs
|
||||
|
||||
rust: build-rust
|
||||
@printf '\n=== rust ===\n'
|
||||
@$(BIN) manifest.json
|
||||
|
||||
node: build-node
|
||||
@printf '\n=== node ===\n'
|
||||
@node node/bench.mjs
|
||||
|
||||
python: build-python
|
||||
@printf '\n=== python ===\n'
|
||||
@$(PY) python/bench.py
|
||||
|
||||
build-rust:
|
||||
@cargo build --release -q -p zen-benchmark
|
||||
|
||||
build-node:
|
||||
@cd $(ROOT)/bindings/nodejs && yarn install --immutable --mode=skip-build && yarn build
|
||||
|
||||
build-python:
|
||||
@test -d $(VENV) || python3 -m venv $(VENV)
|
||||
@$(PY) -m pip install --quiet --upgrade pip maturin
|
||||
@rm -rf $(CURDIR)/.dist && $(PY) -m maturin build --release --out $(CURDIR)/.dist -m $(ROOT)/bindings/python/Cargo.toml
|
||||
@$(PY) -m pip install --quiet --force-reinstall $(CURDIR)/.dist/*.whl
|
||||
@@ -0,0 +1,54 @@
|
||||
import { execSync, execFileSync } from 'node:child_process';
|
||||
import { readFileSync, mkdtempSync, rmSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const dir = path.dirname(fileURLToPath(import.meta.url));
|
||||
const root = path.join(dir, '..');
|
||||
const manifest = JSON.parse(readFileSync(path.join(dir, 'manifest.json'), 'utf8'));
|
||||
const rowNames = manifest.flatMap((e) => [`${e.name} (${e.kind})`, `${e.name} (${e.kind}) +trace`]);
|
||||
|
||||
const langs = [
|
||||
{ key: 'rust', build: 'build-rust', cmd: path.join(root, 'target', 'release', 'zen-benchmark'), args: ['manifest.json'] },
|
||||
{ key: 'node', build: 'build-node', cmd: process.execPath, args: [path.join(dir, 'node', 'bench.mjs')] },
|
||||
{ key: 'python', build: 'build-python', cmd: path.join(dir, '.venv', 'bin', 'python'), args: [path.join(dir, 'python', 'bench.py')] },
|
||||
];
|
||||
|
||||
const tmp = mkdtempSync(path.join(tmpdir(), 'zen-bench-'));
|
||||
const values = {};
|
||||
for (const lang of langs) {
|
||||
try {
|
||||
execSync(`make ${lang.build}`, { cwd: dir, stdio: 'inherit', env: process.env });
|
||||
const out = path.join(tmp, `${lang.key}.json`);
|
||||
execFileSync(lang.cmd, [...lang.args, out], { cwd: dir, stdio: ['ignore', 'ignore', 'inherit'], env: process.env });
|
||||
const arr = JSON.parse(readFileSync(out, 'utf8'));
|
||||
values[lang.key] = Object.fromEntries(arr.map((e) => [e.name, e.value]));
|
||||
} catch (err) {
|
||||
console.error(`! skipping ${lang.key}: ${err.message}`);
|
||||
values[lang.key] = null;
|
||||
}
|
||||
}
|
||||
rmSync(tmp, { recursive: true, force: true });
|
||||
|
||||
const NAME_W = 52;
|
||||
const COL_W = 22;
|
||||
const get = (key, name) => (values[key] ? values[key][name] : undefined);
|
||||
const cell = (v, base) => {
|
||||
if (v == null) return 'n/a'.padStart(COL_W);
|
||||
const ns = `${Math.round(v)} ns`;
|
||||
if (base == null) return ns.padStart(COL_W);
|
||||
const mult = base === 0 ? '' : `${(v / base).toFixed(2)}x`;
|
||||
return `${ns} ${mult}`.padStart(COL_W);
|
||||
};
|
||||
|
||||
const header = `${'fixture'.padEnd(NAME_W)}${['rust', 'node', 'python'].map((l) => l.padStart(COL_W)).join('')}`;
|
||||
console.log('');
|
||||
console.log(header);
|
||||
console.log('-'.repeat(header.length));
|
||||
for (const name of rowNames) {
|
||||
const r = get('rust', name);
|
||||
console.log(`${name.padEnd(NAME_W)}${cell(r, null)}${cell(get('node', name), r)}${cell(get('python', name), r)}`);
|
||||
}
|
||||
console.log('');
|
||||
console.log('x = slowdown vs rust (rust is the baseline floor; lower is better)');
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"contentType":"application/vnd.gorules.decision","nodes":[{"type":"inputNode","id":"in","name":"request","content":{"schema":""},"position":{"x":2020,"y":120}},{"type":"expressionNode","id":"dailyStats","name":"dailyStats","content":{"expressions":[{"id":"dailyStats_e0","key":"cost","value":"dataGB * 0.5 + minutes * 0.01 + texts * 0.001"},{"id":"dailyStats_e1","key":"heavy","value":"dataGB > 2"}],"passThrough":true,"inputField":"usageHistory","outputPath":"daily","executionMode":"loop"},"position":{"x":2180,"y":120}},{"type":"decisionTableNode","id":"dailyTier","name":"dailyTier","content":{"hitPolicy":"first","inputs":[{"id":"i","name":"Cost","field":"cost"}],"outputs":[{"id":"o","name":"Tier","field":"usageTier"}],"rules":[{"_id":"r1","i":"> 5","o":"'high'"},{"_id":"r2","i":"> 2","o":"'medium'"},{"_id":"r3","i":"","o":"'low'"}],"passThrough":true,"inputField":"daily","outputPath":"dailyTiered","executionMode":"loop"},"position":{"x":2340,"y":120}},{"type":"expressionNode","id":"aggregate","name":"aggregate","content":{"expressions":[{"id":"aggregate_e0","key":"totalCost","value":"sum(map(daily, #.cost))"},{"id":"aggregate_e1","key":"heavyDays","value":"len(filter(daily, #.heavy))"},{"id":"aggregate_e2","key":"avgData","value":"sum(map(usageHistory, #.dataGB)) / len(usageHistory)"}],"passThrough":true,"inputField":null,"outputPath":null,"executionMode":"single"},"position":{"x":2500,"y":120}},{"type":"decisionTableNode","id":"accountStatus","name":"accountStatus","content":{"hitPolicy":"first","inputs":[{"id":"i1","name":"Age","field":"accountInfo.accountAge"},{"id":"i2","name":"Payment","field":"accountInfo.paymentHistory"}],"outputs":[{"id":"o1","name":"Status","field":"eligibility.accountStatus"},{"id":"o2","name":"Good","field":"eligibility.goodStanding"}],"rules":[{"_id":"r1","i1":">= 24","i2":"'excellent'","o1":"'excellent'","o2":"true"},{"_id":"r2","i1":">= 12","i2":"'excellent', 'good'","o1":"'good'","o2":"true"},{"_id":"r3","i1":">= 6","i2":"","o1":"'fair'","o2":"true"},{"_id":"r4","i1":"","i2":"","o1":"'review'","o2":"false"}],"passThrough":true,"inputField":null,"outputPath":null,"executionMode":"single"},"position":{"x":2660,"y":120}},{"type":"decisionTableNode","id":"loyaltyTier","name":"loyaltyTier","content":{"hitPolicy":"first","inputs":[{"id":"i1","name":"Age","field":"accountInfo.accountAge"},{"id":"i2","name":"Spend","field":"accountInfo.monthlySpend"}],"outputs":[{"id":"o1","name":"Tier","field":"eligibility.loyaltyTier"},{"id":"o2","name":"Discount","field":"eligibility.loyaltyDiscountPercent"}],"rules":[{"_id":"r1","i1":">= 36","i2":">= 120","o1":"'platinum'","o2":"20"},{"_id":"r2","i1":">= 24","i2":">= 80","o1":"'gold'","o2":"15"},{"_id":"r3","i1":">= 12","i2":">= 50","o1":"'silver'","o2":"10"},{"_id":"r4","i1":"","i2":"","o1":"'standard'","o2":"0"}],"passThrough":true,"inputField":null,"outputPath":null,"executionMode":"single"},"position":{"x":2820,"y":120}},{"type":"expressionNode","id":"specialOffers","name":"specialOffers","content":{"expressions":[{"id":"specialOffers_e0","key":"eligibility.specialOffers","value":"{ 'dataBooster': usageStats.dataUtilizationPercent > 80, 'familyPlan': len(customerProfile.devices) >= 3, 'loyaltyReward': eligibility.loyaltyTier in ['platinum', 'gold', 'silver'] }"},{"id":"specialOffers_e1","key":"eligibility.offerCount","value":"len(filter(values($.eligibility.specialOffers), # == true))"}],"passThrough":true,"inputField":null,"outputPath":null,"executionMode":"single"},"position":{"x":2980,"y":120}},{"type":"expressionNode","id":"replicate","name":"replicate","content":{"expressions":[{"id":"replicate_e0","key":"historyCopy","value":"usageHistory"},{"id":"replicate_e1","key":"dailyCopy","value":"daily"},{"id":"replicate_e2","key":"tieredCopy","value":"dailyTiered"}],"passThrough":true,"inputField":null,"outputPath":null,"executionMode":"single"},"position":{"x":3140,"y":120}}],"edges":[{"id":"edge0","type":"edge","sourceId":"in","targetId":"dailyStats"},{"id":"edge1","type":"edge","sourceId":"dailyStats","targetId":"dailyTier"},{"id":"edge2","type":"edge","sourceId":"dailyTier","targetId":"aggregate"},{"id":"edge3","type":"edge","sourceId":"aggregate","targetId":"accountStatus"},{"id":"edge4","type":"edge","sourceId":"accountStatus","targetId":"loyaltyTier"},{"id":"edge5","type":"edge","sourceId":"loyaltyTier","targetId":"specialOffers"},{"id":"edge6","type":"edge","sourceId":"specialOffers","targetId":"replicate"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"contentType":"application/vnd.gorules.decision","nodes":[{"id":"5eefa8a4-56a9-46b1-a265-7ddbddde3441","type":"inputNode","position":{"x":240,"y":280},"name":"Request"},{"id":"638d767d-ae08-4ba3-9db3-97c6c4e4c6f5","type":"decisionTableNode","position":{"x":520,"y":280},"name":"Discounts","content":{"hitPolicy":"collect","inputs":[{"id":"6fd35e3e-584b-4149-b4bf-5f2d258f40e7","type":"expression","field":"code","name":"Code"},{"id":"a1700de6-fe35-4cec-b66f-0897d2604a3f","name":"Order Date","type":"expression","field":"date(order.createdAt)"},{"id":"813dace4-0b55-4409-adb2-b4739a653302","type":"expression","field":"date(customer.joinDate)","name":"Customer Join Date"},{"id":"f34f2c8b-eba9-4ebe-aeec-384bce69e3aa","type":"expression","field":"len(customer.pastPurchases)","name":"Customer Past Purchases"}],"outputs":[{"field":"discount.percentage","id":"16d637be-1093-4468-b29f-236666bf2f26","name":"Discount Percentage","type":"expression"},{"id":"bccbb1bc-f0da-4b1e-b186-122ba4a193ac","type":"expression","field":"discount.flat","name":"Discount Flat"}],"rules":[{"_id":"eabd4e2e-5c14-4d4d-ada6-b3cdc547ae99","_description":"Welcome bonus of 15%","6fd35e3e-584b-4149-b4bf-5f2d258f40e7":"\"WELCOME_2023\"","a1700de6-fe35-4cec-b66f-0897d2604a3f":"","813dace4-0b55-4409-adb2-b4739a653302":"> date(\"2023-01-01\")","f34f2c8b-eba9-4ebe-aeec-384bce69e3aa":"0","16d637be-1093-4468-b29f-236666bf2f26":"15","bccbb1bc-f0da-4b1e-b186-122ba4a193ac":""},{"_id":"d80dee00-07a7-42fb-bc83-262eeee9fbdb","_description":"Recurring customer 25$ discount","6fd35e3e-584b-4149-b4bf-5f2d258f40e7":"\"BACK_TO_BACK\"","a1700de6-fe35-4cec-b66f-0897d2604a3f":"[date(\"2023-01-01\")..date(\"2023-02-01\")]","813dace4-0b55-4409-adb2-b4739a653302":"","f34f2c8b-eba9-4ebe-aeec-384bce69e3aa":"> 10","16d637be-1093-4468-b29f-236666bf2f26":"","bccbb1bc-f0da-4b1e-b186-122ba4a193ac":"25"},{"_id":"fcfae4b3-5c86-4efe-91cd-ca4bc1fa7c7c","_description":"Old customer 10%","6fd35e3e-584b-4149-b4bf-5f2d258f40e7":"\"EARLY_BIRD\"","a1700de6-fe35-4cec-b66f-0897d2604a3f":"","813dace4-0b55-4409-adb2-b4739a653302":"< date(\"2020-01-01\")","f34f2c8b-eba9-4ebe-aeec-384bce69e3aa":"","16d637be-1093-4468-b29f-236666bf2f26":"10","bccbb1bc-f0da-4b1e-b186-122ba4a193ac":""}]}},{"id":"c87d26e6-f3a2-47ad-9310-cbd1899cc68a","type":"outputNode","position":{"x":830,"y":280},"name":"Response"}],"edges":[{"id":"3b07d6c5-6949-4e5d-a8c6-f5cf44dbba0a","sourceId":"5eefa8a4-56a9-46b1-a265-7ddbddde3441","type":"edge","targetId":"638d767d-ae08-4ba3-9db3-97c6c4e4c6f5"},{"id":"69e558e4-4c20-4a53-9230-c068ebb19830","sourceId":"638d767d-ae08-4ba3-9db3-97c6c4e4c6f5","type":"edge","targetId":"c87d26e6-f3a2-47ad-9310-cbd1899cc68a"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"contentType":"application/vnd.gorules.decision","nodes":[{"type":"inputNode","id":"in","name":"request","content":{"schema":""},"position":{"x":1060,"y":120}},{"type":"expressionNode","id":"dims","name":"dims","content":{"expressions":[{"id":"dims_e0","key":"dimWeight","value":"(length * width * height) / 5000"},{"id":"dims_e1","key":"effWeight","value":"max([weight, (length * width * height) / 5000])"},{"id":"dims_e2","key":"distFactor","value":"distance / 100"}],"passThrough":true,"inputField":"shipments","outputPath":"computed","executionMode":"loop"},"position":{"x":1220,"y":120}},{"type":"decisionTableNode","id":"baseRate","name":"baseRate","content":{"hitPolicy":"first","inputs":[{"id":"i1","name":"Type","field":"shippingType"},{"id":"i2","name":"Weight","field":"effWeight"}],"outputs":[{"id":"o1","name":"Base","field":"baseRate"}],"rules":[{"_id":"r1","i1":"'standard'","i2":"< 20","o1":"10"},{"_id":"r2","i1":"'standard'","i2":"","o1":"20"},{"_id":"r3","i1":"'express'","i2":"< 20","o1":"20"},{"_id":"r4","i1":"'express'","i2":"","o1":"35"},{"_id":"r5","i1":"'priority'","i2":"","o1":"50"},{"_id":"r6","i1":"","i2":"","o1":"15"}],"passThrough":true,"inputField":"computed","outputPath":"rated","executionMode":"loop"},"position":{"x":1380,"y":120}},{"type":"decisionTableNode","id":"finalPrice","name":"finalPrice","content":{"hitPolicy":"first","inputs":[{"id":"i1","name":"Tier","field":"customerTier"}],"outputs":[{"id":"o1","name":"Final","field":"finalPrice"}],"rules":[{"_id":"r1","i1":"'gold'","o1":"baseRate * (effWeight / weight) * (1 + distFactor * 0.1) * 0.9"},{"_id":"r2","i1":"'silver'","o1":"baseRate * (effWeight / weight) * (1 + distFactor * 0.1) * 0.95"},{"_id":"r3","i1":"","o1":"baseRate * (effWeight / weight) * (1 + distFactor * 0.1)"}],"passThrough":true,"inputField":"rated","outputPath":"priced","executionMode":"loop"},"position":{"x":1540,"y":120}},{"type":"expressionNode","id":"replicate","name":"replicate","content":{"expressions":[{"id":"replicate_e0","key":"shipmentsCopy","value":"shipments"},{"id":"replicate_e1","key":"computedCopy","value":"computed"},{"id":"replicate_e2","key":"pricedCopy","value":"priced"}],"passThrough":true,"inputField":null,"outputPath":null,"executionMode":"single"},"position":{"x":1700,"y":120}},{"type":"expressionNode","id":"totals","name":"totals","content":{"expressions":[{"id":"totals_e0","key":"totalPrice","value":"sum(map(priced, #.finalPrice))"},{"id":"totals_e1","key":"count","value":"len(shipments)"}],"passThrough":true,"inputField":null,"outputPath":null,"executionMode":"single"},"position":{"x":1860,"y":120}}],"edges":[{"id":"edge0","type":"edge","sourceId":"in","targetId":"dims"},{"id":"edge1","type":"edge","sourceId":"dims","targetId":"baseRate"},{"id":"edge2","type":"edge","sourceId":"baseRate","targetId":"finalPrice"},{"id":"edge3","type":"edge","sourceId":"finalPrice","targetId":"replicate"},{"id":"edge4","type":"edge","sourceId":"replicate","targetId":"totals"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"contentType":"application/vnd.gorules.decision","nodes":[{"type":"inputNode","id":"in","name":"request","content":{"schema":""},"position":{"x":260,"y":120}},{"type":"expressionNode","id":"enrich","name":"enrich","content":{"expressions":[{"id":"enrich_e0","key":"subtotal","value":"amount * qty"},{"id":"enrich_e1","key":"premium","value":"amount > 40 and group == 'accessories'"}],"passThrough":true,"inputField":"items","outputPath":"enriched","executionMode":"loop"},"position":{"x":420,"y":120}},{"type":"decisionTableNode","id":"classify","name":"classify","content":{"hitPolicy":"first","inputs":[{"id":"ci","name":"Subtotal","field":"subtotal"}],"outputs":[{"id":"co","name":"Discount","field":"discount"}],"rules":[{"_id":"r1","ci":"> 1000","co":"15"},{"_id":"r2","ci":"> 500","co":"10"},{"_id":"r3","ci":"> 100","co":"5"},{"_id":"r4","ci":"","co":"0"}],"passThrough":true,"inputField":"enriched","outputPath":"classified","executionMode":"loop"},"position":{"x":580,"y":120}},{"type":"expressionNode","id":"replicate","name":"replicate","content":{"expressions":[{"id":"replicate_e0","key":"allItems","value":"items"},{"id":"replicate_e1","key":"enrichedCopy","value":"enriched"},{"id":"replicate_e2","key":"classifiedCopy","value":"classified"}],"passThrough":true,"inputField":null,"outputPath":null,"executionMode":"single"},"position":{"x":740,"y":120}},{"type":"expressionNode","id":"totals","name":"totals","content":{"expressions":[{"id":"totals_e0","key":"grandTotal","value":"sum(map(enriched, #.subtotal))"},{"id":"totals_e1","key":"itemCount","value":"len(items)"},{"id":"totals_e2","key":"premiumCount","value":"len(filter(enriched, #.premium))"}],"passThrough":true,"inputField":null,"outputPath":null,"executionMode":"single"},"position":{"x":900,"y":120}}],"edges":[{"id":"edge0","type":"edge","sourceId":"in","targetId":"enrich"},{"id":"edge1","type":"edge","sourceId":"enrich","targetId":"classify"},{"id":"edge2","type":"edge","sourceId":"classify","targetId":"replicate"},{"id":"edge3","type":"edge","sourceId":"replicate","targetId":"totals"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"blocks":[{"id":"dm","type":"dataModel","props":{"data":{"name":"customer","properties":[{"id":"p0","name":"amounts","type":"number","array":true,"optional":false},{"id":"p1","name":"label","type":"string","array":false,"optional":false}]}},"children":[]},{"id":"e1","type":"expression","props":{"data":{"key":"customer.positive","value":"filter(customer.amounts, # > 0)"}}},{"id":"e2","type":"expression","props":{"data":{"key":"customer.negatives","value":"filter(customer.amounts, # < 0)"}}},{"id":"e3","type":"expression","props":{"data":{"key":"customer.doubled","value":"map(customer.amounts, # * 2)"}}},{"id":"e4","type":"expression","props":{"data":{"key":"customer.squared","value":"map(customer.amounts, # * #)"}}},{"id":"e5","type":"expression","props":{"data":{"key":"customer.total","value":"sum(customer.positive)"}}},{"id":"e6","type":"expression","props":{"data":{"key":"customer.negTotal","value":"sum(customer.negatives)"}}},{"id":"e7","type":"expression","props":{"data":{"key":"customer.net","value":"customer.total + customer.negTotal"}}},{"id":"e8","type":"expression","props":{"data":{"key":"customer.posCount","value":"len(customer.positive)"}}},{"id":"e9","type":"expression","props":{"data":{"key":"customer.avg","value":"customer.net / len(customer.amounts)"}}},{"id":"e10","type":"expression","props":{"data":{"key":"customer.maxVal","value":"max(customer.amounts)"}}},{"id":"e11","type":"expression","props":{"data":{"key":"customer.minVal","value":"min(customer.amounts)"}}},{"id":"a1","type":"assertion","props":{"data":{"output":"customer.bigSpender","conditions":[{"id":"a1c","expression":"customer.total > 1000","operator":"and","depth":0}]}},"children":[]},{"id":"a2","type":"assertion","props":{"data":{"output":"customer.balanced","conditions":[{"id":"a2c","expression":"customer.net > 0","operator":"and","depth":0}]}},"children":[]},{"id":"a3","type":"assertion","props":{"data":{"output":"customer.volatile","conditions":[{"id":"a3c","expression":"customer.maxVal - customer.minVal > 50","operator":"and","depth":0}]}},"children":[]}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"blocks":[{"id":"dm","type":"dataModel","props":{"data":{"name":"customer","properties":[{"id":"p0","name":"age","type":"number","array":false,"optional":false},{"id":"p1","name":"income","type":"number","array":false,"optional":false}]}},"children":[]},{"id":"e1","type":"expression","props":{"data":{"key":"customer.score","value":"customer.age + customer.income / 1000"}}},{"id":"a1","type":"assertion","props":{"data":{"output":"customer.eligible","conditions":[{"id":"a1c","expression":"customer.score > 50","operator":"and","depth":0}]}},"children":[]}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"blocks":[{"id":"dm","type":"dataModel","props":{"data":{"name":"customer","properties":[{"id":"p0","name":"score","type":"number","array":false,"optional":false}]}},"children":[]},{"id":"m1","type":"match","props":{"data":{"key":"customer.tier","arms":[{"id":"a1","condition":"customer.score >= 80","value":"\"gold\""},{"id":"a2","condition":"customer.score >= 50","value":"\"silver\""},{"id":"a3","condition":"","value":"\"bronze\""}]}}}]}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"blocks":[{"id":"dm","type":"dataModel","props":{"data":{"name":"customer","properties":[{"id":"p0","name":"age","type":"number","array":false,"optional":false}]}},"children":[]},{"id":"a1","type":"assertion","props":{"data":{"output":"customer.isAdult","conditions":[{"id":"a1c","expression":"customer.age >= 18","operator":"and","depth":0}]}},"children":[]}]}
|
||||
@@ -0,0 +1,328 @@
|
||||
import { writeFileSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const dir = path.dirname(fileURLToPath(import.meta.url));
|
||||
const fixtures = path.join(dir, 'fixtures');
|
||||
|
||||
const ITEMS = 250;
|
||||
const DAYS = 200;
|
||||
const SHIPMENTS = 150;
|
||||
const AMOUNTS = 600;
|
||||
const SCORES = 300;
|
||||
const ASSERTIONS = 30;
|
||||
|
||||
const range = (n) => Array.from({ length: n }, (_, i) => i);
|
||||
|
||||
let x = 100;
|
||||
const pos = () => ({ x: (x += 160), y: 120 });
|
||||
|
||||
const inputNode = (id) => ({ type: 'inputNode', id, name: 'request', content: { schema: '' }, position: pos() });
|
||||
|
||||
const exprNode = (id, name, exprs, transform = {}) => ({
|
||||
type: 'expressionNode',
|
||||
id,
|
||||
name,
|
||||
content: {
|
||||
expressions: exprs.map(([key, value], i) => ({ id: `${id}_e${i}`, key, value })),
|
||||
passThrough: true,
|
||||
inputField: null,
|
||||
outputPath: null,
|
||||
executionMode: 'single',
|
||||
...transform,
|
||||
},
|
||||
position: pos(),
|
||||
});
|
||||
|
||||
const tableNode = (id, name, inputs, outputs, rules, transform = {}) => ({
|
||||
type: 'decisionTableNode',
|
||||
id,
|
||||
name,
|
||||
content: {
|
||||
hitPolicy: 'first',
|
||||
inputs,
|
||||
outputs,
|
||||
rules,
|
||||
passThrough: true,
|
||||
inputField: null,
|
||||
outputPath: null,
|
||||
executionMode: 'single',
|
||||
...transform,
|
||||
},
|
||||
position: pos(),
|
||||
});
|
||||
|
||||
const graph = (nodes) => ({
|
||||
contentType: 'application/vnd.gorules.decision',
|
||||
nodes,
|
||||
edges: nodes.slice(1).map((n, i) => ({ id: `edge${i}`, type: 'edge', sourceId: nodes[i].id, targetId: n.id })),
|
||||
});
|
||||
|
||||
const dataModel = (name, props) => ({
|
||||
id: 'dm',
|
||||
type: 'dataModel',
|
||||
props: { data: { name, properties: props.map((p, i) => ({ id: `p${i}`, name: p.name, type: p.type, array: !!p.array, optional: !!p.optional })) } },
|
||||
children: [],
|
||||
});
|
||||
|
||||
const expr = (id, key, value) => ({ id, type: 'expression', props: { data: { key, value } } });
|
||||
|
||||
const assertion = (id, output, expression) => ({
|
||||
id,
|
||||
type: 'assertion',
|
||||
props: { data: { output, conditions: [{ id: `${id}c`, expression, operator: 'and', depth: 0 }] } },
|
||||
children: [],
|
||||
});
|
||||
|
||||
const expressionTableMap = graph([
|
||||
inputNode('in'),
|
||||
exprNode('enrich', 'enrich', [
|
||||
['subtotal', 'amount * qty'],
|
||||
['premium', "amount > 40 and group == 'accessories'"],
|
||||
], { inputField: 'items', outputPath: 'enriched', executionMode: 'loop' }),
|
||||
tableNode('classify', 'classify',
|
||||
[{ id: 'ci', name: 'Subtotal', field: 'subtotal' }],
|
||||
[{ id: 'co', name: 'Discount', field: 'discount' }],
|
||||
[
|
||||
{ _id: 'r1', ci: '> 1000', co: '15' },
|
||||
{ _id: 'r2', ci: '> 500', co: '10' },
|
||||
{ _id: 'r3', ci: '> 100', co: '5' },
|
||||
{ _id: 'r4', ci: '', co: '0' },
|
||||
],
|
||||
{ inputField: 'enriched', outputPath: 'classified', executionMode: 'loop' }),
|
||||
exprNode('replicate', 'replicate', [
|
||||
['allItems', 'items'],
|
||||
['enrichedCopy', 'enriched'],
|
||||
['classifiedCopy', 'classified'],
|
||||
]),
|
||||
exprNode('totals', 'totals', [
|
||||
['grandTotal', 'sum(map(enriched, #.subtotal))'],
|
||||
['itemCount', 'len(items)'],
|
||||
['premiumCount', 'len(filter(enriched, #.premium))'],
|
||||
]),
|
||||
]);
|
||||
|
||||
const dynamicShipping = graph([
|
||||
inputNode('in'),
|
||||
exprNode('dims', 'dims', [
|
||||
['dimWeight', '(length * width * height) / 5000'],
|
||||
['effWeight', 'max([weight, (length * width * height) / 5000])'],
|
||||
['distFactor', 'distance / 100'],
|
||||
], { inputField: 'shipments', outputPath: 'computed', executionMode: 'loop' }),
|
||||
tableNode('baseRate', 'baseRate',
|
||||
[
|
||||
{ id: 'i1', name: 'Type', field: 'shippingType' },
|
||||
{ id: 'i2', name: 'Weight', field: 'effWeight' },
|
||||
],
|
||||
[{ id: 'o1', name: 'Base', field: 'baseRate' }],
|
||||
[
|
||||
{ _id: 'r1', i1: "'standard'", i2: '< 20', o1: '10' },
|
||||
{ _id: 'r2', i1: "'standard'", i2: '', o1: '20' },
|
||||
{ _id: 'r3', i1: "'express'", i2: '< 20', o1: '20' },
|
||||
{ _id: 'r4', i1: "'express'", i2: '', o1: '35' },
|
||||
{ _id: 'r5', i1: "'priority'", i2: '', o1: '50' },
|
||||
{ _id: 'r6', i1: '', i2: '', o1: '15' },
|
||||
],
|
||||
{ inputField: 'computed', outputPath: 'rated', executionMode: 'loop' }),
|
||||
tableNode('finalPrice', 'finalPrice',
|
||||
[{ id: 'i1', name: 'Tier', field: 'customerTier' }],
|
||||
[{ id: 'o1', name: 'Final', field: 'finalPrice' }],
|
||||
[
|
||||
{ _id: 'r1', i1: "'gold'", o1: 'baseRate * (effWeight / weight) * (1 + distFactor * 0.1) * 0.9' },
|
||||
{ _id: 'r2', i1: "'silver'", o1: 'baseRate * (effWeight / weight) * (1 + distFactor * 0.1) * 0.95' },
|
||||
{ _id: 'r3', i1: '', o1: 'baseRate * (effWeight / weight) * (1 + distFactor * 0.1)' },
|
||||
],
|
||||
{ inputField: 'rated', outputPath: 'priced', executionMode: 'loop' }),
|
||||
exprNode('replicate', 'replicate', [
|
||||
['shipmentsCopy', 'shipments'],
|
||||
['computedCopy', 'computed'],
|
||||
['pricedCopy', 'priced'],
|
||||
]),
|
||||
exprNode('totals', 'totals', [
|
||||
['totalPrice', 'sum(map(priced, #.finalPrice))'],
|
||||
['count', 'len(shipments)'],
|
||||
]),
|
||||
]);
|
||||
|
||||
const customerEligibility = graph([
|
||||
inputNode('in'),
|
||||
exprNode('dailyStats', 'dailyStats', [
|
||||
['cost', 'dataGB * 0.5 + minutes * 0.01 + texts * 0.001'],
|
||||
['heavy', 'dataGB > 2'],
|
||||
], { inputField: 'usageHistory', outputPath: 'daily', executionMode: 'loop' }),
|
||||
tableNode('dailyTier', 'dailyTier',
|
||||
[{ id: 'i', name: 'Cost', field: 'cost' }],
|
||||
[{ id: 'o', name: 'Tier', field: 'usageTier' }],
|
||||
[
|
||||
{ _id: 'r1', i: '> 5', o: "'high'" },
|
||||
{ _id: 'r2', i: '> 2', o: "'medium'" },
|
||||
{ _id: 'r3', i: '', o: "'low'" },
|
||||
],
|
||||
{ inputField: 'daily', outputPath: 'dailyTiered', executionMode: 'loop' }),
|
||||
exprNode('aggregate', 'aggregate', [
|
||||
['totalCost', 'sum(map(daily, #.cost))'],
|
||||
['heavyDays', 'len(filter(daily, #.heavy))'],
|
||||
['avgData', 'sum(map(usageHistory, #.dataGB)) / len(usageHistory)'],
|
||||
]),
|
||||
tableNode('accountStatus', 'accountStatus',
|
||||
[
|
||||
{ id: 'i1', name: 'Age', field: 'accountInfo.accountAge' },
|
||||
{ id: 'i2', name: 'Payment', field: 'accountInfo.paymentHistory' },
|
||||
],
|
||||
[
|
||||
{ id: 'o1', name: 'Status', field: 'eligibility.accountStatus' },
|
||||
{ id: 'o2', name: 'Good', field: 'eligibility.goodStanding' },
|
||||
],
|
||||
[
|
||||
{ _id: 'r1', i1: '>= 24', i2: "'excellent'", o1: "'excellent'", o2: 'true' },
|
||||
{ _id: 'r2', i1: '>= 12', i2: "'excellent', 'good'", o1: "'good'", o2: 'true' },
|
||||
{ _id: 'r3', i1: '>= 6', i2: '', o1: "'fair'", o2: 'true' },
|
||||
{ _id: 'r4', i1: '', i2: '', o1: "'review'", o2: 'false' },
|
||||
]),
|
||||
tableNode('loyaltyTier', 'loyaltyTier',
|
||||
[
|
||||
{ id: 'i1', name: 'Age', field: 'accountInfo.accountAge' },
|
||||
{ id: 'i2', name: 'Spend', field: 'accountInfo.monthlySpend' },
|
||||
],
|
||||
[
|
||||
{ id: 'o1', name: 'Tier', field: 'eligibility.loyaltyTier' },
|
||||
{ id: 'o2', name: 'Discount', field: 'eligibility.loyaltyDiscountPercent' },
|
||||
],
|
||||
[
|
||||
{ _id: 'r1', i1: '>= 36', i2: '>= 120', o1: "'platinum'", o2: '20' },
|
||||
{ _id: 'r2', i1: '>= 24', i2: '>= 80', o1: "'gold'", o2: '15' },
|
||||
{ _id: 'r3', i1: '>= 12', i2: '>= 50', o1: "'silver'", o2: '10' },
|
||||
{ _id: 'r4', i1: '', i2: '', o1: "'standard'", o2: '0' },
|
||||
]),
|
||||
exprNode('specialOffers', 'specialOffers', [
|
||||
['eligibility.specialOffers', "{ 'dataBooster': usageStats.dataUtilizationPercent > 80, 'familyPlan': len(customerProfile.devices) >= 3, 'loyaltyReward': eligibility.loyaltyTier in ['platinum', 'gold', 'silver'] }"],
|
||||
['eligibility.offerCount', 'len(filter(values($.eligibility.specialOffers), # == true))'],
|
||||
]),
|
||||
exprNode('replicate', 'replicate', [
|
||||
['historyCopy', 'usageHistory'],
|
||||
['dailyCopy', 'daily'],
|
||||
['tieredCopy', 'dailyTiered'],
|
||||
]),
|
||||
]);
|
||||
|
||||
const expressionChain = {
|
||||
blocks: [
|
||||
dataModel('customer', [
|
||||
{ name: 'amounts', type: 'number', array: true },
|
||||
{ name: 'label', type: 'string' },
|
||||
]),
|
||||
expr('e1', 'customer.positive', 'filter(customer.amounts, # > 0)'),
|
||||
expr('e2', 'customer.negatives', 'filter(customer.amounts, # < 0)'),
|
||||
expr('e3', 'customer.doubled', 'map(customer.amounts, # * 2)'),
|
||||
expr('e4', 'customer.squared', 'map(customer.amounts, # * #)'),
|
||||
expr('e5', 'customer.total', 'sum(customer.positive)'),
|
||||
expr('e6', 'customer.negTotal', 'sum(customer.negatives)'),
|
||||
expr('e7', 'customer.net', 'customer.total + customer.negTotal'),
|
||||
expr('e8', 'customer.posCount', 'len(customer.positive)'),
|
||||
expr('e9', 'customer.avg', 'customer.net / len(customer.amounts)'),
|
||||
expr('e10', 'customer.maxVal', 'max(customer.amounts)'),
|
||||
expr('e11', 'customer.minVal', 'min(customer.amounts)'),
|
||||
assertion('a1', 'customer.bigSpender', 'customer.total > 1000'),
|
||||
assertion('a2', 'customer.balanced', 'customer.net > 0'),
|
||||
assertion('a3', 'customer.volatile', 'customer.maxVal - customer.minVal > 50'),
|
||||
],
|
||||
};
|
||||
|
||||
const multiAssertion = {
|
||||
blocks: [
|
||||
dataModel('customer', [
|
||||
{ name: 'age', type: 'number' },
|
||||
{ name: 'income', type: 'number' },
|
||||
{ name: 'employmentYears', type: 'number' },
|
||||
{ name: 'scores', type: 'number', array: true },
|
||||
]),
|
||||
expr('s1', 'customer.scoreSum', 'sum(customer.scores)'),
|
||||
expr('s2', 'customer.scoreAvg', 'customer.scoreSum / len(customer.scores)'),
|
||||
expr('s3', 'customer.highScores', 'filter(customer.scores, # > 50)'),
|
||||
expr('s4', 'customer.scaled', 'map(customer.scores, # * 1.5)'),
|
||||
...range(ASSERTIONS).map((i) => assertion(`a${i}`, `customer.flag${i}`, `customer.scoreAvg >= ${i}`)),
|
||||
],
|
||||
};
|
||||
|
||||
const manifest = [
|
||||
{
|
||||
name: 'decision-table-discounts',
|
||||
kind: 'graph',
|
||||
file: 'graphs/decision-table-discounts.json',
|
||||
input: { code: 'WELCOME_2023', order: { createdAt: '2023-01-15' }, customer: { joinDate: '2023-02-01', pastPurchases: [] } },
|
||||
},
|
||||
{
|
||||
name: 'expression-table-map',
|
||||
kind: 'graph',
|
||||
file: 'graphs/expression-table-map.json',
|
||||
input: {
|
||||
customer: { name: 'John Doe', country: 'US' },
|
||||
items: range(ITEMS).map((i) => ({ name: `item${i}`, amount: 10 + (i % 90), group: i % 3 === 0 ? 'accessories' : 'electronics', qty: 1 + (i % 5) })),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'credit-limit-adjustment',
|
||||
kind: 'graph',
|
||||
file: 'graphs/credit-limit-adjustment.json',
|
||||
input: {
|
||||
account: {
|
||||
customer_id: 'CUST10025',
|
||||
current_credit_limit: 5000,
|
||||
payment_history: { on_time_payment_percentage: 98, late_payments_last_12_months: 0, total_payments: 24 },
|
||||
utilization: { current_percentage: 25, average_last_6_months: 40, highest_balance: 2800 },
|
||||
financial_behavior: { credit_inquiries_last_12_months: 0, years_with_institution: 4, income_verified: true, has_other_products: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'dynamic-shipping-cost-calculator',
|
||||
kind: 'graph',
|
||||
file: 'graphs/dynamic-shipping-cost-calculator.json',
|
||||
input: {
|
||||
shipments: range(SHIPMENTS).map((i) => ({
|
||||
weight: 5 + (i % 40),
|
||||
length: 20 + (i % 30),
|
||||
width: 15 + (i % 20),
|
||||
height: 10 + (i % 15),
|
||||
distance: 50 + (i % 500),
|
||||
shippingType: ['standard', 'express', 'priority'][i % 3],
|
||||
customerTier: ['gold', 'silver', 'standard'][i % 3],
|
||||
})),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'customer-eligibility-engine',
|
||||
kind: 'graph',
|
||||
file: 'graphs/customer-eligibility-engine.json',
|
||||
input: {
|
||||
accountInfo: { accountAge: 28, paymentHistory: 'excellent', currentPlan: 'Family Premium 50GB', monthlySpend: 95, contractStatus: 'pending_renewal' },
|
||||
usageStats: { dataUsageGB: 42.5, dataUtilizationPercent: 85, callMinutes: 350, textMessages: 1250 },
|
||||
customerProfile: { segment: 'consumer', location: 'Seattle, WA', devices: ['iPhone 14', 'iPad Air', 'Apple Watch'], previousComplaints: 0 },
|
||||
usageHistory: range(DAYS).map((d) => ({ day: d, dataGB: 1 + (d % 5), minutes: 100 + (d % 200), texts: 10 + (d % 50) })),
|
||||
},
|
||||
},
|
||||
{ name: 'simple-assertion', kind: 'policy', file: 'policies/simple-assertion.json', input: { customer: { age: 30 } } },
|
||||
{ name: 'expression', kind: 'policy', file: 'policies/expression.json', input: { customer: { age: 35, income: 60000 } } },
|
||||
{
|
||||
name: 'multi-assertion',
|
||||
kind: 'policy',
|
||||
file: 'policies/multi-assertion.json',
|
||||
input: { customer: { age: 40, income: 60000, employmentYears: 5, scores: range(SCORES).map((i) => (i * 13) % 100) } },
|
||||
},
|
||||
{
|
||||
name: 'expression-chain',
|
||||
kind: 'policy',
|
||||
file: 'policies/expression-chain.json',
|
||||
input: { customer: { amounts: range(AMOUNTS).map((i) => ((i * 7) % 41) - 20), label: 'batch' } },
|
||||
},
|
||||
{ name: 'match', kind: 'policy', file: 'policies/match.json', input: { customer: { score: 85 } } },
|
||||
];
|
||||
|
||||
writeFileSync(path.join(fixtures, 'graphs', 'expression-table-map.json'), JSON.stringify(expressionTableMap));
|
||||
writeFileSync(path.join(fixtures, 'graphs', 'dynamic-shipping-cost-calculator.json'), JSON.stringify(dynamicShipping));
|
||||
writeFileSync(path.join(fixtures, 'graphs', 'customer-eligibility-engine.json'), JSON.stringify(customerEligibility));
|
||||
writeFileSync(path.join(fixtures, 'policies', 'expression-chain.json'), JSON.stringify(expressionChain));
|
||||
writeFileSync(path.join(fixtures, 'policies', 'multi-assertion.json'), JSON.stringify(multiAssertion));
|
||||
writeFileSync(path.join(dir, 'manifest.json'), JSON.stringify(manifest, null, 2) + '\n');
|
||||
|
||||
console.log('generated 5 heavy fixtures + manifest.json');
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { readFileSync, writeFileSync } from 'node:fs';
|
||||
import { hrtime, argv, env } from 'node:process';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { createRequire } from 'node:module';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const { ZenEngine } = require('../../bindings/nodejs/index.js');
|
||||
|
||||
const dir = path.dirname(fileURLToPath(import.meta.url));
|
||||
const root = path.join(dir, '..');
|
||||
const fixtures = path.join(root, 'fixtures');
|
||||
const manifest = JSON.parse(readFileSync(path.join(root, 'manifest.json'), 'utf8'));
|
||||
const iters = Number(env.BENCH_ITERS || 2000);
|
||||
const outPath = argv[2];
|
||||
|
||||
const loader = (key) => readFile(path.join(fixtures, key));
|
||||
const engine = new ZenEngine({ loader });
|
||||
|
||||
const results = [];
|
||||
for (const e of manifest) {
|
||||
for (const trace of [false, true]) {
|
||||
const opts = { trace };
|
||||
await engine.evaluate(e.file, e.input, opts);
|
||||
const start = hrtime.bigint();
|
||||
for (let i = 0; i < iters; i++) {
|
||||
await engine.evaluate(e.file, e.input, opts);
|
||||
}
|
||||
const per = Number(hrtime.bigint() - start) / iters;
|
||||
results.push({ name: `${e.name} (${e.kind})${trace ? ' +trace' : ''}`, unit: 'ns/op', value: per });
|
||||
}
|
||||
}
|
||||
|
||||
engine.dispose?.();
|
||||
|
||||
if (outPath) {
|
||||
writeFileSync(outPath, JSON.stringify(results, null, 2));
|
||||
} else {
|
||||
for (const r of results) {
|
||||
console.log(`${r.name.padEnd(44)} ${r.value.toFixed(0).padStart(12)} ns/op`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
import zen
|
||||
|
||||
root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
fixtures = os.path.join(root, "fixtures")
|
||||
manifest = json.load(open(os.path.join(root, "manifest.json")))
|
||||
iters = int(os.environ.get("BENCH_ITERS", "2000"))
|
||||
out_path = sys.argv[1] if len(sys.argv) > 1 else None
|
||||
|
||||
|
||||
def loader(key):
|
||||
with open(os.path.join(fixtures, key)) as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
engine = zen.ZenEngine({"loader": loader})
|
||||
|
||||
results = []
|
||||
for e in manifest:
|
||||
for trace in (False, True):
|
||||
opts = {"trace": trace}
|
||||
engine.evaluate(e["file"], e["input"], opts)
|
||||
start = time.perf_counter_ns()
|
||||
for _ in range(iters):
|
||||
engine.evaluate(e["file"], e["input"], opts)
|
||||
per = (time.perf_counter_ns() - start) / iters
|
||||
suffix = " +trace" if trace else ""
|
||||
results.append({"name": f'{e["name"]} ({e["kind"]}){suffix}', "unit": "ns/op", "value": per})
|
||||
|
||||
if out_path:
|
||||
with open(out_path, "w") as f:
|
||||
f.write(json.dumps(results, indent=2))
|
||||
else:
|
||||
for r in results:
|
||||
print(f'{r["name"]:<44} {r["value"]:>12.0f} ns/op')
|
||||
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "zen-benchmark"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
zen-engine = { path = "../../core/engine" }
|
||||
zen-expression = { path = "../../core/expression" }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
|
||||
@@ -0,0 +1,99 @@
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use zen_engine::loader::{FilesystemLoader, FilesystemLoaderOptions};
|
||||
use zen_engine::{DecisionEngine, EvaluationOptions};
|
||||
use zen_expression::Variable;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Entry {
|
||||
name: String,
|
||||
kind: String,
|
||||
file: String,
|
||||
input: Value,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct BenchResult {
|
||||
name: String,
|
||||
unit: String,
|
||||
value: f64,
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "multi_thread")]
|
||||
async fn main() {
|
||||
let mut args = std::env::args().skip(1);
|
||||
let manifest_path = args
|
||||
.next()
|
||||
.unwrap_or_else(|| "../manifest.json".to_string());
|
||||
let out_path = args.next();
|
||||
let iters: u32 = std::env::var("BENCH_ITERS")
|
||||
.ok()
|
||||
.and_then(|s| s.parse().ok())
|
||||
.unwrap_or(2000);
|
||||
|
||||
let manifest_path = Path::new(&manifest_path);
|
||||
let base = manifest_path
|
||||
.parent()
|
||||
.unwrap_or_else(|| Path::new("."))
|
||||
.join("fixtures");
|
||||
let manifest: Vec<Entry> =
|
||||
serde_json::from_str(&std::fs::read_to_string(manifest_path).expect("read manifest"))
|
||||
.expect("parse manifest");
|
||||
|
||||
let engine = DecisionEngine::default().with_loader(Arc::new(FilesystemLoader::new(
|
||||
FilesystemLoaderOptions {
|
||||
root: base.to_string_lossy().to_string(),
|
||||
},
|
||||
)));
|
||||
|
||||
let mut results = Vec::new();
|
||||
for e in &manifest {
|
||||
let input: Variable = e.input.clone().into();
|
||||
for trace in [false, true] {
|
||||
let opts = || EvaluationOptions {
|
||||
trace,
|
||||
max_depth: 10,
|
||||
};
|
||||
engine
|
||||
.evaluate_with_opts(e.file.as_str(), input.clone(), opts())
|
||||
.await
|
||||
.unwrap_or_else(|err| panic!("warmup {} failed: {err:?}", e.name));
|
||||
|
||||
let start = Instant::now();
|
||||
for _ in 0..iters {
|
||||
engine
|
||||
.evaluate_with_opts(e.file.as_str(), input.clone(), opts())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
let per = start.elapsed().as_nanos() as f64 / f64::from(iters);
|
||||
|
||||
results.push(BenchResult {
|
||||
name: format!(
|
||||
"{} ({}){}",
|
||||
e.name,
|
||||
e.kind,
|
||||
if trace { " +trace" } else { "" }
|
||||
),
|
||||
unit: "ns/op".to_string(),
|
||||
value: per,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
match out_path {
|
||||
Some(p) => {
|
||||
let json = serde_json::to_string_pretty(&results).expect("serialize results");
|
||||
std::fs::write(p, json).expect("write output");
|
||||
}
|
||||
None => {
|
||||
for r in &results {
|
||||
println!("{:<44} {:>12.0} ns/op", r.name, r.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+52
-52
@@ -77,8 +77,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-android-arm64')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-android-arm64/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -93,8 +93,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-android-arm-eabi')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-android-arm-eabi/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -114,8 +114,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-win32-x64-gnu')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-win32-x64-gnu/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -130,8 +130,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-win32-x64-msvc')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-win32-x64-msvc/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -147,8 +147,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-win32-ia32-msvc')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-win32-ia32-msvc/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -163,8 +163,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-win32-arm64-msvc')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-win32-arm64-msvc/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -182,8 +182,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-darwin-universal')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-darwin-universal/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -198,8 +198,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-darwin-x64')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-darwin-x64/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -214,8 +214,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-darwin-arm64')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-darwin-arm64/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -234,8 +234,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-freebsd-x64')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-freebsd-x64/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -250,8 +250,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-freebsd-arm64')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-freebsd-arm64/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -271,8 +271,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-linux-x64-musl')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-linux-x64-musl/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -287,8 +287,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-linux-x64-gnu')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-linux-x64-gnu/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -305,8 +305,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-linux-arm64-musl')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-linux-arm64-musl/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -321,8 +321,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-linux-arm64-gnu')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-linux-arm64-gnu/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -339,8 +339,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-linux-arm-musleabihf')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-linux-arm-musleabihf/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -355,8 +355,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-linux-arm-gnueabihf')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-linux-arm-gnueabihf/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -373,8 +373,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-linux-loong64-musl')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-linux-loong64-musl/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -389,8 +389,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-linux-loong64-gnu')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-linux-loong64-gnu/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -407,8 +407,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-linux-riscv64-musl')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-linux-riscv64-musl/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -423,8 +423,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-linux-riscv64-gnu')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-linux-riscv64-gnu/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -440,8 +440,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-linux-ppc64-gnu')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-linux-ppc64-gnu/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -456,8 +456,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-linux-s390x-gnu')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-linux-s390x-gnu/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -476,8 +476,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-openharmony-arm64')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-openharmony-arm64/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -492,8 +492,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-openharmony-x64')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-openharmony-x64/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
@@ -508,8 +508,8 @@ function requireNative() {
|
||||
try {
|
||||
const binding = require('@gorules/zen-engine-openharmony-arm')
|
||||
const bindingPackageVersion = require('@gorules/zen-engine-openharmony-arm/package.json').version
|
||||
if (bindingPackageVersion !== '0.54.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
if (bindingPackageVersion !== '0.54.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.54.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"include-component-in-tag": true,
|
||||
"tag-separator": "-",
|
||||
"pull-request-title-pattern": "chore(release): publish",
|
||||
"group-pull-request-title-pattern": "chore(release): publish",
|
||||
"release-as": "1.0.0-beta.0",
|
||||
"prerelease": true,
|
||||
"prerelease-type": "beta",
|
||||
|
||||
Reference in New Issue
Block a user