Execute MultiFlexi jobs (one-shot or as a long-running daemon).
multiflexi-executor is part of the MultiFlexi suite. See the full list of ready-to-run applications within the MultiFlexi platform on the application list page.
- PHP 8.2+
- Composer
- A configured MultiFlexi database (shared across the suite)
- Optional: the
pcntlextension for SIGTERM/SIGINT graceful-shutdown support in the daemon
composer install
Place a .env file at the repository root. The executor reads configuration via Ease\Shared.
Common keys:
| Variable | Default | Description |
|---|---|---|
DB_CONNECTION |
mysql |
Database driver (mysql, pgsql, sqlite) |
DB_HOST |
localhost |
Database host |
DB_PORT |
driver default | Database port |
DB_DATABASE |
— | Database name |
DB_USERNAME |
— | Database user |
DB_PASSWORD |
— | Database password |
APP_DEBUG |
false |
Log to console when true |
MULTIFLEXI_DAEMONIZE |
true |
Run the daemon continuously |
MULTIFLEXI_CYCLE_PAUSE |
10 |
Seconds between polling cycles |
MULTIFLEXI_MAX_PARALLEL |
0 |
Max concurrent jobs; 0 = unlimited |
MULTIFLEXI_MEMORY_LIMIT_MB |
0 |
Soft memory limit in MB (0 = disabled) |
RESULT_FILE |
php://stdout |
Default output destination for one-shot runs |
RUNTEMPLATE_WAIT_TIMEOUT |
300 |
Seconds -r waits for the daemon to finish a queued job (0 = forever) |
RUNTEMPLATE_WAIT_POLL |
2 |
Seconds between DB polls while -r waits for completion |
ZABBIX_SERVER / ZABBIX_HOST |
— | Enable LogToZabbix when both are set |
Notes:
src/executor.phpandsrc/daemon.phpexpectvendor/autoload.phpand.envone directory above. Run them fromsrc/so relative paths resolve.- The daemon passes the absolute
.envpath to each job subprocess automatically.
From repo root:
cd src && php -q -f executor.php -- -r <RUNTEMPLATE_ID> [-o <output_path>] [-t <seconds>] [-e <env_file>]
This queues a new job for the given RunTemplate to run now and then blocks until the executor daemon has finished it. Once done, the job's captured stdout is written to the output destination, its stderr is forwarded to stderr, and the command exits with the job's own exit code.
The executor daemon must be running for the queued job to be picked up. If it is not, the command waits until the timeout elapses and exits
124.
Flags:
- -r, --runtemplate: RunTemplate ID to schedule and wait for
- -o, --output: destination for captured output (defaults to stdout or RESULT_FILE)
- -t, --timeout: max seconds to wait for the daemon to run the job;
0waits forever (default: 300, or RUNTEMPLATE_WAIT_TIMEOUT) - -e, --environment: path to .env (defaults to ../.env)
From repo root:
cd src && php -q -f daemon.php
Behavior:
- Controlled by
.env. WhenMULTIFLEXI_DAEMONIZE=truethe process runs continuously, sleepingMULTIFLEXI_CYCLE_PAUSEseconds between polling cycles. - Parallel execution: each due job is launched as an isolated
executor.phpsubprocess. Jobs run concurrently without blocking one another, so a slow job never delays the next timeslot. Each subprocess gets its own PHP process, database connection, and memory — no shared state between jobs. - Per-runtemplate serialisation: the daemon will not start a new job if another job from the same RunTemplate is already in flight. The queued entry is left untouched and picked up automatically once the running job finishes. This prevents duplicate side-effects (e.g. double bank-statement imports) when a long-running job overlaps its next scheduled trigger.
MULTIFLEXI_MAX_PARALLELcaps the number of concurrently running subprocesses (0= unlimited). When all slots are occupied the daemon waits until a slot frees before launching the next job.- On
SIGTERMorSIGINT(requires thepcntlextension) the daemon stops accepting new jobs and waits for all in-flight subprocesses to finish before exiting.
Examples:
# Run daemon with up to 4 concurrent jobs
MULTIFLEXI_MAX_PARALLEL=4 php -q -f src/daemon.php
# Unlimited parallelism (default when 0 or unset)
php -q -f src/daemon.phpmake vendor # install dependencies
make static-code-analysis # phpstan
make static-code-analysis-baseline
make cs # coding standards (php-cs-fixer)
make autoload # composer update
make tests # run PHPUnit tests
make buildimage # build container image
make buildx # multi-arch build & push
make drun # run container (requires .env)
Run all tests:
make tests
Run a single test file or filtered tests:
vendor/bin/phpunit path/to/TestFile.php
vendor/bin/phpunit --filter "TestNameOrRegex"
The repo includes an integration-oriented script under tests/ that schedules a RunTemplate using multiflexi-cli:
multiflexi-cli runtemplate schedule --id 1 --format json
The Kubernetes executor (MultiFlexi\Executor\Kubernetes) runs jobs as one-shot pods in a Kubernetes cluster using kubectl run --attach.
- Config derivation: The executor reconstructs Kubernetes config from existing DB fields — no dedicated kubernetes JSON column is needed:
helmchartcolumn → Helm chart URI (OCI or repo reference)namecolumn → Helm release name (lowercased, DNS-1123 safe)artifactscolumn → artifact output paths forkubectl cp- Sensible defaults for namespace (
multiflexi), timeout (300s), etc.
- Helm pre-deploy: On first run, if the application is not yet deployed, the executor runs
helm upgrade --installusing the chart from thehelmchartDB field. - Job execution: Creates an ephemeral pod via
kubectl runwith--restart=Never --attach, passing environment variables via--envflags. - Artifact collection: After pod completion, copies artifacts from the pod via
kubectl cpand stores them in the MultiFlexi FileStore. - Log capture:
storeLogs()fetches pod output viakubectl logsafter job completion.
kubectlbinary in PATHhelmbinary in PATH (for Helm pre-deployment)- Valid kubeconfig at
~/.kube/configor$KUBECONFIG - Applications must have
ociimageset (container image reference) - Applications should have
helmchartset to a valid Helm chart URI for first-time deployment
File-path config fields from the executor host are skipped for Kubernetes jobs — host paths are not available inside the pod. A warning is logged for each skipped field.
The Azure executor (MultiFlexi\Executor\Azure) runs jobs as one-shot containers in Azure Container Instances (ACI).
- Container creation: Creates a container group via
az container create --restart-policy Never(one-shot). - Environment variables: Passes env vars via
--environment-variables. Sensitive vars (containing PASSWORD, SECRET, TOKEN, KEY) are routed to--secure-environment-variables. - Status polling: Polls
az container showevery 10 seconds until the container reaches a terminal state (up to 1 hour). - Log collection: Fetches output via
az container logsafter completion. - Cleanup: Deletes the container group via
az container delete.
- Azure CLI (
az) in PATH, authenticated (az login) AZURE_RESOURCE_GROUPenvironment variable set (required)- Applications must have
ociimageset
AZURE_RESOURCE_GROUP— Azure resource group (required)AZURE_LOCATION— Azure region (default:westeurope)AZURE_CPU— CPU cores per container (default:1)AZURE_MEMORY— Memory in GB per container (default:1.5)