update docs
This commit is contained in:
parent
2916e49973
commit
c6c6276fe6
292
ARCHITECTURE.md
292
ARCHITECTURE.md
|
|
@ -1,27 +1,28 @@
|
|||
# System Architecture Overview
|
||||
# Обзор архитектуры системы
|
||||
|
||||
This document is the single source of truth for the platform’s architecture, protocols, data flows, and operational details. It supersedes previous scattered docs.
|
||||
Этот документ — единый и актуальный источник информации по платформе: архитектура, протоколы, данные, конфигурация, сценарии, эксплуатация. Заменяет собой разрозненные и устаревшие документы.
|
||||
|
||||
## Contents
|
||||
- Components & Topology
|
||||
- Decentralized Layer (Membership, Replication, Metrics)
|
||||
- Upload/Conversion Pipeline
|
||||
- Content View & Purchase Flow
|
||||
- API Surface (selected endpoints)
|
||||
- Data Keys & Schemas
|
||||
- Configuration & Defaults
|
||||
- Observability & Metrics
|
||||
- Sequence Diagrams (Mermaid)
|
||||
## Содержание
|
||||
- Компоненты и топология
|
||||
- Децентрализованный слой (членство, оценка размера сети, репликации, метрики)
|
||||
- Загрузка и конвертация контента
|
||||
- Просмотр и покупка контента (UI/UX требования)
|
||||
- API (ключевые эндпойнты и полезная нагрузка)
|
||||
- Ключи и схемы данных (DHT)
|
||||
- Конфигурация и значения по умолчанию
|
||||
- Наблюдаемость и метрики
|
||||
- Диаграммы последовательностей (Mermaid)
|
||||
- Сборка и тестирование
|
||||
|
||||
---
|
||||
|
||||
## Components & Topology
|
||||
## Компоненты и топология
|
||||
|
||||
- Backend API: Sanic-based service (Telegram bots embedded) with PostgreSQL (SQLAlchemy + Alembic).
|
||||
- Storage: Local FS for uploaded/derived data; IPFS used for discovery/pinning; tusd for resumable uploads.
|
||||
- Converter workers: Dockerized ffmpeg pipeline (convert_v3, convert_process) driven by background tasks.
|
||||
- Frontend: Vite + TypeScript client served via nginx container.
|
||||
- Decentralized overlay (in-process DHT): Membership, replication lease management, windowed content metrics.
|
||||
- Backend API: сервис на Sanic (Python) с бота́ми Telegram; база данных PostgreSQL (SQLAlchemy + Alembic).
|
||||
- Хранилище: локальная ФС (uploads/derivatives); IPFS (kubo) для ретривания/пининга; tusd (resumable upload).
|
||||
- Конвертеры: воркеры (ffmpeg) в контейнерах — `convert_v3`, `convert_process`.
|
||||
- Frontend: SPA (Vite + TypeScript), отдается nginx-контейнером.
|
||||
- Децентрализованный слой: встроенный DHT (в процессе) — членство, лизы реплик, метрики контента.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
|
|
@ -29,7 +30,7 @@ flowchart LR
|
|||
Frontend -- REST --> API[Backend API]
|
||||
API -- tus hooks --> tusd
|
||||
API -- SQL --> Postgres
|
||||
API -- IPC --> Workers[Converter Workers]
|
||||
API -- IPC --> Workers[Converters]
|
||||
API -- IPFS --> IPFS
|
||||
API -- DHT --> DHT[(In-Process DHT)]
|
||||
DHT -- CRDT Merge --> DHT
|
||||
|
|
@ -37,183 +38,238 @@ flowchart LR
|
|||
|
||||
---
|
||||
|
||||
## Decentralized Layer
|
||||
## Децентрализованный слой
|
||||
|
||||
### Identity & Versions
|
||||
- NodeID = blake3(Ed25519 public key), ContentID = blake3(encrypted_blob)
|
||||
- schema_version = v1 embedded into DHT keys/records.
|
||||
### Идентификаторы и версии
|
||||
- NodeID = blake3(Ed25519 публичного ключа) — шестнадцатеричная строка (256 бит).
|
||||
- ContentID = blake3(зашифрованного блоба) — неизменяемый идентификатор контента.
|
||||
- schema_version = v1 — фиксируется во всех DHT-ключах/записях.
|
||||
|
||||
### Membership
|
||||
- Signed `/api/v1/network.handshake` with Ed25519; includes:
|
||||
- Node info, capabilities, metrics, IPFS metadata.
|
||||
- reachability_receipts: (issuer, target, ASN, timestamp, signature).
|
||||
- State: LWW-Set for members + receipts, HyperLogLog for population estimate.
|
||||
- Island filtering: nodes with `reachability_ratio < q` are excluded (`k=5`, `q=0.6`, TTL=600s).
|
||||
- N_estimate: `max(valid N_local reports)` across sufficiently reachable peers.
|
||||
### Членство (membership)
|
||||
- Рукопожатие `/api/v1/network.handshake` — запрос подписан Ed25519; верифицируется на стороне получателя. Без корректной подписи — 400 BAD_SIGNATURE.
|
||||
- Полезная нагрузка включает: сведения о ноде (версия, возможности, IPFS), метрики, массив известных публичных нод, квитанции достижимости (reachability_receipts: issuer, target, ASN, timestamp, signature).
|
||||
- Состояние членства — CRDT LWW-Set (добавления/удаления) с TTL (`DHT_MEMBERSHIP_TTL=600` сек), плюс HyperLogLog для оценки мощности (N_local).
|
||||
- Фильтрация «островов»: ноды с `reachability_ratio < q` (по умолчанию `q=0.6`) исключаются при вычислении N_estimate и выборе реплик.
|
||||
- Итоговая оценка `N_estimate = max(валидных N_local от пиров)`.
|
||||
|
||||
### Replication & Leases
|
||||
- Compute prefix `p = max(0, round(log2(N_estimate / R_target)))` with `R_target ≥ 3`.
|
||||
- Responsible nodes: first `p` bits of NodeID equal first `p` bits of ContentID.
|
||||
- Leader = min NodeID among responsible.
|
||||
- Leader maintains `replica_leases` with TTL=600s and diversity: ≥3 IP first octets and ≥3 ASN if available.
|
||||
- Rendezvous ranking: blake3(ContentID || NodeID) for candidate selection.
|
||||
- Heartbeat interval 60s, miss threshold 3 → failover within ≤180s.
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant A as Узел A
|
||||
participant B as Узел B
|
||||
A->>B: POST /network.handshake {nonce, ts, node, receipts, signature}
|
||||
B->>B: верификация ts/nonce, подписи
|
||||
B->>B: upsert member; merge(receipts)
|
||||
B-->>A: {node, known_public_nodes, n_estimate, server_signature}
|
||||
A->>A: merge; N_estimate = max(N_local, полученные)
|
||||
```
|
||||
|
||||
### Metrics (Windowed CRDT)
|
||||
- On view: PN-Counter for views; HyperLogLog for uniques (ViewID = blake3(ContentID || device_salt)); G-Counter for watch_time, bytes_out, completions.
|
||||
- Keys are windowed by hour; commutative merges ensure deterministic convergence.
|
||||
### Репликации и лизы
|
||||
- Выбор префикса: `p = max(0, round(log2(N_estimate / R_target)))`, где `R_target ≥ 3` (по умолчанию 3).
|
||||
- Ответственные ноды: чьи первые `p` бит NodeID совпадают с первыми `p` бит ContentID.
|
||||
- Лидер — минимальный NodeID среди ответственных.
|
||||
- Лидер выдаёт `replica_leases` (TTL=600 сек), соблюдая разнообразие: не менее 3 разных первых октетов IP и, если доступно, 3 разных ASN.
|
||||
- Ранжирование кандидатов — rendezvous score `blake3(ContentID || NodeID)`.
|
||||
- Сердцебиение (heartbeat) держателей — каждые 60 сек; 3 пропуска → признать down и переназначить ≤180 сек.
|
||||
- Недобор/перебор фиксируются в `conflict_log` и прометеус‑метриках.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Discover
|
||||
Discover: Handshake + receipts
|
||||
Discover --> Active: k ASN receipts & TTL ok
|
||||
Active --> Leader: Content prefix p elects min NodeID
|
||||
Leader --> Leased: Assign replica_leases (diversity)
|
||||
Leased --> Monitoring: Heartbeats every 60s
|
||||
Monitoring --> Reassign: Missed 3 intervals
|
||||
Discover: Рукопожатия + квитанции
|
||||
Discover --> Active: TTL & кворм ASN
|
||||
Active --> Leader: Выбор лидера префикса p
|
||||
Leader --> Leased: Выдача лизов (diversity)
|
||||
Leased --> Monitoring: Heartbeat 60s
|
||||
Monitoring --> Reassign: 3 пропуска
|
||||
Reassign --> Leased
|
||||
```
|
||||
|
||||
### Метрики (окна)
|
||||
- На событии просмотра формируются дельты CRDT:
|
||||
- PN‑Counter — количество просмотров;
|
||||
- HyperLogLog — уникальные ViewID (ViewID = blake3(ContentID || соль_устройства));
|
||||
- G‑Counter — watch_time, bytes_out, количество завершений.
|
||||
- Окно по часу (`DHT_METRIC_WINDOW_SEC`), ключ `MetricKey = blake3(ContentID || WindowID)`.
|
||||
- Мерджи коммутативные, детерминированные.
|
||||
|
||||
---
|
||||
|
||||
## Upload & Conversion Pipeline
|
||||
## Загрузка и конвертация контента
|
||||
|
||||
1) Client uploads via `tusd` (resumable). Backend receives hooks (`/api/v1/upload.tus-hook`).
|
||||
2) Encrypted content is registered; converter workers derive preview/low/high (for media) or original (for binaries).
|
||||
3) Derivative metadata stored in DB and surfaced via `/api/v1/content.view`.
|
||||
1) Клиент грузит в `tusd` (resumable). Бэкенд получает HTTP‑hooks `/api/v1/upload.tus-hook`.
|
||||
2) Создается запись в БД для зашифрованного контента, воркеры размещают производные:
|
||||
- для медиа — preview/low/high;
|
||||
- для бинарей — оригинал (доступен только при наличии лицензии).
|
||||
3) `/api/v1/content.view` возвращает `display_options` и агрегированное состояние конвертации/загрузки.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as Client
|
||||
participant C as Клиент
|
||||
participant T as tusd
|
||||
participant B as Backend
|
||||
participant W as Workers
|
||||
participant B as Бэкенд
|
||||
participant W as Воркеры
|
||||
participant DB as PostgreSQL
|
||||
|
||||
C->>T: upload chunks
|
||||
C->>T: upload
|
||||
T->>B: hooks (pre/post-finish)
|
||||
B->>DB: create content record
|
||||
B->>W: enqueue conversion
|
||||
W->>DB: store derivatives
|
||||
B->>DB: create content
|
||||
B->>W: очередь конвертации
|
||||
W->>DB: derive/previews
|
||||
C->>B: GET /content.view
|
||||
B->>DB: resolve latest derivatives
|
||||
B->>DB: resolve derivatives
|
||||
B-->>C: display_options + status
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Content View & Purchase Flow
|
||||
## Просмотр и покупка (UI/UX)
|
||||
|
||||
- `/api/v1/content.view/<content_address>` resolves content and derivatives:
|
||||
- For binary content without previews: present original only when licensed.
|
||||
- For audio/video: use preview/low for unauth; decrypted_low/high for licensed users.
|
||||
- Frontend shows processing state when derivatives are pending.
|
||||
- Purchase options (TON/Stars) remain in a single row (UI constraint).
|
||||
- Cover art layout: fixed square slot; image fits without stretching; background follows page color, not black.
|
||||
- `/api/v1/content.view/<content_address>` определяет доступные отображения:
|
||||
- бинарный контент без превью — оригинал только при наличии лицензии;
|
||||
- аудио/видео — для неавторизованных preview/low, для имеющих доступ — decrypted_low/high.
|
||||
- В процессе конвертации фронтенд показывает статус «processing», без фальшивых ссылок.
|
||||
- Обложка (cover):
|
||||
- фиксированный квадратный слот; изображение «вписывается» без растягивания/искажения;
|
||||
- пустые области не заполняются чёрным — фон совпадает с фоном страницы.
|
||||
- Кнопки «Купить за TON/Stars»: всегда в одной строке (без горизонтального/вертикального скролла контента на малых экранах).
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
View[content.view] --> Resolve[Resolve encrypted/decrypted rows]
|
||||
Resolve --> Derivations{Derivatives ready?}
|
||||
Derivations -- No --> Status[processing/pending]
|
||||
Derivations -- Yes --> Options
|
||||
Options -- Binary + No License --> Original hidden
|
||||
Options -- Media + No License --> Preview/Low
|
||||
Options -- Licensed --> Decrypted Low/High or Original
|
||||
View[content.view] --> Resolve[Определение деривативов]
|
||||
Resolve --> Ready{Готово?}
|
||||
Ready -- Нет --> Info[Статус: processing/pending]
|
||||
Ready -- Да --> Options
|
||||
Options -- Бинарь + нет лицензии --> HideOriginal[Скрыть оригинал]
|
||||
Options -- Медиа + нет лицензии --> PreviewLow[preview/low]
|
||||
Options -- Есть лицензия --> Decrypted[decrypted low/high|original]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Selected APIs
|
||||
## API (ключевые)
|
||||
|
||||
- `GET /api/system.version` – liveness/protocol version.
|
||||
- `POST /api/v1/network.handshake` – signed membership exchange.
|
||||
- `GET /api/v1/content.view/<content_address>` – resolves display options, status, and downloadability.
|
||||
- `GET /api/v1.5/storage/<file_hash>` – static file access.
|
||||
- `POST /api/v1/storage` – legacy upload endpoint.
|
||||
- `GET /api/system.version` — актуальность сервиса.
|
||||
- `POST /api/v1/network.handshake` — обмен членством (обязательная Ed25519‑подпись запроса). Пример запроса:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "3.0.0",
|
||||
"schema_version": "v1",
|
||||
"public_key": "<base58 ed25519 pubkey>",
|
||||
"node_id": "<blake3(pubkey)>",
|
||||
"public_host": "https://node.example",
|
||||
"node_type": "public|private",
|
||||
"metrics": {"uptime_sec": 123, "content_count": 42},
|
||||
"capabilities": {"accepts_inbound": true, "is_bootstrap": false},
|
||||
"ipfs": {"multiaddrs": ["/ip4/.../tcp/4001"], "peer_id": "..."},
|
||||
"known_public_nodes": [],
|
||||
"reachability_receipts": [],
|
||||
"timestamp": 1710000000,
|
||||
"nonce": "<hex>",
|
||||
"signature": "<base58 ed25519 signature>"
|
||||
}
|
||||
```
|
||||
|
||||
- `GET /api/v1/content.view/<content_address>` — `display_options`, `status`, `conversion`.
|
||||
- `GET /api/v1.5/storage/<file_hash>` — отдача файла.
|
||||
- `GET /metrics` — экспозиция метрик Prometheus (либо fallback‑дамп счётчиков).
|
||||
|
||||
---
|
||||
|
||||
## Data Keys & Schemas
|
||||
## Ключи и схемы DHT
|
||||
|
||||
- MetaKey(content_id): tracks `replica_leases`, `leader`, `conflict_log`, `revision`.
|
||||
- MembershipKey(node_id): LWW-Set of members & receipts, HyperLogLog population, N_reports.
|
||||
- MetricKey(content_id, window_id): PN-/G-/HLL serialized state.
|
||||
- `MetaKey(content_id)` — метаданные репликаций:
|
||||
- `replica_leases`: карта `{lease_id -> {node_id, issued_at, expires_at, asn, ip_first_octet, heartbeat_at, score}}`;
|
||||
- `leader`: NodeID лидера; `revision`: номер ревизии;
|
||||
- `conflict_log`: массив событий `UNDER/OVER/LEASE_EXPIRED` и т.п.
|
||||
|
||||
All DHT records are signed and merged via deterministic CRDT strategies + LWW dominance (logical_counter, timestamp, node_id).
|
||||
- `MembershipKey(node_id)` — членство:
|
||||
- `members`: LWW‑Set; `receipts`: LWW‑Set;
|
||||
- `hll`: HyperLogLog; `reports`: карты локальных оценок N;
|
||||
- `logical_counter`: логический счётчик для LWW‑доминации.
|
||||
|
||||
- `MetricKey(content_id, window_id)` — метрики окна:
|
||||
- `views`: PN‑Counter; `unique`: HLL; `watch_time`, `bytes_out`, `completions`: G‑Counters.
|
||||
|
||||
Все записи подписываются и сливаются детерминированно: CRDT‑логика + LWW‑доминация (`logical_counter`, `timestamp`, `node_id`).
|
||||
|
||||
---
|
||||
|
||||
## Configuration & Defaults
|
||||
## Конфигурация и значения по умолчанию
|
||||
|
||||
- Network: `NODE_PRIVACY`, `PUBLIC_HOST`, `HANDSHAKE_INTERVAL_SEC`, TLS verify, IPFS peering.
|
||||
- DHT: `DHT_MIN_RECEIPTS=5`, `DHT_MIN_REACHABILITY=0.6`, `DHT_MEMBERSHIP_TTL=600`, `DHT_REPLICATION_TARGET=3`, `DHT_LEASE_TTL=600`, `DHT_HEARTBEAT_INTERVAL=60`, `DHT_HEARTBEAT_MISS_THRESHOLD=3`, `DHT_MIN_ASN=3`, `DHT_MIN_IP_OCTETS=3`, `DHT_METRIC_WINDOW_SEC=3600`.
|
||||
- Conversion resources: `CONVERT_*` limits (CPU/mem), `MAX_CONTENT_SIZE_MB`.
|
||||
- Сеть/рукопожатия: `NODE_PRIVACY`, `PUBLIC_HOST`, `HANDSHAKE_INTERVAL_SEC`, `NETWORK_TLS_VERIFY`, IPFS‑пиры/бустрапы.
|
||||
- DHT:
|
||||
- `DHT_MIN_RECEIPTS=5`, `DHT_MIN_REACHABILITY=0.6`, `DHT_MEMBERSHIP_TTL=600`;
|
||||
- `DHT_REPLICATION_TARGET=3`, `DHT_LEASE_TTL=600`,
|
||||
- `DHT_HEARTBEAT_INTERVAL=60`, `DHT_HEARTBEAT_MISS_THRESHOLD=3`;
|
||||
- `DHT_MIN_ASN=3`, `DHT_MIN_IP_OCTETS=3`,
|
||||
- `DHT_METRIC_WINDOW_SEC=3600`.
|
||||
- Конвертация: квоты `CONVERT_*`, `MAX_CONTENT_SIZE_MB`.
|
||||
|
||||
Примечание: PoW‑допуски и Kademlia k‑buckets на текущем этапе не активированы в коде — заложены в дизайн и могут быть реализованы отдельно.
|
||||
|
||||
---
|
||||
|
||||
## Observability & Metrics
|
||||
## Наблюдаемость и метрики
|
||||
|
||||
Prometheus (exported in-process):
|
||||
- dht_replication_under / dht_replication_over / dht_leader_changes_total
|
||||
- dht_merge_conflicts_total
|
||||
- dht_view_count_total / dht_unique_view_estimate / dht_watch_time_seconds
|
||||
Prometheus:
|
||||
- `dht_replication_under_total`, `dht_replication_over_total`, `dht_leader_changes_total`;
|
||||
- `dht_merge_conflicts_total`;
|
||||
- `dht_view_count_total`, `dht_unique_view_estimate`, `dht_watch_time_seconds`.
|
||||
|
||||
Logs track replication conflict_log entries and HTTP structured errors (with session_id/error_id).
|
||||
Логи: структурированные ошибки HTTP (с id), `conflict_log` по репликациям, события регистрации нод.
|
||||
|
||||
---
|
||||
|
||||
## Sequence Diagrams (Consolidated)
|
||||
## Диаграммы последовательностей (сводные)
|
||||
|
||||
### Membership & N_estimate
|
||||
### Обновление N_estimate
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant A as Node A
|
||||
participant B as Node B
|
||||
A->>B: POST /network.handshake {nonce, ts, signature}
|
||||
B->>B: verify ts, nonce, signature
|
||||
B->>B: upsert member; store receipts
|
||||
B-->>A: {node, known_public_nodes, n_estimate, signature}
|
||||
A->>A: merge; recompute N_estimate = max(N_local, peers)
|
||||
participant Peer
|
||||
participant Membership
|
||||
participant DHT
|
||||
Peer->>Membership: handshake(payload, receipts)
|
||||
Membership->>Membership: merge LWW/receipts
|
||||
Membership->>Membership: update HLL и N_local
|
||||
Membership->>DHT: persist MembershipKey
|
||||
Membership->>Membership: N_estimate = max(valid reports)
|
||||
```
|
||||
|
||||
### Replication Leader Election
|
||||
### Выбор лидера и выдача лизов
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant L as Leader
|
||||
participant Peers as Responsible Nodes
|
||||
L->>L: compute p from N_estimate
|
||||
L->>Peers: rendezvous scores for ContentID
|
||||
participant R as Responsible
|
||||
L->>L: p = round(log2(N_est/R))
|
||||
L->>R: rank by rendezvous(ContentID, NodeID)
|
||||
L->>L: assign leases (diversity)
|
||||
Peers-->>L: heartbeat every 60s
|
||||
L->>L: reassign on 3 misses (≤180s)
|
||||
R-->>L: heartbeat/60s
|
||||
L->>L: reassign on 3 misses
|
||||
```
|
||||
|
||||
### Metrics Publication
|
||||
### Публикация метрик окна
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as Client
|
||||
participant API as Backend
|
||||
participant M as MetricsAggregator
|
||||
participant M as Metrics
|
||||
participant D as DHT
|
||||
|
||||
C->>API: GET content.view?watch_time&bytes_out
|
||||
C->>API: GET content.view?watch_time,bytes_out
|
||||
API->>M: record_view(delta)
|
||||
M->>D: merge MetricKey(ContentID, Window)
|
||||
M->>API: update gauges
|
||||
M->>D: merge MetricKey(ContentID, window)
|
||||
API-->>Prom: /metrics
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Run & Test
|
||||
## Сборка и тестирование
|
||||
|
||||
```bash
|
||||
# Spin services
|
||||
# Старт окружения (пример для /home/configs)
|
||||
docker compose -f /home/configs/docker-compose.yml --env-file /home/configs/.env up -d --build
|
||||
|
||||
# Backend unit tests (DHT integration)
|
||||
# Тесты слоя DHT
|
||||
cd uploader-bot
|
||||
python3 -m unittest discover -s tests/dht
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# Sanic Telegram Bot [template]
|
||||
|
||||
See the consolidated system design with protocol, flows, configuration, and diagrams in `ARCHITECTURE.md`.
|
||||
Полная документация по системе (архитектура, протоколы, конфигурация, диаграммы) — см. `ARCHITECTURE.md`.
|
||||
|
||||
### Running DHT integration tests
|
||||
### Запуск тестов интеграции DHT
|
||||
|
||||
```shell
|
||||
cd uploader-bot
|
||||
|
|
|
|||
Loading…
Reference in New Issue