Skip to content

Repository files navigation

GPU cover worker service

A SQLite-backed API for creating six styled book-cover previews and one selected final cover.

SERVICE_URL=https://pin-log.com/image

The unauthenticated readiness endpoint is GET /health and returns {"status":"ok"} with HTTP 200.

Run locally

python -m venv .venv
. .venv/bin/activate
pip install -r requirements-dev.txt
uvicorn app.main:app --reload

Configuration:

  • DATABASE_PATH defaults to data/app.db.
  • FILES_DIR defaults to data/files.
  • STALE_JOB_SECONDS defaults to 1800. A running job older than this is requeued when attempts remain, or marked failed after MAX_ATTEMPTS claims.
  • PUBLIC_BASE_PATH defaults to empty. Set it to the externally mounted service prefix (for example, /image) so returned file URLs use /image/files/NAME; the application's internal static route remains /files/NAME.
  • WORKER_TOKEN, when set, protects every /jobs endpoint with Authorization: Bearer TOKEN.

Exact workflow

Create all six previews:

curl -X POST "$SERVICE_URL/api/covers" \
  -H 'content-type: application/json' \
  -d '{"title":"달빛 고양이","keywords":["숲","달빛"]}'

The response is {"request_id":"...","candidates":[{"style_id":"watercolour","label":"수채화"}, ...]}.

Poll request state:

curl "$SERVICE_URL/api/covers/REQUEST_ID"

A worker claims work (the default long poll is 25 seconds):

curl "$SERVICE_URL/jobs/claim?worker_id=gpu-1" \
  -H "Authorization: Bearer $WORKER_TOKEN"

The claim response contains exactly id, workflow, and inputs. Upload one or more generated images with a JSON-string meta field; image_0 is required:

curl -X POST "$SERVICE_URL/jobs/JOB_ID/result" \
  -H "Authorization: Bearer $WORKER_TOKEN" \
  -F 'meta={"renderer":"comfyui"}' \
  -F image_0=@preview.webp \
  -F image_1=@alternate.webp

Report a permanent or retryable failure:

curl -X POST "$SERVICE_URL/jobs/JOB_ID/fail" \
  -H "Authorization: Bearer $WORKER_TOKEN" \
  -H 'content-type: application/json' \
  -d '{"error":"GPU unavailable","retryable":true}'

Select a style to enqueue the full-size final job:

curl -X POST "$SERVICE_URL/api/covers/REQUEST_ID/select" \
  -H 'content-type: application/json' \
  -d '{"style_id":"watercolour"}'

Previews request 512×768 WebP at quality 82. Final jobs request 1795×2657 WebP at quality 92. Both use generation dimensions 1024×1536 and four steps.

Verification

pytest -q
python -m compileall -q app tests

Container and CI

The container runs as the fixed non-root identity 1000:1000. Its persistent /data directory is owned by that identity, so any mounted volume must also be writable by UID/GID 1000.

GitHub Actions runs the test suite and Python bytecode compilation for pull requests and pushes to main. A push to main also publishes the image as ghcr.io/team-pinlog/image:sha-COMMIT_SHA and reports its registry digest. No mutable latest tag is produced.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages