გორა.
AI-translation · draft (awaiting native review)
GoraGen — AI-ვიდეო გენერაციის პლატფორმა

ტექნიკური სტეკი

FastAPI + Postgres 16 + ChromaDB + R2, ოთხი აპლიკაცია ერთი Caddy-ის უკან, იზოლირებული workers-კონტეინერი, Plan-100 control plane.

~5 წუთი წასაკითხი · 1049 სიტყვა

TL;DR

Backend — ერთადერთი FastAPI-აპლიკაცია. Workers — ცალკე singleton-კონტეინერი რვა loop-ით. Frontend — სამი აპლიკაცია (landing Astro-ზე, dash React 19 + TanStack Router-ზე, admin React 19-ზე) ერთი Caddy-ის უკან TLS-ით, per-host CSP-ით და 1სთ-იანი WS-ტაიმაუტებით გრძელი pipeline-ებისთვის. Postgres 16 + ChromaDB + Cloudflare R2 — ძირითადი საცავი. 61 მიგრაცია, Plan-100 control plane კოორდინატორით/რანერით/რეკონსილერით.

სტეკი და არქიტექტურა

ტოპოლოგია

Caddy (TLS + per-host CSP + WS timeouts 1h, flush_interval -1)
  ↓
  ├── landing.goragen.com   → Astro static
  ├── app.goragen.com       → React 19 SPA (dash)
  ├── admin.goragen.com     → React 19 SPA (admin)
  └── api.goragen.com       → FastAPI + WS endpoints
                              ↓
                              ↓     workers (replicas:1, stop_grace 120s)
                              ↓     ├── coordinator_loop
                              ↓     ├── runner_loop
                              ↓     ├── reconciler_loop
                              ↓     ├── auto_provisioner_loop
                              ↓     ├── daily_cleanup_loop
                              ↓     ├── distribution_worker
                              ↓     ├── voice/lip_sync workers
                              ↓     └── heartbeat_loop
                              ↓
                              ├── Postgres 16 (psycopg v3)
                              ├── ChromaDB (vectors)
                              └── External:
                                    Vast.ai (GPU rental)
                                    Kling Direct API
                                    Anthropic Claude
                                    Google Gemini
                                    Cloudflare R2
                                    Sentry

API (FastAPI)

api/main.py — entry-point. Startup-თანმიმდევრობა:

  1. SQL-მიგრაციების გაშვება (61 ფაილი, idempotent, ordered, pg_advisory_lock(42) multi-replica უსაფრთხოებისთვის).
  2. Legacy vast_instance.json singleton-კონფიგის მიგრაცია vast_instances ცხრილში.
  3. Auth-ცხრილების ინიციალიზაცია, admin-ის seed ENV-დან, __system__ sentinel-user-ის seed (FK-ისთვის users(id)-ზე სისტემურ ჩანაწერებში).
  4. reconcile_interrupted_on_startup()running-ში დარჩენილი job-ების ხელახლა queue-ში ჩაყრა არასწორი shutdown-ის შემდეგ.
  5. In-flight WS-სესიების restore DB-დან, ჩარჩენილების მონიშვნა interrupted-ად.
  6. Voice-სემპლების გენერაცია პირველ boot-ზე (თუ არ იყო).
  7. scheduler_loop-ის გაშვება (დანარჩენი loop-ები — workers-კონტეინერში).

Shutdown-ისას: app.state.bg_tasks-ის cancel, WS close-code 1012 («Service Restart») broadcast აქტიურ სესიებზე. Dash-კლიენტი ხედავს 1012-ს და მაშინვე ცდილობს reconnect-ს — timeout-wait-ის გარეშე.

Workers კონტეინერი

ცალკე სიდეკარი, replicas: 1 (singleton). ეს კრიტიკულია — ზოგი loop ინახავს მდგომარეობას მეხსიერებაში (lease tracking, in-progress provisions), რომელიც ვერ გადანაწილდება რთული კოორდინაციის გარეშე.

