A high-performance Package Revision (PR) server for BitBake builds, rewritten in Rust and backed by PostgreSQL.
Integrating prserv into a cluster? See docs/integration.md for the design (PR-allocation correctness), requirements, the multi-tenant database-per-dataset model, and deployment guidance.
- PostgreSQL backend - Concurrency-safe storage; state lives in a shared database, not a local file
- Concurrency-safe PR allocation - Atomic
max+1allocation with a uniqueness guard (see docs/integration.md) - Async TCP server - High-performance async networking with tokio
- BitBake compatibility - Drop-in replacement for the Python prserv
- History and no-history modes - Supports both PR increment modes
- Read-only mode - Safe querying without modifications
- Structured logging - Comprehensive logging with tracing
- Type-safe errors - Rust's error handling for reliability
This Rust implementation backs prserv with PostgreSQL so it can run as a stateless pod against a shared database:
- Concurrency-safe allocation: PR values are allocated with a single atomic SQL statement guarded by
a
UNIQUE(version, pkgarch, value)constraint with retry — multiple replicas against one database are safe (no single-writer requirement). See docs/integration.md. - Durable per commit: every write is committed inline; there is no write buffer to lose on a crash.
- Memory safety: Rust's ownership system prevents common memory issues.
Build from source:
cargo build --releaseThe binary will be available at target/release/prserv.
# Start server (defaults: localhost:8585, postgres://prserv@localhost:5432/prserv)
prserv server
# Custom database URL and bind address
prserv server --database postgres://user:pass@db-host:5432/prserv_2026 --bind 0.0.0.0:9090
# Cap the connection pool (size against the instance's max_connections budget)
prserv server --max-connections 64
# Read-only mode
prserv server --read-only
# No-history mode (no PR decrements)
prserv server --nohist# Get a PR value (creates if doesn't exist)
prserv client get-pr "1.0" "x86_64" "abc123hash"
# Test if PR exists
prserv client test-pr "1.0" "x86_64" "abc123hash"
# Check if package exists
prserv client test-package "1.0" "x86_64"
# Get maximum PR for package
prserv client max-package-pr "1.0" "x86_64"
# Import a PR value
prserv client import-one "1.0" "x86_64" "abc123hash" 42
# Export data
prserv client export --colinfo
# Check server status
prserv client ping
prserv client is-readonlyThe server auto-creates its tables in the connected PostgreSQL database. The
UNIQUE(version, pkgarch, value) constraint is what makes concurrent PR allocation safe — see
docs/integration.md.
CREATE TABLE IF NOT EXISTS "PRMAIN_hist" ( -- history mode (default)
version TEXT NOT NULL,
pkgarch TEXT NOT NULL,
checksum TEXT NOT NULL,
value BIGINT NOT NULL,
PRIMARY KEY (version, pkgarch, checksum),
UNIQUE (version, pkgarch, value)
);
-- "PRMAIN_nohist" is identical; --nohist selects it.The server supports JSON/YAML configuration files:
# config.yaml
server:
database: "postgres://user:pass@db-host:5432/prserv_2026"
bind_addr: "0.0.0.0:8585"
read_only: false
nohist: false
client:
server_addr: "localhost:8585"The server implements a JSON-RPC style protocol over TCP:
{
"id": "unique-request-id",
"method": "get-pr",
"params": {
"version": "1.0",
"pkgarch": "x86_64",
"checksum": "abc123hash"
}
}{
"id": "unique-request-id",
"result": {"value": 42},
"error": null
}get-pr: Get/create PR valuetest-pr: Test if PR existstest-package: Test if package existsmax-package-pr: Get maximum PR for packageimport-one: Import PR valueexport: Export PR datais-readonly: Check server modeping: Health check
- PostgreSQL backend: state lives in a shared database, enabling a stateless service
- Concurrency-safe allocation: atomic
max+1with a uniqueness guard; safe across replicas - Better error handling: type-safe error propagation
- Async architecture: non-blocking I/O for better performance
Note: the sqlite-era
--sync-modeflag (immediate/periodic/on_shutdown) is deprecated and ignored — the postgres backend is durable per commit and has no write buffer. The flag is still accepted so old invocations don't break.
cargo buildcargo testRUST_LOG=debug cargo run -- serverYou can configure the server using environment variables:
# Server configuration
export PRSERV_DATABASE="postgres://user:pass@db-host:5432/prserv_2026"
export PRSERV_BIND_ADDR="0.0.0.0:8585"
export PRSERV_MAX_CONNECTIONS="64"
export PRSERV_READ_ONLY="false"
export PRSERV_NOHIST="false"
# PRSERV_SYNC_MODE is accepted but ignored (sqlite-era; postgres is durable per commit)
# Client configuration
export PRSERV_SERVER_ADDR="localhost:8585"
# Start server with environment config
prserv serverApache-2.0