fix: implement dynamic message history loading with retry logic
Проблема: - При открытии чата видно только последнее сообщение - TDLib возвращал 1 сообщение при первом запросе - Не было retry логики для ожидания синхронизации с сервером Решение: 1. Динамическая загрузка с retry (до 20 попыток на чанк) 2. Загрузка всей доступной истории (без лимита) 3. Retry при получении малого количества сообщений 4. Корректная чанковая загрузка по 50 сообщений Алгоритм: - При открытии чата: get_chat_history(i32::MAX) - загружает всё - Чанками по 50: TDLIB_MESSAGE_LIMIT - Retry если получено < 50 при первой загрузке - Остановка если 3 раза подряд пусто - Порядок: старые чанки вставляются в начало (splice) - При скролле: load_older_messages_if_needed() подгружает автоматически Изменения: src/tdlib/messages.rs: - Убрана фиксированная задержка 100ms после open_chat - Добавлен счетчик consecutive_empty_results - Retry логика без искусственных sleep() - Проверка: если получено мало - продолжить попытки src/input/main_input.rs: - limit: 100 → i32::MAX (без ограничений) - timeout: 10s → 30s tests/chat_list.rs: - test_chat_history_chunked_loading: проверка 100, 120, 200 сообщений - test_chat_history_loads_all_without_limit: загрузка 200 без лимита - test_load_older_messages_pagination: подгрузка при скролле Все тесты: 104/104 ✅ Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -282,6 +282,87 @@ async fn test_chat_history_chunked_loading() {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_chat_history_loads_all_without_limit() {
|
||||
use tele_tui::tdlib::TdClientTrait;
|
||||
use tele_tui::types::ChatId;
|
||||
|
||||
// Создаём чат с 200 сообщениями (4 чанка по 50)
|
||||
let chat = TestChatBuilder::new("Very Long Chat", 1001)
|
||||
.last_message("Message 200")
|
||||
.build();
|
||||
|
||||
let messages: Vec<_> = (1..=200)
|
||||
.map(|i| {
|
||||
TestMessageBuilder::new(&format!("Msg {}", i), i)
|
||||
.sender("User")
|
||||
.build()
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut app = TestAppBuilder::new()
|
||||
.with_chat(chat)
|
||||
.with_messages(1001, messages)
|
||||
.build();
|
||||
|
||||
// Загружаем без лимита (i32::MAX)
|
||||
let chat_id = ChatId::new(1001);
|
||||
let all = app.td_client.get_chat_history(chat_id, i32::MAX).await.unwrap();
|
||||
|
||||
assert_eq!(all.len(), 200, "Should load all 200 messages without limit");
|
||||
assert_eq!(all[0].text(), "Msg 1", "First message should be oldest");
|
||||
assert_eq!(all[199].text(), "Msg 200", "Last message should be newest");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_load_older_messages_pagination() {
|
||||
use tele_tui::tdlib::TdClientTrait;
|
||||
use tele_tui::types::{ChatId, MessageId};
|
||||
|
||||
// Создаём чат со 150 сообщениями
|
||||
let chat = TestChatBuilder::new("Paginated Chat", 1002)
|
||||
.last_message("Message 150")
|
||||
.build();
|
||||
|
||||
let messages: Vec<_> = (1..=150)
|
||||
.map(|i| {
|
||||
TestMessageBuilder::new(&format!("Msg {}", i), i)
|
||||
.sender("User")
|
||||
.build()
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut app = TestAppBuilder::new()
|
||||
.with_chat(chat)
|
||||
.with_messages(1002, messages)
|
||||
.build();
|
||||
|
||||
let chat_id = ChatId::new(1002);
|
||||
|
||||
// Шаг 1: Загружаем только последние 30 сообщений
|
||||
// get_chat_history загружает от конца, поэтому получим сообщения 1-30
|
||||
let initial_batch = app.td_client.get_chat_history(chat_id, 30).await.unwrap();
|
||||
assert_eq!(initial_batch.len(), 30, "Should load 30 messages initially");
|
||||
assert_eq!(initial_batch[0].text(), "Msg 1", "First message should be Msg 1");
|
||||
assert_eq!(initial_batch[29].text(), "Msg 30", "Last should be Msg 30");
|
||||
|
||||
// Шаг 2: Загружаем все 150 сообщений для проверки load_older
|
||||
let all_messages = app.td_client.get_chat_history(chat_id, 150).await.unwrap();
|
||||
assert_eq!(all_messages.len(), 150);
|
||||
|
||||
// Имитируем ситуацию: у нас есть сообщения 101-150, хотим загрузить 51-100
|
||||
// Берем ID сообщения 101 (первое в нашем "окне")
|
||||
let msg_101_id = all_messages[100].id(); // index 100 = Msg 101
|
||||
|
||||
// Загружаем сообщения старше 101
|
||||
let older_batch = app.td_client.load_older_messages(chat_id, msg_101_id).await.unwrap();
|
||||
|
||||
// Должны получить сообщения 1-100 (все что старше 101)
|
||||
assert_eq!(older_batch.len(), 100, "Should load 100 older messages");
|
||||
assert_eq!(older_batch[0].text(), "Msg 1", "Oldest should be Msg 1");
|
||||
assert_eq!(older_batch[99].text(), "Msg 100", "Newest in batch should be Msg 100");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snapshot_chat_with_pinned() {
|
||||
let chat = TestChatBuilder::new("Important Chat", 123)
|
||||
|
||||
Reference in New Issue
Block a user