fix: Фикс бага с подключением при первичной регистрации юзера

This commit is contained in:
2026-04-17 23:45:52 +05:00
parent 1a57d8f4d0
commit 7f4684082e
6 changed files with 936 additions and 103 deletions

382
Architecture.md Normal file
View File

@@ -0,0 +1,382 @@
# Rosetta Android — Architecture
> Документ описывает **текущую** архитектуру `rosetta-android` (ветка `dev`) по коду, без идеализаций.
## 1. Архитектурный стиль
Приложение построено как **layered + feature-oriented** архитектура:
- UI на Jetpack Compose (`MainActivity` + `ui/*`).
- Бизнес-оркестрация в singleton-сервисах (`ProtocolManager`, `CallManager`, `TransportManager`, `UpdateManager`).
- Data слой через репозитории (`MessageRepository`, `GroupRepository`, `AvatarRepository`, `AccountManager`).
- Persistence через Room (`RosettaDatabase`).
- Crypto изолирован в `crypto/*`.
DI-контейнера (Hilt/Koin) сейчас нет: зависимости поднимаются через `object`, `getInstance(...)`, singleton-инициализацию.
---
## 2. Слои и границы
```mermaid
flowchart TB
subgraph UI["UI Layer (Compose + ViewModel)"]
A1["MainActivity"]
A2["ui/chats/*"]
A3["ui/auth/*"]
A4["ui/settings/*"]
end
subgraph SVC["Service Layer (Singleton orchestrators)"]
B1["ProtocolManager"]
B2["CallManager"]
B3["TransportManager"]
B4["UpdateManager"]
B5["RosettaFirebaseMessagingService"]
end
subgraph DATA["Data Layer"]
C1["MessageRepository"]
C2["GroupRepository"]
C3["AvatarRepository"]
C4["AccountManager / PreferencesManager"]
C5["DraftManager / ForwardManager"]
end
subgraph DB["Persistence Layer"]
D1["Room: RosettaDatabase"]
D2["DAO: message/dialog/group/etc"]
end
subgraph NET["Network Layer"]
E1["Protocol (WebSocket)"]
E2["Packet* codec"]
E3["OkHttp HTTP (transport/update)"]
E4["WebRTC"]
end
subgraph CRYPTO["Crypto Layer"]
F1["CryptoManager"]
F2["MessageCrypto"]
F3["XChaCha20E2EE (calls)"]
end
UI --> SVC
UI --> DATA
SVC --> DATA
SVC --> NET
DATA --> DB
DATA --> CRYPTO
SVC --> CRYPTO
```
---
## 3. Главные модули и ответственность
### 3.1 `MainActivity` (composition root)
`MainActivity` — главный orchestration entrypoint приложения:
- поднимает `ProtocolManager.initialize(...)`, `CallManager.initialize(...)`;
- управляет auth-гейтингом, онбордингом и основным nav-stack (`Screen`);
- привязывает текущий аккаунт к runtime-сервисам;
- триггерит fast reconnect на `onResume`;
- следит за разрешениями (уведомления, fullscreen intent и т.д.).
### 3.2 `RosettaApplication`
На старте процесса инициализирует глобальные подсистемы:
- crash reporting,
- draft manager,
- transport manager,
- update manager.
### 3.3 Репозитории
#### `MessageRepository`
Ключевой data-центр для чатов:
- инициализация аккаунт-контекста (`publicKey/privateKey`);
- отправка сообщений (optimistic insert + сетевой send);
- обработка входящих `PacketMessage`/`PacketDelivery`/`PacketRead`;
- обновление `dialogs`, `messages`, `message_search_index`;
- синк timestamp (`accounts_sync_times`);
- шина событий для UI (`newMessageEvents`, `deliveryStatusEvents`).
#### `GroupRepository`
- хранение и операции по группам,
- интеграция с `PacketGroup*`.
#### `AvatarRepository`
- кэш/история аватаров (Room + file storage),
- реактивная выдача аватаров через `Flow`.
#### `AccountManager`
- хранение аккаунтов в DataStore,
- last logged public/private hash в SharedPreferences для быстрых синхронных чтений.
---
## 4. Сетевой стек
## 4.1 `Protocol` (низкий уровень)
`Protocol` отвечает за:
- WebSocket lifecycle (`DISCONNECTED/CONNECTING/CONNECTED/HANDSHAKING/DEVICE_VERIFICATION_REQUIRED/AUTHENTICATED`),
- heartbeat,
- reconnect/backoff,
- packet encode/decode,
- `waitPacket/unwaitPacket` обработчики,
- queue pre-handshake пакетов.
Ключевые механизмы устойчивости:
- `lifecycleMutex` для serialized lifecycle операций,
- `connectionGeneration` для игнора stale callbacks старых сокетов,
- guard `isConnecting` от параллельного `connect()`.
## 4.2 `ProtocolManager` (верхний уровень)
`ProtocolManager` — orchestration-слой над `Protocol`:
- единая точка для UI/Data слоёв (`send`, `authenticate`, `reconnect`, `waitPacket` и т.д.);
- bootstrap после auth (sync, own-profile resolve, push subscribe);
- маршрутизация входящих packet-ов в репозитории/подсистемы;
- call signaling bridge для `CallManager`;
- управление typed caches (`SearchUser`, user info cache).
Новый runtime-дизайн connection orchestration:
- `ProtocolConnectionModels.kt``ConnectionLifecycleState`, `ConnectionEvent`, bootstrap context;
- `ProtocolConnectionSupervisor.kt` — actor/event-loop для serialized событий;
- `ReadyPacketGate.kt` — очередь пакетов до состояния `READY` (TTL + max size).
---
## 5. Lifecycle состояния соединения (верхний уровень)
`ProtocolManager.connectionLifecycleState`:
- `DISCONNECTED`
- `CONNECTING`
- `HANDSHAKING`
- `AUTHENTICATED`
- `BOOTSTRAPPING`
- `READY`
- `DEVICE_VERIFICATION_REQUIRED`
Переход в `READY` происходит только когда одновременно выполнено:
- аккаунт инициализирован,
- протокол аутентифицирован,
- sync завершён,
- own-profile резолвнут (или истёк fallback timeout).
```mermaid
stateDiagram-v2
[*] --> DISCONNECTED
DISCONNECTED --> CONNECTING
CONNECTING --> HANDSHAKING
HANDSHAKING --> DEVICE_VERIFICATION_REQUIRED
HANDSHAKING --> AUTHENTICATED
AUTHENTICATED --> BOOTSTRAPPING
BOOTSTRAPPING --> READY
READY --> DISCONNECTED
DEVICE_VERIFICATION_REQUIRED --> CONNECTING
```
---
## 6. Поток auth / session bootstrap
```mermaid
sequenceDiagram
participant UI as AuthFlow/MainActivity
participant PM as ProtocolManager
participant P as Protocol
participant MR as MessageRepository
UI->>PM: initializeAccount(public, private)
UI->>PM: connect()
UI->>PM: authenticate(public, privateHash)
PM->>P: connect + startHandshake
P-->>PM: AUTHENTICATED
PM->>PM: onAuthenticated()
PM->>PM: subscribePushTokenIfAvailable()
PM->>PM: requestSynchronize()
PM->>MR: initialize(...)
PM-->>PM: SyncCompleted + OwnProfileResolved
PM-->>UI: connectionLifecycleState = READY
```
Критично: отправка пользовательских пакетов до `READY` не теряется, а попадает в `ReadyPacketGate`.
---
## 7. Поток сообщений (send/receive/delivery)
## 7.1 Отправка
1. UI (`ChatViewModel`) вызывает отправку через `MessageRepository.sendMessage(...)`.
2. Репозиторий делает optimistic insert в `messages` (`WAITING`).
3. Формируется `PacketMessage`.
4. Отправка идёт в `ProtocolManager.send(...)`.
5. Если состояние не `READY`, пакет ставится в `ReadyPacketGate`.
6. После `READY` очередь сбрасывается в `Protocol.sendPacket(...)`.
## 7.2 Подтверждение доставки
1. Сервер присылает `PacketDelivery (0x08)`.
2. `ProtocolManager` маршрутизирует в `MessageRepository.handleDelivery(...)`.
3. Репозиторий обновляет статус в Room.
4. UI получает апдейт через `Flow`/события.
## 7.3 Входящие
1. `PacketMessage (0x06)` приходит в `Protocol`.
2. `ProtocolManager` dispatch → `MessageRepository.handleIncomingMessage(...)`.
3. Сообщение сохраняется в Room, обновляется `dialogs` и индексы поиска.
4. UI реактивно перерисовывается.
---
## 8. Sync-пайплайн
Используется пакет `PacketSync (0x19)` и режимы:
- `BATCH_START`
- поток синк-пакетов (`MESSAGE/READ/DELIVERY/...`)
- `BATCH_END`
- `NOT_NEEDED`
Особенности:
- есть последовательная очередь inbound задач для сохранения порядка обработки;
- after-sync hooks: retry waiting messages, request missing user info;
- sync timestamp хранится в `accounts_sync_times`.
---
## 9. Calls (WebRTC + signaling)
`CallManager` использует:
- signaling пакеты: `PacketSignalPeer (0x1A)`, `PacketWebRTC (0x1B)`;
- ICE: `PacketIceServers (0x1C)`;
- WebRTC stack (`PeerConnectionFactory`, `PeerConnection`, audio track);
- E2EE голоса через `XChaCha20E2EE` обвязки sender/receiver.
Основные фазы звонка:
- `IDLE``INCOMING`/`OUTGOING``CONNECTING``ACTIVE``IDLE`.
```mermaid
stateDiagram-v2
[*] --> IDLE
IDLE --> OUTGOING
IDLE --> INCOMING
OUTGOING --> CONNECTING
INCOMING --> CONNECTING
CONNECTING --> ACTIVE
ACTIVE --> IDLE
OUTGOING --> IDLE
INCOMING --> IDLE
```
---
## 10. Transport (вложения)
`TransportManager`:
- получает transport server через `PacketRequestTransport (0x0F)` (desktop parity);
- upload/download через OkHttp;
- resumable download (HTTP Range);
- трекает состояния прогресса через `StateFlow` (`uploading`, `downloading`);
- поддерживает cancel/pause/resume через `FileDownloadManager`.
---
## 11. Push Notifications
`RosettaFirebaseMessagingService`:
- обрабатывает `onNewToken` и подписку токена через `ProtocolManager`;
- dedup пушей;
- маршрутизация типов (`personal_message`, `group_message`, `call`, `read`);
- очистка уведомлений по read events;
- wake-up reconnect при silent push.
---
## 12. Обновления (SDU)
`UpdateManager`:
1. запрашивает update server через `PacketRequestUpdate (0x0A)`;
2. ходит на SDU HTTP endpoint;
3. скачивает APK через `DownloadManager`;
4. ведёт update state machine (`Idle/Checking/UpdateAvailable/Downloading/ReadyToInstall/Error`).
---
## 13. Persistence (Room)
`RosettaDatabase` (version `17`) включает:
- `messages` — сообщения,
- `dialogs` — диалоги + денормализованные поля для быстрых списков,
- `message_search_index` — локальный индекс поиска,
- `groups` — группы,
- `pinned_messages` — закрепы,
- `avatar_cache` — аватары,
- `blacklist` — blacklist,
- `accounts_sync_times` — sync cursor,
- `encrypted_accounts` — аккаунты (legacy Room account storage).
Есть длинная цепочка миграций (4→17) с оптимизациями под производительность и денормализацию.
---
## 14. Crypto
- `CryptoManager`:
- seed phrase / keypair,
- PBKDF2-derived key caching,
- encrypt/decrypt для локального хранения.
- `MessageCrypto`:
- message-level XChaCha20-Poly1305,
- ECDH/AES-обмен ключом для payload,
- attachment decrypt logic.
Crypto и network связаны через `MessageRepository`/`ProtocolManager`.
---
## 15. Наблюдаемость и диагностика
- wire/protocol логи через `ProtocolManager.addLog(...)` + trace file;
- debug logs доступны в UI;
- отдельные диагностические логи для звонков (`CallManager` breadcrumbs).
---
## 16. Текущие архитектурные сильные стороны
- Реактивная модель состояния (`StateFlow`) на большинстве критических путей.
- Сильная декомпозиция packet протокола (`Packet*`).
- Наличие ready-gate и serialized supervisor снижает race-condition в соединении.
- Room + денормализация ускоряют списки чатов/поиск.
---
## 17. Текущие архитектурные риски
- `MainActivity` остаётся очень крупным composition root.
- `ProtocolManager` и `MessageRepository` всё ещё крупные “god objects”.
- Отсутствие DI усложняет управляемость зависимостей/тестируемость.
- Часть жизненного цикла связана через runtime singleton state, что повышает риск регрессий при эволюции.
---
## 18. Карта ключевых файлов
- `app/src/main/java/com/rosetta/messenger/MainActivity.kt`
- `app/src/main/java/com/rosetta/messenger/RosettaApplication.kt`
- `app/src/main/java/com/rosetta/messenger/network/Protocol.kt`
- `app/src/main/java/com/rosetta/messenger/network/ProtocolManager.kt`
- `app/src/main/java/com/rosetta/messenger/network/ProtocolConnectionModels.kt`
- `app/src/main/java/com/rosetta/messenger/network/ProtocolConnectionSupervisor.kt`
- `app/src/main/java/com/rosetta/messenger/network/ReadyPacketGate.kt`
- `app/src/main/java/com/rosetta/messenger/network/CallManager.kt`
- `app/src/main/java/com/rosetta/messenger/network/TransportManager.kt`
- `app/src/main/java/com/rosetta/messenger/push/RosettaFirebaseMessagingService.kt`
- `app/src/main/java/com/rosetta/messenger/update/UpdateManager.kt`
- `app/src/main/java/com/rosetta/messenger/data/MessageRepository.kt`
- `app/src/main/java/com/rosetta/messenger/database/RosettaDatabase.kt`
- `app/src/main/java/com/rosetta/messenger/crypto/CryptoManager.kt`
- `app/src/main/java/com/rosetta/messenger/crypto/MessageCrypto.kt`