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