python/ directory holds the Python executor and SDK. See Architecture overview for the overall architecture and Repository layout and code layering for the directory layering.
Prerequisites
Quick start
Clone and download Go dependencies
git can reach github.com/Chaintable/*; CI solves this with GOPRIVATE=github.com/Chaintable/* and token injection.Install Python dependencies
python/.venv/. pythonBin() in internal/testutil/paths.go looks for /tmp/blockx-venv/bin/python and then python/.venv/bin/python, falling back to python3 only when neither exists. When the venv is missing, all process E2E tests are skipped rather than failed.Build and run unit tests
cmd/worker links the DuckDB static library and is much slower than the other packages; later builds hit the build cache. go test ./... also runs the process / contract / system E2E tests (they don’t check -short), which need the venv from the previous step; e2e/perf is skipped by TestMain by default. To run only pure unit tests, use go test ./internal/... ./api/....Run the Python unit tests
Start a worker on your machine
StartWorkerAt in internal/testutil/worker.go; it is the minimal set the process E2E tests use to start a real worker:worker listening and executor started. What each item means:ETCD_ENDPOINTS=none: don’t register with etcd, so no Coordinator is involved; clients callRequestTaskSlot/SubmitTaskon the worker directly.ICEBERG_NAMESPACE:WorkerFullConfig.Validaterequires it to be non-empty (internal/worker/app/config.go).BLOCKDB_BATCH_WRITE_ADDR: the block profile incmd/workerregisters theBundleWriteplugin, andvalidateProfileRuntimeConfigrequires this address to be non-empty; locally, any unreachable port will do.STUB_BLOCKDB_DELAY_MS=0: once anyBLOCKDB_*_ADDRis set, the worker treats BlockDB as real; this variable switches the read path back to the devstub.
examples/local_test_service/README.md to start local_proxy.py and then run submit.py. You can also run a single process E2E test to see a real call:Makefile targets
Environment variables and config files
The worker’s load order lives ininternal/worker/app/app.go: DefaultWorkerFullConfig() → the profile’s TuneDefaults → the JSON file pointed to by WORKER_CONFIG (LoadWorkerFullConfigFrom) → environment variable overrides. JSON field names match the json tags of WorkerFullConfig; see docs/deploy.md §9.3 in the blockx repository for an example. The coordinator reads only environment variables and has no config file (LoadCoordinatorRuntimeConfigFromEnv in internal/coordinator/app/config.go).
The variables you’ll run into most often in local development:
docs/deploy.md §9 in the blockx repository; deploy/env/worker.env.example is a sample env file for EC2 deployment that contains many keys read only by the host scripts, so it isn’t suitable for running locally as-is.
Code generation
Regenerate the Go bindings after changing.proto files:
Makefile adds $(go env GOBIN) (or $(go env GOPATH)/bin) to PATH, so installing the plugins in the default location is enough. Proto source locations: api/grpc/*/ and internal/sdk/{blockdb,meta,localtestservice}/proto/. Commit the generated output together with the change.
Common issues
All E2E tests show SKIP with Python dependencies not available
All E2E tests show SKIP with Python dependencies not available
RequirePythonModules in internal/testutil/python.go tries an import with the detected interpreter and calls t.Skip on failure. The process E2E tests in cmd/worker require all seven modules greenlet, blockx_sdk, blockx_executor, blockdb, blockx, leafage, chaintable to be importable (cmd/worker/worker_process_helpers_test.go); the last four come from the private git dependencies in pyproject.toml. Run uv sync --project python first and confirm that python/.venv/bin/python exists.go build ./cmd/worker fails with build constraints exclude all Go files in duckdb-go-bindings/lib
go build ./cmd/worker fails with build constraints exclude all Go files in duckdb-go-bindings/lib
CGO_ENABLED=0. worker and bundle_worker must have CGO enabled, and the machine needs a C compiler. A slow first link is normal.The worker exits immediately: invalid worker config
The worker exits immediately: invalid worker config
icebergNamespace must not be empty, add ICEBERG_NAMESPACE; for plugin BlockBundleWriteResultHandler requires blockdb.batchWriteAddr, add BLOCKDB_BATCH_WRITE_ADDR; for usage-related errors, add BLOCKX_USAGE_DISABLED=true.The worker is running but the Coordinator can't see it
The worker is running but the Coordinator can't see it
ETCD_ENDPOINTS points to the same etcd and that WORKER_ADDR is an address the Coordinator can reach; with container network isolation it must be set explicitly (docs/deploy.md §7). For single-machine local debugging, you can bypass the Coordinator with ETCD_ENDPOINTS=none.The Python executor child processes don't start
The Python executor child processes don't start
PYTHON_BIN points to can import blockx_executor (PYTHONPATH must include python/). The default python3 is usually the system interpreter and lacks dependencies such as greenlet.go mod download can't fetch github.com/Chaintable/*
go mod download can't fetch github.com/Chaintable/*
git config --global url."git@github.com:".insteadOf "https://github.com/") and set GOPRIVATE=github.com/Chaintable/*. The Python-side blockx-py and friends are also private git dependencies and need credentials too.Related docs
- Testing: commands, durations, and prerequisites for each test layer.
- Contributing: commit and PR conventions.
- Repository layout and code layering: what goes in
cmd/,internal/,api/, andpython/. - Deployment overview: image build and the EC2 runtime shape.
docs/deploy.mdin the blockx repository: full environment variable table, Docker startup examples, and common issues.AGENTS.mdin the blockx repository: the authoritative checklist for build, test, and collaboration conventions.