Files
woggioni-opencode-agent c7d75f6899
CI / Build and push docker image (push) Successful in 2m52s
Support standard GRANIAN_* env vars and the rloop event loop
- Launcher now only injects --interface/--host/--port when the matching
  GRANIAN_* env var is unset, so every granian option (GRANIAN_LOOP,
  GRANIAN_WORKERS, GRANIAN_HTTP, GRANIAN_HOST, GRANIAN_PORT, ...) can be
  configured via granian's standard GRANIAN_* environment variables
- Add the rloop event loop as a runtime dependency so GRANIAN_LOOP=rloop
  works out of the box (previously failed with a missing 'rloop' package)
2026-08-03 05:28:04 +00:00

4.3 KiB

kaya-rbcs

A simplified Python clone of RBCS (Remote Build Cache Server) built on the Kaya web framework.

It implements only the two core cache endpoints — GET and PUT — persisting values to memcached. Authentication, RBAC, rate limiting, TRACE health checks, compression and TLS are intentionally left out.

Behavior

The cache key is the request path relative to a configurable URL prefix (default /), normalized (.. segments are resolved). Values are stored in memcached together with the Content-Type and Content-Disposition metadata sent on upload, mirroring RBCS' CacheValueMetadata.

Request Response
PUT /<key> 201 Created, body = key, Content-Type: text/plain
GET /<key> (hit) 200 OK, body = value, stored Content-Type / Content-Disposition
GET /<key> (miss) 404 Not Found, empty body
GET/PUT outside prefix 400 Bad Request

Installation

pip install -e .            # + kaya-core, aiomcache
pip install -e .[server]    # additionally installs granian + kaya-rsgi

Requires Python 3.10+ and a running memcached.

Running

Start the server with the rbcs-server console script or python -m kaya_rbcs:

rbcs-server

Configuration is read from environment variables:

Variable Default Description
RBCS_HOST 127.0.0.1 Bind address
RBCS_PORT 8080 Bind port
RBCS_PATH_PREFIX / URL prefix that maps to the cache
RBCS_MEMCACHE_HOST 127.0.0.1 Memcached host
RBCS_MEMCACHE_PORT 11211 Memcached port
RBCS_KEY_PREFIX (unset) String appended to each cache key
RBCS_DIGEST (unset) Hash the key with this algorithm (e.g. sha256)
RBCS_MAX_AGE 7d Value TTL (s/m/h/d)

Configuring Granian

The server runs on Granian via its RSGI interface. Any granian option can be configured with its standard GRANIAN_* environment variables (see granian --help), for example:

GRANIAN_LOOP=rloop GRANIAN_WORKERS=4 GRANIAN_HTTP=2 rbcs-server

Every granian CLI option has a matching GRANIAN_* variable (GRANIAN_LOOP, GRANIAN_WORKERS, GRANIAN_HTTP, GRANIAN_TASK_IMPL, GRANIAN_RUNTIME_THREADS, GRANIAN_BLOCKING_THREADS, GRANIAN_LOG_LEVEL, GRANIAN_METRICS, GRANIAN_WS, ...).

When a GRANIAN_* variable and the corresponding RBCS_* variable are both set, the granian one wins:

  • GRANIAN_HOST overrides RBCS_HOST (default 127.0.0.1)
  • GRANIAN_PORT overrides RBCS_PORT (default 8080)
  • GRANIAN_INTERFACE overrides the default rsgi interface

The Docker image ships the rloop event loop, so GRANIAN_LOOP=rloop works out of the box:

docker run -e GRANIAN_LOOP=rloop -e RBCS_MEMCACHE_HOST=memcached kaya-rbcs

The app is also a plain ASGI application, so it can be served by any ASGI server, e.g. daphne kaya_rbcs.app:app.

Usage example

curl -X PUT -H 'Content-Type: application/octet-stream' \
     --data-binary @build-output.tar http://localhost:8080/my-module/build
curl http://localhost:8080/my-module/build -o build-output.tar

Tests

python -m unittest discover -s tests

Tests use an in-process fake memcached (text protocol), so they run offline with no external dependencies.

Layout

src/kaya_rbcs/
├── __init__.py    # package exports + `rbcs-server` entry point
├── __main__.py    # Granian (RSGI) launcher
├── config.py      # env-based configuration
├── store.py       # MemcacheStore: value+metadata encoding, key processing
└── app.py         # create_app(): KayaApp with GET/PUT recursive routes
tests/
├── fake_memcached.py
└── test_app.py