rust_jsonl_async est un wrapper Rust pour l'écriture de fichiers JSONL (JSON Lines) qui offre une interface thread-safe et non bloquante. Il exécute toutes les
opérations d'écriture dans un thread d'arrière-plan dédié, ce qui le rend idéal pour les applications qui nécessitent une journalisation (logging) performante sans
bloquer le thread principal.
Cette caisse est parfaite pour les applications à haute concurrence, comme les serveurs web ou les services de traitement de données, où la journalisation des événements ou des objets structurés doit être rapide et efficace.
- Écritures Asynchrones: Les objets sérialisables sont envoyés à un thread d'écriture dédié via un canal, évitant ainsi de bloquer le thread appelant.
- Écriture par Lots (Batching): Le worker utilise un buffer et traite les écritures par lots pour minimiser les opérations d'I/O système et maximiser le débit.
- Sécurité des Threads (Thread-Safe): La structure
AsyncJsonlQueuepeut être partagée en toute sécurité entre plusieurs threads (Sync+Send). - Back-Pressure: Le canal pour les écritures a une capacité limitée, ce qui empêche une utilisation excessive de la mémoire si les données sont produites plus rapidement qu'elles ne peuvent être écrites sur le disque.
- Gestion du Cycle de Vie: Le thread d'arrière-plan est démarré et arrêté proprement, avec des méthodes pour attendre la synchronisation des données.
Dropest implémenté pour garantir que les données restantes sont écrites avant la fermeture. - Générique sur les Données: Peut écrire n'importe quel type de données qui implémente
serde::Serialize.
Ajoutez cette ligne à votre Cargo.toml:
[dependencies] rust_jsonl_async = "0.1.0"
(Note: Remplacez 0.1.0 par la version souhaitée.)
Voici un exemple simple pour créer un fichier, y écrire des données structurées de manière asynchrone.
use rust_jsonl_async::AsyncJsonlQueue; use serde::Serialize; use std::time::Duration; use tempfile::NamedTempFile; #[derive(Serialize, Clone)] struct LogEntry { level: String, message: String, timestamp: u64, } fn main() { // Utiliser un fichier temporaire pour cet exemple let temp_file = NamedTempFile::new().unwrap(); let mut queue = AsyncJsonlQueue::new(temp_file.path()); // Démarrer le thread d'écriture queue.start(); // Attendre que le worker soit prêt (fichier ouvert) if !queue.wait_for_ready(Duration::from_secs(5)) { panic!("Le worker JSONL n'a pas pu démarrer à temps"); } // Créer une entrée de log let entry = LogEntry { level: "info".to_string(), message: "Ceci est un test".to_string(), timestamp: 1678886400, }; // Envoyer les données à la file d'écriture (ne bloque pas) queue.write(entry.clone()).unwrap(); // `sync` attend que toutes les écritures en attente soient terminées assert!(queue.sync(Duration::from_secs(5)), "La synchronisation a échoué"); // Lire le fichier pour vérifier le contenu let content = std::fs::read_to_string(temp_file.path()).unwrap(); let written_line = content.lines().next().unwrap(); let written_entry: LogEntry = serde_json::from_str(written_line).unwrap(); assert_eq!(written_entry.message, "Ceci est un test"); println!("Données écrites avec succès: {}", written_line); // La méthode `stop` est appelée automatiquement lorsque `queue` est détruite (Drop) }
AsyncJsonlQueue::new(path): Crée une nouvelle file d'écriture pour le fichier spécifié.queue.start(): Démarre le thread d'écriture en arrière-plan.queue.wait_for_ready(timeout): Attend que le thread worker ait ouvert le fichier et soit prêt à recevoir des données.queue.write(data): Ajoute un objet sérialisable (T: Serialize) à la file d'écriture. Bloque si la file est pleine.queue.sync(timeout): Bloque jusqu'à ce que toutes les écritures en attente dans la file soient écrites sur le disque.queue.stop(): Arrête proprement le thread d'arrière-plan (appelé automatiquement viaDrop).
Ce projet est sous licence MIT. Voir le fichier LICENSE pour plus de détails.