feat: store async generated images as WebP

This commit is contained in:
vasily committed 2026-10-16 16:34:02 +08:00
1 parent a07c178fda
commit dc0f2080f3
6 files changed
+404 -18

No files matched your search

+4 -4
View File
@@ -57,7 +57,7 @@ Success is `200` with `provider_used`, `model_used`, `images`, `text`, elapsed t
### Poll
`GET /v1/jobs/{job_id}?client_id={client_id}` plus the client's secret header. Returns status and, when complete, result; terminal failures include a sanitized error. Unknown and cross-client job IDs return `404`.
`GET /v1/jobs/{job_id}?client_id={client_id}&include_result=false` plus the client's secret header. Returns small status metadata and, when complete, result metadata with binary image download links. The links are signed, scoped to one image, and expire after one hour by default, so they can be opened directly in a browser without sending a client secret. Treat them as temporary bearer credentials. Authenticated clients may also use `GET /v1/jobs/{job_id}/images/{image_index}?client_id={client_id}` with the secret header. `include_result=true` retains the legacy Base64 response. Terminal failures include a sanitized error. Unknown and cross-client job IDs return `404`.
### Management
@@ -82,12 +82,12 @@ SQLite connections enable foreign keys and busy timeout; WAL is initialized once
3. A route loads the active client's provider keys from SQLite.
4. The adapter translates the request to Google or OpenRouter format and sends through shared async `httpx`.
5. A retryable upstream failure advances to the next configured key; success is normalized into a provider-neutral response.
6. Polling mode persists a queued job before scheduling the single-process async worker; state and results are persisted.
6. Polling mode persists a queued job before scheduling the single-process async worker. Compact status and result metadata live in SQLite; generated async images are converted to WebP and written to a private output directory. Image files are deleted after 24 hours while job, timing, and cost metadata remain. Prompt and input-image payloads are cleared from the job record at completion or failure.
## Operational plan
1. Install Python dependencies and set a unique `ADMIN_SECRET`.
2. Mount a persistent local volume at the configured database path with restrictive permissions.
2. Mount persistent local storage for both the SQLite database and generated output directory. Keep database and output backups access-restricted.
3. Run one Uvicorn worker as `www-data`, bound to `127.0.0.1:8081`. Put TLS and request-size enforcement at Nginx; keep the application port private.
4. Create clients, add provider credentials, then call `/healthz` and verify one small generation using the intended account/model.
5. Back up the database securely. Treat backups and job records as secrets and apply retention appropriate to the installation.
@@ -106,4 +106,4 @@ SQLite connections enable foreign keys and busy timeout; WAL is initialized once
- SQLite WAL assumes local storage and one app process. Multi-host operation needs a different DB and durable queue.
- Upstream model availability and provider-specific parameter support vary by account and change over time. Configure and validate model IDs per provider.
- The initial admin portal has no user/session system; protect it behind network access controls and HTTPS.
- Memory use grows with uploaded image size and serialized base64/job results; the service is asynchronous, not zero-copy or constant-memory.
- Memory use grows with uploaded image size and provider response size while a generation runs; completed async image payloads are stored as files rather than Base64 in SQLite.