SHA256
196 lines
7.3 KiB
Markdown
196 lines
7.3 KiB
Markdown
# 07. Channels Feature Runbook (человеческое описание + диагностика)
|
||
|
||
## 1) Что уже сделано простыми словами
|
||
|
||
Сейчас реализован полный минимальный контур для каналов:
|
||
|
||
1. **Серверные read API**:
|
||
- `ListSubscriptionsFeed` — экран списка каналов.
|
||
- `GetChannelMessages` — сообщения конкретного канала.
|
||
- `GetMessageThread` — дерево обсуждения для сообщения.
|
||
- `GetMessageLikes` — списки пользователей, поставивших лайк сообщению.
|
||
- `SetChannelReadState` — подписанный watermark чтения канала.
|
||
|
||
2. **UI вкладки Каналы**:
|
||
- при открытии пытается загрузить реальный feed с сервера;
|
||
- если сервер недоступен — fallback на мок-данные;
|
||
- группы каналов выводятся в нужном порядке;
|
||
- есть кнопка «Добавить канал», модалки подписки, переход в канал.
|
||
|
||
3. **Проверка уникальности имени канала на сервере**
|
||
- в `AddBlock` при `CreateChannelBody` добавлена проверка;
|
||
- при дубле возвращается `409 channel_name_already_exists`.
|
||
|
||
---
|
||
|
||
## 2) Что тестировать в первую очередь (быстрый чеклист)
|
||
|
||
### Базовый smoke
|
||
1. Авторизоваться в UI.
|
||
2. Открыть вкладку «Каналы».
|
||
3. Убедиться, что данные загрузились с сервера (или виден fallback-баннер).
|
||
4. Нажать любой канал — должен открыться экран канала с сообщениями.
|
||
|
||
### API smoke
|
||
1. Вызвать `ListSubscriptionsFeed`.
|
||
2. Для канала `ownedChannels[0]` вызвать `GetChannelMessages`.
|
||
3. Для первого `messages[0]` вызвать `GetMessageThread`.
|
||
4. Для первого `messages[0]` вызвать `GetMessageLikes`.
|
||
5. Для подписанного канала вызвать `SetChannelReadState` с текущим `messagesCount`.
|
||
|
||
### Ошибки
|
||
1. `ListSubscriptionsFeed` с пустым login -> `bad_fields`.
|
||
2. `GetChannelMessages` с битым channel payload -> `bad_fields`.
|
||
3. `GetMessageThread` с несуществующим block -> `message_not_found`.
|
||
4. `GetMessageLikes` с битым `message.blockHash` -> `bad_hash`.
|
||
5. `SetChannelReadState` без активной подписки -> `CHANNEL_NOT_FOLLOWED`.
|
||
6. `AddBlock(CreateChannel)` с уже существующим именем -> `channel_name_already_exists`.
|
||
|
||
---
|
||
|
||
## 3) Готовые JSON-запросы для ручной диагностики
|
||
|
||
## 3.1 ListSubscriptionsFeed
|
||
```json
|
||
{
|
||
"op": "ListSubscriptionsFeed",
|
||
"requestId": "debug-feed-1",
|
||
"payload": {
|
||
"login": "TestUser1",
|
||
"limit": 200
|
||
}
|
||
}
|
||
```
|
||
|
||
## 3.2 GetChannelMessages
|
||
```json
|
||
{
|
||
"op": "GetChannelMessages",
|
||
"requestId": "debug-ch-1",
|
||
"payload": {
|
||
"channel": {
|
||
"ownerBlockchainName": "TestUser1-001",
|
||
"channelRootBlockNumber": 0,
|
||
"channelRootBlockHash": ""
|
||
},
|
||
"limit": 200,
|
||
"sort": "asc"
|
||
}
|
||
}
|
||
```
|
||
|
||
## 3.3 GetMessageThread
|
||
```json
|
||
{
|
||
"op": "GetMessageThread",
|
||
"requestId": "debug-thread-1",
|
||
"payload": {
|
||
"message": {
|
||
"blockchainName": "TestUser1-001",
|
||
"blockNumber": 123,
|
||
"blockHash": "<hash-from-GetChannelMessages>"
|
||
},
|
||
"depthUp": 20,
|
||
"depthDown": 2,
|
||
"limitChildrenPerNode": 50
|
||
}
|
||
}
|
||
```
|
||
|
||
## 3.4 GetMessageLikes
|
||
```json
|
||
{
|
||
"op": "GetMessageLikes",
|
||
"requestId": "debug-likes-1",
|
||
"payload": {
|
||
"message": {
|
||
"blockchainName": "TestUser1-001",
|
||
"blockNumber": 123,
|
||
"blockHash": "<hash-from-GetChannelMessages>"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## 3.5 SetChannelReadState
|
||
```json
|
||
{
|
||
"op": "SetChannelReadState",
|
||
"requestId": "debug-read-state-1",
|
||
"payload": {
|
||
"login": "TestUser1",
|
||
"owner_bch_name": "TestUser2-001",
|
||
"channel_name": "news",
|
||
"read_count": 25,
|
||
"time_ms": 1760000000000,
|
||
"client_key": "<base64-client-public-key>",
|
||
"signature": "<base64-ed25519-signature>"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 4) Что смотреть в ответах
|
||
|
||
### ListSubscriptionsFeed
|
||
- `payload.login` — канонический login.
|
||
- `ownedChannels / followedUsersChannels / followedChannels` — массивы.
|
||
- у каждой записи есть:
|
||
- `channel.channelRoot.blockNumber`,
|
||
- `messagesCount`,
|
||
- `unreadCount`,
|
||
- `readStateInitialized`,
|
||
- `lastMessage` (может быть null, если сообщений нет).
|
||
|
||
### GetChannelMessages
|
||
- `payload.channel` заполнен;
|
||
- `payload.messages[]` содержит:
|
||
- `likesCount`, `repliesCount`,
|
||
- `versionsTotal`, `versions[]`,
|
||
- `text` должен быть текущей (последней) версией.
|
||
|
||
### GetMessageThread
|
||
- `payload.ancestors[]`, `payload.focus`, `payload.descendants[]`.
|
||
- у узлов должны быть версии и счетчики.
|
||
- у каждого узла дополнительно может приходить `rawBlockB64` (Base64 сырого `block_bytes`).
|
||
|
||
### GetMessageLikes
|
||
- `payload.shining[]`, `payload.official[]`, `payload.others[]` — группы пользователей.
|
||
- у каждого пользователя есть `login`, `firstName`, `lastName`, `avatarAr`.
|
||
- `payload.truncated` сейчас всегда `false`; поле оставлено для совместимости и будущей пагинации.
|
||
|
||
### SetChannelReadState
|
||
- `payload.read_count` — сохраненная позиция чтения.
|
||
- `payload.unread_count` — пересчитанный unread для канала.
|
||
- `payload.applied=false` означает, что на сервере уже была более новая signed-позиция.
|
||
|
||
### Важно по совместимости
|
||
- `rawBlockB64` добавлен только в `GetMessageThread`.
|
||
- `GetChannelMessages` не содержит `rawBlockB64` (без изменений формата ленты).
|
||
|
||
---
|
||
|
||
## 5) Частые проблемы и как быстро локализовать
|
||
|
||
1. **`status != 200`, code=bad_fields**
|
||
- проверить вложенность payload и обязательные поля.
|
||
|
||
2. **`message_not_found` в GetMessageThread**
|
||
- обычно передали blockNumber/hash не из `messageRef`.
|
||
|
||
3. **Пустой список сообщений в GetChannelMessages**
|
||
- проверить `ownerBlockchainName` и `channelRootBlockNumber`.
|
||
|
||
4. **`channel_name_already_exists` при AddBlock**
|
||
- это ожидаемо: в этой цепочке уже есть канал с таким именем.
|
||
|
||
---
|
||
|
||
## 6) Для будущей доработки
|
||
|
||
1. Добавить курсоры (пагинацию) для больших каналов.
|
||
2. Перевести «Подписаться»/«Добавить канал» в UI с демо-заглушек на реальные write RPC.
|
||
3. Добавить batch-агрегации для thread/versions (оптимизация).
|
||
4. Добавить полноценные интеграционные тесты на негативные кейсы и нагрузку.
|