Implement kaya-rbcs: simplified RBCS clone on the Kaya framework
CI / Build and push docker image (push) Successful in 2m57s
CI / Build and push docker image (push) Successful in 2m57s
- KayaApp with GET/PUT recursive routes backed by memcached (aiomcache) - env-based configuration, metadata-aware value encoding, key prefix/digest - Granian RSGI launcher (rbcs-server / python -m kaya_rbcs) - pinned requirements via pip-compile, alpine:3.24 Dockerfile with healthcheck - offline tests using an in-process fake memcached - Gitea Actions workflow to build and push the multi-arch Docker image
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
# kaya-rbcs
|
||||
|
||||
A simplified Python clone of [RBCS](https://gitea.woggioni.net/woggioni/rbcs)
|
||||
(Remote Build Cache Server) built on the [Kaya](https://gitea.woggioni.net/woggioni/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
|
||||
|
||||
```bash
|
||||
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`:
|
||||
|
||||
```bash
|
||||
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`) |
|
||||
|
||||
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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
Reference in New Issue
Block a user