ჰოსტი:

  • coordinator_loop — admission control. კითხულობს instance_requests-ს, ადებს parallel-limits + velocity-guard, INSERTs provision_attempts-ში. Leader-elected provision_leader-ით.
  • runner_loop — execution. იღებს claimed attempts-ს, იძახებს scripts/vast_provision.ensure_instance(...)-ს, ადებს terminal reducer-ს (success → ready, failed → terminated, etc).
  • reconciler_loop — recovery. სკანერავს stale lease-ებს ხუთი ტიპის წყაროებიდან, ძალით ხურავს cancelling-ში ჩარჩენილებს, ათავისუფლებს destroyed instances-ს.
  • auto_provisioner_loop — წუთიერი tick, rule-based spawn/destroy. ახლა აგზავნის control plane-ის გავლით source_kind='auto_pool'-ზე.
  • daily_cleanup_loop — 24h retention sweep: job_queue, decisions, lora_workspaces, idempotency keys, domain events >180d, disk usage check.
  • distribution_worker — 30წმ tick, scheduled posts → social platforms.
  • voice_clone_worker / lip_sync_worker — voice job mock-ები (მომავალი სრული inference-ისთვის).
  • heartbeat_loop — ყოველ 30 წამში წერს system_settings.workers_last_heartbeat-ს.

SIGTERM → 120წმ graceful. Coordinator, runner, reconciler ხედავენ heartbeat_task.done()-ს, რომ leadership loss არ დადუმდეს.

მონაცემთა ბაზა

PostgreSQL 16, წვდომა api/db.py:get_connection-ით — psycopg v3 wrapper SQLite-style API-ით. ეს საჭიროა, რადგან legacy runtime SQL იწერებოდა SQLite-ისთვის (row[0], row["col"], ? placeholders); api/db_dialect.translate_runtime_sql თითო execute-ზე გადააწერს placeholders + datetime('now')-ს.

ეს კომპრომისია: 100k+ ხაზის SQL-ის გადაწერის ნაცვლად — runtime-მთარგმნელი. Phase 11→12 cutover-მა (2026-05-12) წაშალა dual-driver.

მიგრაციები

61 SQL-ფაილი api/migrations/-ში:

  • 001–027 — Phase 0–7 foundation: auth, workspaces, plans, personas, storyboards, gallery, distribution, voice, API keys, webhooks.
  • 028–029 — Phase 8.1: job_queue, instance LoRA cache.
  • 030–032 — Phase 8.2: vast_instances, provisioning_rules, provisioner_decisions.
  • 033 — Phase 8.3: lora_training_jobs.
  • 034–037 — Phase 9: domain_events, idempotency_keys, user_daily_spend, cost-protection knobs.
  • 040–044 — Phase 11→12: Postgres-cutover artefacts.
  • 047–054 — Phase 14 slim_provisioning: model_registry_v2, node_packages, presets, bootstrap meta, Telegram bot storage.
  • 055–061 — Plan-100 Stage 1–6: shadow tables, atomic reuse claim, cutover flags, observability thresholds.

თითო მიგრაცია — idempotent, _migrations tracker-ცხრილი, pg_advisory_lock(42) სერიალიზებს multi-replica startup-ებს.

ChromaDB

knowledge/db/chroma/ — ვექტორული ინდექსი promt-რეცეპტებისთვისა და Civitai-მონაცემებისთვის. 2 458 ComfyUI node-სქემა დაკეშილია node_info_cache.py-ში. 40 reference workflow (WAN 2.1, HunyuanVideo, LTX 2.3) დევს knowledge/db/workflow_examples/-ში.

knowledge/workflow_builder.py — ComfyUI-გრაფების პროგრამული აგება; patch_workflow_with_lora ინჟექტავს LoRA-loader-ებს base-workflow-ში.

ავთენტიფიკაცია

ორი რეჟიმი:

  1. Cookie JWT — primary, browser flow. access_token + refresh_token .goragen.com-ზე. Argon2 პაროლებისთვის.
  2. Bearer gk_live_* — SDK / CI. Argon2-ჰეშირებული გასაღებები api_keys.key_hash-ში. გადადის get_current_user-ში cookie-გზის შემდეგ.

require_admin, require_plan(...) — depends-დეკორატორები ავტორიზაციისთვის.

Middleware

  • rate_limit.py — slowapi keyed JWT user → API key prefix → IP-ით.
  • idempotency.py — Phase 9 C5 @idempotent(ttl_hours=24). კითხულობს Idempotency-Key-ს, lookup idempotency_keys-ში handler-ის გაშვებამდე. Hit → replay cached JSONResponse; hash mismatch (იგივე გასაღები, განსხვავებული body) → 409; missing header → 400. გამოყენებულია 5 mutating endpoint-ზე. Dash-კლიენტი ავტოს ინჟექტავს crypto.randomUUID()-ს ამ გზებზე და იყენებს key-ს ხელახლა 401/429/5xx retry-ებზე.
  • maintenance_middleware — გლობალური 503, როცა system_settings.maintenance_mode == 'true' (admin/auth/health passthrough).
  • CORS — დაფიქსირებულია ["GET","POST","PATCH","DELETE","OPTIONS"].
  • _record_unhandled — აგზავნის unhandled exceptions-ს error_buffer ring-buffer-ში admin dashboard-ისთვის.

