From 67739583f3a72eb16c5706e0372770911ef3661e Mon Sep 17 00:00:00 2001 From: Mikhail Kilin Date: Sun, 1 Feb 2026 02:26:03 +0300 Subject: [PATCH] refactor: generalize LruCache to support any key type (P5.16) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made LruCache generic over key type K, not just UserId: - LruCache → LruCache - Added trait bounds: K: Eq + Hash + Clone + Copy - Updated UserCache field types: * user_usernames: LruCache * user_names: LruCache * user_statuses: LruCache Benefits: - Reusable cache implementation for any key types - Type-safe caching - No additional dependencies Progress: Priority 5: 2/3 tasks, Total: 18/20 (90%) Co-Authored-By: Claude Sonnet 4.5 --- CONTEXT.md | 13 +++++++++---- REFACTORING_ROADMAP.md | 23 ++++++++++++++++++++--- src/tdlib/users.rs | 29 +++++++++++++++++------------ 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index 6746988..ab50aa3 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -904,9 +904,9 @@ let message = MessageBuilder::new(MessageId::new(123)) - ✅ Priority 2: 5/5 (100%) - ✅ Priority 3: 4/4 (100%) 🎉 - ✅ Priority 4: 4/4 (100%) 🎉 -- ⏳ Priority 5: 1/3 (33%, P5.15 завершено) +- ⏳ Priority 5: 2/3 (67%, P5.15, P5.16 завершены) -**Общий прогресс: 17/20 задач (85%)** +**Общий прогресс: 18/20 задач (90%)** **Последние изменения (1 февраля 2026)**: - ✅ **P5.15 — Feature flags для зависимостей** (2026-02-01) @@ -915,9 +915,14 @@ let message = MessageBuilder::new(MessageId::new(123)) - Условная компиляция в коде с graceful degradation - Преимущества: уменьшение размера бинарника, модульность +- ✅ **P5.16 — LRU cache обобщение** (2026-02-01) + - Обобщена структура `LruCache` в src/tdlib/users.rs + - Type-safe: `K: Eq + Hash + Clone + Copy`, `V: Clone` + - Обновлены типы в UserCache: `LruCache`, `LruCache` + - Переиспользуемая реализация без дополнительных зависимостей + **Следующие шаги**: -- P5.16: LRU cache обобщение -- P5.17: Tracing вместо println! +- P5.17: Tracing вместо println! (последняя задача Priority 5!) ## Известные проблемы diff --git a/REFACTORING_ROADMAP.md b/REFACTORING_ROADMAP.md index dc59992..5f79b80 100644 --- a/REFACTORING_ROADMAP.md +++ b/REFACTORING_ROADMAP.md @@ -728,12 +728,28 @@ open = { version = "5.0", optional = true } --- -### 16. LRU cache обобщение +### 16. LRU cache обобщение ✅ ЗАВЕРШЕНО **Проблема**: Отдельные LRU кеши для `user_names` и `user_statuses`. **Решение**: Создать обобщённый `LruCache` или использовать готовый крейт `lru = "0.12"`. +**Реализовано**: +- ✅ Обобщённая структура `LruCache` в `src/tdlib/users.rs` +- ✅ Type parameters: + - `K: Eq + Hash + Clone + Copy` — тип ключа + - `V: Clone` — тип значения +- ✅ Обновлена `UserCache`: + - `user_usernames: LruCache` + - `user_names: LruCache` + - `user_statuses: LruCache` +- ✅ Все методы обобщены: `get()`, `peek()`, `insert()`, `contains_key()`, `len()` + +**Преимущества**: +- ✅ Переиспользуемая реализация для любых типов ключей +- ✅ Type-safe кеширование +- ✅ Без дополнительных зависимостей + --- ### 17. Tracing вместо println! @@ -781,10 +797,11 @@ tracing-subscriber = "0.3" - [x] P4.12 — Rustdoc ✅ - [x] P4.13 — Config validation ✅ - [x] P4.14 — Async/await consistency ✅ -- [ ] Priority 5: 1/3 задач +- [ ] Priority 5: 2/3 задач - [x] P5.15 — Feature flags ✅ + - [x] P5.16 — LRU cache обобщение ✅ -**Всего**: 17/20 задач (85%) +**Всего**: 18/20 задач (90%) --- diff --git a/src/tdlib/users.rs b/src/tdlib/users.rs index 3471812..71ddcba 100644 --- a/src/tdlib/users.rs +++ b/src/tdlib/users.rs @@ -13,27 +13,32 @@ use super::types::UserOnlineStatus; /// /// # Type Parameters /// +/// * `K` - Тип ключа (должен реализовывать `Eq + Hash + Clone + Copy`) /// * `V` - Тип значения (должен реализовывать `Clone`) /// /// # Examples /// /// ```ignore -/// let mut cache = LruCache::::new(100); +/// let mut cache = LruCache::::new(100); /// cache.insert(UserId::new(1), "Alice".to_string()); /// assert_eq!(cache.get(&UserId::new(1)), Some(&"Alice".to_string())); /// ``` -pub struct LruCache { +pub struct LruCache { /// Хранилище ключ-значение. - map: HashMap, + map: HashMap, /// Порядок доступа: последний элемент — самый недавно использованный. - order: Vec, + order: Vec, /// Максимальная ёмкость кэша. capacity: usize, } -impl LruCache { +impl LruCache +where + K: Eq + std::hash::Hash + Clone + Copy, + V: Clone, +{ /// Создает новый LRU кэш с заданной ёмкостью. pub fn new(capacity: usize) -> Self { Self { @@ -44,7 +49,7 @@ impl LruCache { } /// Получает значение и обновляет порядок доступа (помечает как использованное). - pub fn get(&mut self, key: &UserId) -> Option<&V> { + pub fn get(&mut self, key: &K) -> Option<&V> { if self.map.contains_key(key) { // Перемещаем ключ в конец (самый недавно использованный) self.order.retain(|k| k != key); @@ -56,12 +61,12 @@ impl LruCache { } /// Получить значение без обновления порядка (для read-only доступа) - pub fn peek(&self, key: &UserId) -> Option<&V> { + pub fn peek(&self, key: &K) -> Option<&V> { self.map.get(key) } /// Вставить значение - pub fn insert(&mut self, key: UserId, value: V) { + pub fn insert(&mut self, key: K, value: V) { if self.map.contains_key(&key) { // Обновляем существующее значение self.map.insert(key, value); @@ -81,7 +86,7 @@ impl LruCache { } /// Проверить наличие ключа - pub fn contains_key(&self, key: &UserId) -> bool { + pub fn contains_key(&self, key: &K) -> bool { self.map.contains_key(key) } @@ -118,10 +123,10 @@ impl LruCache { /// ``` pub struct UserCache { /// LRU-кэш usernames: user_id → username. - pub user_usernames: LruCache, + pub user_usernames: LruCache, /// LRU-кэш имён: user_id → display_name (first_name + last_name). - pub user_names: LruCache, + pub user_names: LruCache, /// Связь chat_id → user_id для приватных чатов. pub chat_user_ids: HashMap, @@ -130,7 +135,7 @@ pub struct UserCache { pub pending_user_ids: Vec, /// LRU-кэш онлайн-статусов: user_id → status. - pub user_statuses: LruCache, + pub user_statuses: LruCache, /// ID клиента TDLib для API вызовов. client_id: i32,