mirror of
https://github.com/logos-messaging/libchat.git
synced 2026-02-10 08:53:08 +00:00
chore: shared memory db with name
This commit is contained in:
parent
4f6705603d
commit
75fd6acda9
@ -1,26 +1,19 @@
|
||||
//! Example: Ping-Pong Chat
|
||||
//!
|
||||
//! This example demonstrates a back-and-forth conversation between two users
|
||||
//! using temporary file storage.
|
||||
//! using in-memory storage.
|
||||
//!
|
||||
//! Run with: cargo run -p logos-chat --example ping_pong
|
||||
|
||||
use logos_chat::{ChatManager, StorageConfig};
|
||||
use tempfile::tempdir;
|
||||
use logos_chat::ChatManager;
|
||||
|
||||
fn main() {
|
||||
println!("=== Ping-Pong Chat Example ===\n");
|
||||
|
||||
// Create temporary directories for storage
|
||||
let dir = tempdir().expect("Failed to create temp dir");
|
||||
let alice_db = dir.path().join("alice.db");
|
||||
let bob_db = dir.path().join("bob.db");
|
||||
|
||||
// Create two chat participants with file-based storage
|
||||
let mut alice = ChatManager::open(StorageConfig::File(alice_db.to_str().unwrap().to_string()))
|
||||
.expect("Failed to create Alice's chat manager");
|
||||
let mut bob = ChatManager::open(StorageConfig::File(bob_db.to_str().unwrap().to_string()))
|
||||
.expect("Failed to create Bob's chat manager");
|
||||
// Create two chat participants with in-memory storage
|
||||
// Each ChatManager has its own shared in-memory SQLite database
|
||||
let mut alice = ChatManager::in_memory("alice").expect("Failed to create Alice's chat manager");
|
||||
let mut bob = ChatManager::in_memory("bob").expect("Failed to create Bob's chat manager");
|
||||
|
||||
println!("Created participants:");
|
||||
println!(" Alice: {}", alice.local_address());
|
||||
|
||||
@ -39,6 +39,7 @@ pub enum ChatManagerError {
|
||||
///
|
||||
/// It manages identity, inbox, and chats with all state persisted to SQLite.
|
||||
/// Chats are loaded from storage on each operation - no in-memory caching.
|
||||
/// Uses a single shared database for both chat metadata and ratchet state.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@ -68,6 +69,8 @@ pub struct ChatManager {
|
||||
/// Storage for chat metadata (identity, inbox keys, chat records).
|
||||
storage: ChatStorage,
|
||||
/// Storage config for creating ratchet storage instances.
|
||||
/// For file/encrypted databases, SQLite handles connection efficiently.
|
||||
/// For in-memory testing, use SharedInMemory to share data.
|
||||
storage_config: StorageConfig,
|
||||
}
|
||||
|
||||
@ -103,8 +106,14 @@ impl ChatManager {
|
||||
}
|
||||
|
||||
/// Creates a new in-memory ChatManager (for testing).
|
||||
pub fn in_memory() -> Result<Self, ChatManagerError> {
|
||||
Self::open(StorageConfig::InMemory)
|
||||
///
|
||||
/// Uses a shared in-memory SQLite database so that multiple storage
|
||||
/// instances within the same ChatManager share data.
|
||||
///
|
||||
/// The `db_name` should be unique per ChatManager instance to avoid
|
||||
/// sharing data between different users.
|
||||
pub fn in_memory(db_name: &str) -> Result<Self, ChatManagerError> {
|
||||
Self::open(StorageConfig::SharedInMemory(db_name.to_string()))
|
||||
}
|
||||
|
||||
/// Creates a new RatchetStorage instance using the stored config.
|
||||
@ -334,13 +343,13 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_create_chat_manager() {
|
||||
let manager = ChatManager::in_memory().unwrap();
|
||||
let manager = ChatManager::in_memory("test1").unwrap();
|
||||
assert!(!manager.local_address().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_identity_persistence() {
|
||||
let manager = ChatManager::in_memory().unwrap();
|
||||
let manager = ChatManager::in_memory("test2").unwrap();
|
||||
let address = manager.local_address();
|
||||
|
||||
// Identity should be persisted
|
||||
@ -351,15 +360,15 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_create_intro_bundle() {
|
||||
let mut manager = ChatManager::in_memory().unwrap();
|
||||
let mut manager = ChatManager::in_memory("test3").unwrap();
|
||||
let bundle = manager.create_intro_bundle();
|
||||
assert!(bundle.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_start_private_chat() {
|
||||
let mut alice = ChatManager::in_memory().unwrap();
|
||||
let mut bob = ChatManager::in_memory().unwrap();
|
||||
let mut alice = ChatManager::in_memory("alice1").unwrap();
|
||||
let mut bob = ChatManager::in_memory("bob1").unwrap();
|
||||
|
||||
// Bob creates an intro bundle
|
||||
let bob_intro = bob.create_intro_bundle().unwrap();
|
||||
@ -379,7 +388,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_inbox_key_persistence() {
|
||||
let mut manager = ChatManager::in_memory().unwrap();
|
||||
let mut manager = ChatManager::in_memory("test4").unwrap();
|
||||
|
||||
// Create intro bundle (should persist ephemeral key)
|
||||
let intro = manager.create_intro_bundle().unwrap();
|
||||
@ -392,8 +401,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_chat_exists() {
|
||||
let mut alice = ChatManager::in_memory().unwrap();
|
||||
let mut bob = ChatManager::in_memory().unwrap();
|
||||
let mut alice = ChatManager::in_memory("alice2").unwrap();
|
||||
let mut bob = ChatManager::in_memory("bob2").unwrap();
|
||||
|
||||
let bob_intro = bob.create_intro_bundle().unwrap();
|
||||
let (chat_id, _) = alice.start_private_chat(&bob_intro, "Hello!").unwrap();
|
||||
@ -405,8 +414,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_delete_chat() {
|
||||
let mut alice = ChatManager::in_memory().unwrap();
|
||||
let mut bob = ChatManager::in_memory().unwrap();
|
||||
let mut alice = ChatManager::in_memory("alice3").unwrap();
|
||||
let mut bob = ChatManager::in_memory("bob3").unwrap();
|
||||
|
||||
let bob_intro = bob.create_intro_bundle().unwrap();
|
||||
let (chat_id, _) = alice.start_private_chat(&bob_intro, "Hello!").unwrap();
|
||||
@ -427,7 +436,7 @@ mod tests {
|
||||
let dir = tempdir().unwrap();
|
||||
let db_path = dir.path().join("test.db");
|
||||
|
||||
let mut bob = ChatManager::in_memory().unwrap();
|
||||
let mut bob = ChatManager::in_memory("bob4").unwrap();
|
||||
let bob_intro = bob.create_intro_bundle().unwrap();
|
||||
|
||||
let chat_id;
|
||||
|
||||
@ -8,8 +8,11 @@ use crate::StorageError;
|
||||
/// Configuration for SQLite storage.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum StorageConfig {
|
||||
/// In-memory database (for testing).
|
||||
/// In-memory database (isolated, for simple testing).
|
||||
InMemory,
|
||||
/// Shared in-memory database with a name (multiple connections share data).
|
||||
/// Use this when you need multiple storage instances to share the same in-memory DB.
|
||||
SharedInMemory(String),
|
||||
/// File-based SQLite database.
|
||||
File(String),
|
||||
/// SQLCipher encrypted database.
|
||||
@ -29,6 +32,17 @@ impl SqliteDb {
|
||||
pub fn new(config: StorageConfig) -> Result<Self, StorageError> {
|
||||
let conn = match config {
|
||||
StorageConfig::InMemory => Connection::open_in_memory()?,
|
||||
StorageConfig::SharedInMemory(ref name) => {
|
||||
// Use URI mode to create a shared in-memory database
|
||||
// Multiple connections with the same name share the same data
|
||||
let uri = format!("file:{}?mode=memory&cache=shared", name);
|
||||
Connection::open_with_flags(
|
||||
&uri,
|
||||
rusqlite::OpenFlags::SQLITE_OPEN_URI
|
||||
| rusqlite::OpenFlags::SQLITE_OPEN_READ_WRITE
|
||||
| rusqlite::OpenFlags::SQLITE_OPEN_CREATE,
|
||||
)?
|
||||
}
|
||||
StorageConfig::File(ref path) => Connection::open(path)?,
|
||||
StorageConfig::Encrypted { ref path, ref key } => {
|
||||
let conn = Connection::open(path)?;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user