Frontend

apps/dash — მომხმარებლის კაბინეტი

React 19 + TypeScript + Vite 6 + Tailwind 4. Routing — TanStack Router (file-based, flat).

State-ის გაყოფა:

  • TanStack Query — სერვერული კეში, refetch, mutations.
  • Zustand — cross-component session signals (live cost ticker).
  • lib/_http.ts — HTTP კლიენტი, ამუშავებს 401/refresh-ს, 429 retry-ს, 5xx exponential backoff-ს, offline detection-ს.

WebSocket reconnect — backoff [1წმ, 2წმ, 5წმ, 10წმ, 30წმ] src/lib/ws.ts-ში.

Routes (high-level): /, /library, /library/$slug, /generate, /storyboard, /gallery, /voice, /lora, /distribution, /compliance, /settings/* (7 sub-routes).

Onboarding-tour ლეიზად ჩაიტვირთება Driver.js-ით.

apps/admin — admin SPA

React 19. Sidebar shell AdminShell.tsx keyboard shortcut-ებით.

Routes: /dashboard, /users, /personas, /presets, /workflows, /instances, /tasks (4 sub-tabs), /lora, /system (6 sub-tabs control-plane-ის ჩათვლით), /compliance, /settings.

apps/landing — მარკეტინგი

Astro static. SPA-runtime-ის გარეშე. ესაუბრება მხოლოდ /auth/register, /auth/login, /auth/forgot-password-ს.

Caddy

ერთადერთი TLS-ტერმინატორი. Per-host CSP. Reverse-proxy ოთხ სერვისზე. კრიტიკული პარამეტრი გრძელი pipeline-ებისთვის:

read_timeout 1h
write_timeout 1h
flush_interval -1

LoRA-სწავლება იღებს 45-90 წუთს, storyboard — 10-15 წუთს. ამ timeout-ების გარეშე WS-სესია ცვივებოდა ყოველ 30-60 წამში.

External

  • Vast.ai — rented GPU pool. Provisioning scripts/vast_provision.py-ით. SSH ControlMaster + retry helpers ssh_utils.py-ში.
  • Kling Direct API — endpoints T2V, I2V, omni, extend, lip-sync, effects-ისთვის. JWT (HS256) KlingClient-ში.
  • Anthropic Claude — orchestration (მოდელის არჩევა, prompt engineering, captions).
  • Google Gemini 2.5 Pro — output evaluation (4 კრიტერიუმი, verdict).
  • Cloudflare R2 — canonical storage (STORAGE_BACKEND=s3, bucket goragen-prod, CDN cdn.goragen.com-ზე).
  • Sentry — error tracking (no-op, როცა SENTRY_DSN ცარიელია).

რას გადავწერდი

Workers ერთიანი რეპლიკით. ახლა singleton აუცილებლობით (in-memory state). შესაძლებელია per-loop კონტეინერებად დაყოფა პასუხისმგებლობების გაყოფით — თითო loop ცალკე პროცესი persistent state-ით Postgres-ში. მაგრამ ეს მნიშვნელოვანი სამუშაოა და ახლა blocker არ არის.

Workflow templates როგორც კოდი. ახლა reference workflows — JSON-ფაილებია. შესაძლებელია DSL-ის შექმნა გრაფების აგებისთვის პრიმიტივებიდან (camera move + model + lora + sampler), რომელიც კომპილდება JSON-ში.

Self-hosted Kling-ის ალტერნატივა. Kling — დახურული API. როცა open-source ალტერნატივა ცალკდება (WAN 3.x / Hunyuan v2), შესაძლებელია გადართვა model_selector-ის გავლით ცვლილებების გარეშე ზემოდან.

პლატფორმა პროდაქშენშია goragen.com-ზე. 61 მიგრაცია — ეს ექვსი თვის აქტიური დეველოპმენტია რეგულარული დეპლოით downtime-ის გარეშე (Phase 11→12 cutover კრიტიკული იყო, გავიდა chunked).