Рефакторинг network-runtime: выделены ProtocolRuntimeCore, DeviceRuntimeService и OutgoingMessagePipelineService

This commit is contained in:
2026-04-18 20:42:19 +05:00
parent aa0fa3fdb1
commit 15bca1ec34
44 changed files with 2887 additions and 2221 deletions

View File

@@ -7,12 +7,14 @@
Приложение сейчас устроено как layered + service-oriented архитектура:
- UI: `MainActivity` + Compose-экраны + ViewModel.
- DI: Hilt (`@HiltAndroidApp`, `@AndroidEntryPoint`, модули в `di/AppContainer.kt`).
- Runtime orchestration: `ProtocolManager`, `CallManager`, `TransportManager`, `UpdateManager`.
- Runtime orchestration: `ProtocolRuntime` -> `ProtocolRuntimeCore` (+ compatibility facade `ProtocolManager`), `CallManager`, `TransportManager`, `UpdateManager`.
- Session/Identity runtime state: `SessionStore`, `SessionReducer`, `IdentityStore`.
- Data: `MessageRepository`, `GroupRepository`, `AccountManager`, `PreferencesManager`.
- Persistence: Room (`RosettaDatabase`) + DataStore/SharedPreferences.
`ProtocolManager` остается крупным runtime orchestrator-объектом, но критичные зоны уже вынесены в отдельные сервисы.
Основная runtime-логика сети вынесена в instance-класс `ProtocolRuntimeCore`.
`ProtocolManager` сохранен как тонкий compatibility facade.
DI-вход в network core идет через `ProtocolRuntime` (Hilt singleton).
---
@@ -29,11 +31,12 @@ flowchart TB
subgraph DI["Hilt Singleton Graph"]
D1["ProtocolGateway"]
D1A["ProtocolRuntime"]
D2["SessionCoordinator"]
D3["IdentityGateway"]
D4["AccountManager / PreferencesManager"]
D5["MessageRepository / GroupRepository"]
D6["UiEntryPoint + UiDependencyAccess"]
D6["UiEntryPoint + EntryPointAccessors"]
end
subgraph SESSION["Session / Identity Runtime"]
@@ -44,7 +47,9 @@ flowchart TB
end
subgraph NET["Network Runtime"]
N1["ProtocolManager"]
N0["ProtocolRuntime"]
N1["ProtocolRuntimeCore"]
N1A["ProtocolManager (compat facade)"]
N2["Protocol"]
N3["PacketSubscriptionRegistry"]
N4["ReadyPacketGate"]
@@ -60,6 +65,9 @@ flowchart TB
DI --> SESSION
DI --> NET
DI --> DATA
D1 --> D1A
D1A --> N1
N1A --> N1
SESSION --> NET
DATA --> NET
DATA --> R3
@@ -75,11 +83,26 @@ flowchart TB
- Entry points уровня Android-компонентов: `MainActivity`, `IncomingCallActivity`, `CallForegroundService`, `RosettaFirebaseMessagingService`.
- Основные модули:
- `AppDataModule`: `AccountManager`, `PreferencesManager`.
- `AppGatewayModule`: биндинги `ProtocolGateway`, `SessionCoordinator`, `IdentityGateway`.
- `AppGatewayModule`: биндинги `ProtocolGateway`, `SessionCoordinator`, `IdentityGateway`, `ProtocolClient`.
- `ProtocolGatewayImpl` и `ProtocolClientImpl` делегируют в `ProtocolRuntime`, а не напрямую в UI-слой.
### 3.2 UI bridge для не-Hilt классов
Часть UI/VM пока получает зависимости через `UiDependencyAccess` -> `UiEntryPoint`.
Это transitional-слой, чтобы не тащить singleton `getInstance(...)` в UI и постепенно перейти на чистый constructor injection.
### 3.2 UI bridge для composable-слоя
UI-композаблы получают зависимости через `UiEntryPoint` + `EntryPointAccessors.fromApplication(...)`.
`UiDependencyAccess.get(...)` из `ui/*` удален (DoD: 0 вхождений).
Для non-Hilt `object`-ов (`CallManager`, `TransportManager`, `UpdateManager`, utils)
используется `ProtocolRuntimeAccess` + `ProtocolRuntimePort`:
- runtime ставится в `RosettaApplication` через `ProtocolRuntimeAccess.install(protocolRuntime)`;
- доступ до install запрещен (fail-fast), чтобы не было тихого отката в `ProtocolManager`.
### 3.3 Разрыв DI-cycle (Hilt)
После перехода на `ProtocolRuntime` был закрыт цикл зависимостей:
`MessageRepository -> ProtocolClient -> ProtocolRuntime -> MessageRepository`.
Текущее решение:
- `ProtocolClientImpl` получает `Provider<ProtocolRuntime>` (ленивая резолюция).
- `ProtocolRuntime` остается singleton-композицией для `MessageRepository/GroupRepository/AccountManager`.
- На `assembleDebug/assembleRelease` больше нет `Dagger/DependencyCycle`.
---
@@ -129,21 +152,36 @@ stateDiagram-v2
## 5. Network orchestration после декомпозиции
`ProtocolManager` теперь делегирует отдельные зоны ответственности:
`ProtocolRuntime` — DI-фасад runtime слоя.
`ProtocolRuntimeCore` содержит runtime state machine и делегирует отдельные зоны ответственности:
- `ConnectionOrchestrator`: connect/reconnect/authenticate + network-aware поведение.
- `BootstrapCoordinator`: пересчет lifecycle (`AUTHENTICATED`/`BOOTSTRAPPING`/`READY`) и работа с `ReadyPacketGate`.
- `SyncCoordinator`: sync state machine (request/timeout, BATCH_START/BATCH_END/NOT_NEEDED, foreground/manual sync).
- `PresenceTypingService`: in-memory typing presence с TTL и snapshot `StateFlow`.
- `PacketRouter`: user/search cache + resolve/search continuation routing.
- `OwnProfileSyncService`: применение собственного профиля из search и синхронизация `IdentityStore`.
- `RetryQueueService`: retry очереди отправки `PacketMessage`.
- `AuthBootstrapCoordinator`: session-aware post-auth bootstrap (transport/update/profile/sync/push).
- `NetworkReconnectWatcher`: единый watcher ожидания сети и fast-reconnect триггеры.
- `DeviceVerificationService`: состояние списка устройств + pending verification + resolve packets.
- `DeviceRuntimeService`: device-id/handshake device + device verification orchestration.
- `CallSignalBridge`: call/webrtc/ice signal send+subscribe bridge.
- `PacketSubscriptionRegistry`: централизованные подписки на пакеты и fan-out.
- `OutgoingMessagePipelineService`: отправка `PacketMessage` с retry/error policy.
```mermaid
flowchart TB
PM["ProtocolManager"] --> CO["ConnectionOrchestrator"]
PM["ProtocolRuntimeCore"] --> CO["ConnectionOrchestrator"]
PM --> BC["BootstrapCoordinator"]
PM --> SC["SyncCoordinator"]
PM --> PT["PresenceTypingService"]
PM --> PR["PacketRouter"]
PM --> OPS["OwnProfileSyncService"]
PM --> RQ["RetryQueueService"]
PM --> ABC["AuthBootstrapCoordinator"]
PM --> NRW["NetworkReconnectWatcher"]
PM --> DVS["DeviceVerificationService"]
PM --> CSB["CallSignalBridge"]
PM --> PSR["PacketSubscriptionRegistry"]
PM --> SUP["ProtocolConnectionSupervisor"]
PM --> RPG["ReadyPacketGate"]
@@ -163,7 +201,7 @@ flowchart TB
```mermaid
sequenceDiagram
participant Feature as Feature/Service
participant PM as ProtocolManager
participant PM as ProtocolRuntimeCore
participant REG as PacketSubscriptionRegistry
participant P as Protocol
@@ -189,14 +227,14 @@ sequenceDiagram
1. ViewModel готовит command и шифрованный payload.
2. UseCase собирает `PacketMessage`.
3. UseCase вызывает `protocolGateway.sendMessageWithRetry(packet)`.
4. `ProtocolManager` регистрирует пакет в `RetryQueueService` и отправляет в сеть.
4. `ProtocolRuntimeCore` регистрирует пакет в `RetryQueueService` и отправляет в сеть.
5. Если lifecycle еще не `READY`, пакет попадает в `ReadyPacketGate` и flush после `READY`.
```mermaid
flowchart LR
VM["ChatViewModel"] --> UC["Send*UseCase"]
UC --> GW["ProtocolGateway.sendMessageWithRetry"]
GW --> PM["ProtocolManager"]
GW --> PM["ProtocolRuntimeCore"]
PM --> RQ["RetryQueueService"]
PM --> RG["ReadyPacketGate"]
PM --> P["Protocol.sendPacket"]
@@ -212,7 +250,7 @@ sequenceDiagram
participant SC as SessionCoordinatorImpl
participant SS as SessionStore
participant PG as ProtocolGateway
participant PM as ProtocolManager
participant PM as ProtocolRuntimeCore
participant AM as AccountManager
UI->>SC: bootstrapAuthenticatedSession(account, reason)
@@ -235,7 +273,7 @@ sequenceDiagram
## 9. Состояния соединения (network lifecycle)
`ProtocolManager.connectionLifecycleState`:
`ProtocolRuntimeCore.connectionLifecycleState`:
- `DISCONNECTED`
- `CONNECTING`
- `HANDSHAKING`
@@ -263,6 +301,10 @@ stateDiagram-v2
- `app/src/main/java/com/rosetta/messenger/di/AppContainer.kt`
- `app/src/main/java/com/rosetta/messenger/di/UiEntryPoint.kt`
- `app/src/main/java/com/rosetta/messenger/network/ProtocolRuntime.kt`
- `app/src/main/java/com/rosetta/messenger/network/ProtocolRuntimeCore.kt`
- `app/src/main/java/com/rosetta/messenger/network/ProtocolClient.kt`
- `app/src/main/java/com/rosetta/messenger/network/ProtocolRuntimeAccess.kt`
- `app/src/main/java/com/rosetta/messenger/session/AppSessionCoordinator.kt`
- `app/src/main/java/com/rosetta/messenger/session/SessionStore.kt`
- `app/src/main/java/com/rosetta/messenger/session/SessionReducer.kt`
@@ -275,6 +317,14 @@ stateDiagram-v2
- `app/src/main/java/com/rosetta/messenger/network/ReadyPacketGate.kt`
- `app/src/main/java/com/rosetta/messenger/network/connection/ConnectionOrchestrator.kt`
- `app/src/main/java/com/rosetta/messenger/network/connection/BootstrapCoordinator.kt`
- `app/src/main/java/com/rosetta/messenger/network/connection/SyncCoordinator.kt`
- `app/src/main/java/com/rosetta/messenger/network/connection/PresenceTypingService.kt`
- `app/src/main/java/com/rosetta/messenger/network/connection/AuthBootstrapCoordinator.kt`
- `app/src/main/java/com/rosetta/messenger/network/connection/NetworkReconnectWatcher.kt`
- `app/src/main/java/com/rosetta/messenger/network/connection/DeviceVerificationService.kt`
- `app/src/main/java/com/rosetta/messenger/network/connection/DeviceRuntimeService.kt`
- `app/src/main/java/com/rosetta/messenger/network/connection/CallSignalBridge.kt`
- `app/src/main/java/com/rosetta/messenger/network/connection/OutgoingMessagePipelineService.kt`
- `app/src/main/java/com/rosetta/messenger/network/connection/PacketRouter.kt`
- `app/src/main/java/com/rosetta/messenger/network/connection/OwnProfileSyncService.kt`
- `app/src/main/java/com/rosetta/messenger/network/connection/RetryQueueService.kt`
@@ -286,6 +336,7 @@ stateDiagram-v2
## 11. Что осталось как технический долг
- `ProtocolManager` все еще содержит много cross-cutting логики и требует дальнейшей декомпозиции.
- Не весь UI перешел на constructor injection (`UiDependencyAccess` пока нужен для части ViewModel).
- Часть data-слоя напрямую знает о network singleton (`ProtocolManager`) и требует окончательного разрыва через интерфейсы.
- `ProtocolRuntimeCore` все еще содержит много cross-cutting логики и требует дальнейшей декомпозиции.
- UI больше не использует `UiDependencyAccess.get(...)`, но часть экранов все еще берет зависимости через `UiEntryPoint` (следующий шаг: передача зависимостей параметрами/через VM).
- DI-адаптеры (`ProtocolGatewayImpl`, `ProtocolClientImpl`) переведены на `ProtocolRuntime`, dependency-cycle закрыт через `Provider<ProtocolRuntime>`.
- Следующий шаг по network core: продолжить декомпозицию `ProtocolRuntimeCore` (например: `ProtocolLifecycleLogger`, `AuthRestoreService`, `ProtocolTraceService`) и сократить фасад `ProtocolManager` до полного legacy-режима.