fix: Replace HashSet with VecDeque for recent blocks cache
Problem: - HashSet doesn't maintain insertion order - iter().next() returns arbitrary element, not the oldest - Cache eviction was unpredictable Solution: - Use VecDeque for FIFO ordering - push_back() adds new block - pop_front() removes oldest block when cache exceeds 10 elements - contains() is O(n) but performant for 10 elements Changes: - RadioParadiseStreamSourceLogic: recent_blocks now VecDeque<EventId> - mark_block_downloaded(): simplified with guaranteed FIFO eviction - Documentation updated with VecDeque usage and advantages
This commit is contained in:
@@ -20,7 +20,7 @@ RadioParadiseStreamSource (wrapper)
|
||||
|
||||
Responsabilités :
|
||||
- **File d'attente** : `VecDeque<EventId>` pour les blocks à télécharger
|
||||
- **Cache anti-redondance** : `HashSet<EventId>` pour 10 blocs récents
|
||||
- **Cache anti-redondance** : `VecDeque<EventId>` pour 10 blocs récents (FIFO)
|
||||
- **Téléchargement** : Fetch bloc FLAC (bitrate=4 uniquement)
|
||||
- **Décodage** : Stream FLAC via `pmoflac::decode_audio_stream`
|
||||
- **Timing** : Calcul précis pour insertion TrackBoundary
|
||||
@@ -36,7 +36,7 @@ Responsabilités :
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 2. Vérification cache │
|
||||
│ └─> HashSet::contains(&event_id) │
|
||||
│ └─> VecDeque::contains(&event_id) │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
@@ -118,17 +118,20 @@ AudioSegment::new_audio(42, AudioChunk::I16(...))
|
||||
const RECENT_BLOCKS_CACHE_SIZE: usize = 10;
|
||||
|
||||
fn mark_block_downloaded(&mut self, event_id: EventId) {
|
||||
self.recent_blocks.insert(event_id);
|
||||
self.recent_blocks.push_back(event_id);
|
||||
|
||||
// Limiter la taille du cache : retirer le plus ancien
|
||||
if self.recent_blocks.len() > RECENT_BLOCKS_CACHE_SIZE {
|
||||
// Retirer un élément (ordre non garanti avec HashSet)
|
||||
if let Some(&first) = self.recent_blocks.iter().next() {
|
||||
self.recent_blocks.remove(&first);
|
||||
}
|
||||
self.recent_blocks.pop_front();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Avantages VecDeque** :
|
||||
- ✅ Ordre FIFO garanti (le plus ancien est toujours retiré)
|
||||
- ✅ Simple et prévisible
|
||||
- ✅ Pour 10 éléments, `contains()` en O(n) reste très performant
|
||||
|
||||
## Support FLAC
|
||||
|
||||
### Formats supportés
|
||||
|
||||
@@ -17,7 +17,7 @@ use pmoaudio::{
|
||||
use pmoflac::decode_audio_stream;
|
||||
use pmometadata::{MemoryTrackMetadata, TrackMetadata};
|
||||
use std::{
|
||||
collections::{HashSet, VecDeque},
|
||||
collections::VecDeque,
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
};
|
||||
@@ -38,7 +38,7 @@ const RECENT_BLOCKS_CACHE_SIZE: usize = 10;
|
||||
pub struct RadioParadiseStreamSourceLogic {
|
||||
client: RadioParadiseClient,
|
||||
chunk_frames: usize,
|
||||
recent_blocks: HashSet<EventId>,
|
||||
recent_blocks: VecDeque<EventId>,
|
||||
block_queue: VecDeque<EventId>,
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ impl RadioParadiseStreamSourceLogic {
|
||||
Self {
|
||||
client,
|
||||
chunk_frames,
|
||||
recent_blocks: HashSet::with_capacity(RECENT_BLOCKS_CACHE_SIZE),
|
||||
recent_blocks: VecDeque::with_capacity(RECENT_BLOCKS_CACHE_SIZE),
|
||||
block_queue: VecDeque::new(),
|
||||
}
|
||||
}
|
||||
@@ -65,16 +65,13 @@ impl RadioParadiseStreamSourceLogic {
|
||||
self.recent_blocks.contains(&event_id)
|
||||
}
|
||||
|
||||
/// Marque un bloc comme récemment téléchargé
|
||||
/// Marque un bloc comme récemment téléchargé (FIFO)
|
||||
fn mark_block_downloaded(&mut self, event_id: EventId) {
|
||||
self.recent_blocks.insert(event_id);
|
||||
self.recent_blocks.push_back(event_id);
|
||||
|
||||
// Limiter la taille du cache
|
||||
// Limiter la taille du cache : retirer le plus ancien
|
||||
if self.recent_blocks.len() > RECENT_BLOCKS_CACHE_SIZE {
|
||||
// Retirer un élément (HashSet n'a pas d'ordre, donc on retire le premier)
|
||||
if let Some(&first) = self.recent_blocks.iter().next() {
|
||||
self.recent_blocks.remove(&first);
|
||||
}
|
||||
self.recent_blocks.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user