lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

open_lifecycle.rs (3681B)


      1 use std::time::Duration;
      2 
      3 use radroots_storage::{EventStore, event::SourceGeneration, status::EventStoreMode};
      4 use radroots_storage_sqlite::{Error, OpenMode, OpenOptions, Paths, SqliteStorage};
      5 
      6 fn generation(byte: u8) -> SourceGeneration {
      7     SourceGeneration::new([byte; 32]).expect("source generation")
      8 }
      9 
     10 #[tokio::test]
     11 async fn public_open_creates_both_databases_and_reuses_the_durable_generation() {
     12     let directory = tempfile::tempdir().expect("temporary directory");
     13     let paths = Paths::from_directory(directory.path()).expect("owned paths");
     14     let expected = generation(31);
     15     let store = SqliteStorage::open(
     16         OpenOptions::new(paths.clone(), OpenMode::Create)
     17             .with_busy_timeout(Duration::from_millis(250))
     18             .expect("busy timeout")
     19             .with_source_generation(expected, 1_000)
     20             .expect("source generation"),
     21     )
     22     .await
     23     .expect("create storage");
     24     assert!(paths.runtime().is_file());
     25     assert!(paths.private().is_file());
     26     let status = EventStore::status(&store).await.expect("event status");
     27     assert_eq!(status.generation(), expected);
     28     assert_eq!(status.mode(), EventStoreMode::ReadWrite);
     29 
     30     let reader = SqliteStorage::open(OpenOptions::new(paths.clone(), OpenMode::ReadOnly))
     31         .await
     32         .expect("concurrent reader");
     33     let reader_status = EventStore::status(&reader).await.expect("reader status");
     34     assert_eq!(reader_status.generation(), expected);
     35     assert_eq!(reader_status.mode(), EventStoreMode::ReadOnly);
     36     drop(reader);
     37 
     38     assert!(matches!(
     39         SqliteStorage::open(OpenOptions::new(paths.clone(), OpenMode::ReadWriteExisting,)).await,
     40         Err(Error::WriterAlreadyActive { .. })
     41     ));
     42     let cloned = store.clone();
     43     drop(store);
     44     assert!(matches!(
     45         SqliteStorage::open(OpenOptions::new(paths.clone(), OpenMode::ReadWriteExisting,)).await,
     46         Err(Error::WriterAlreadyActive { .. })
     47     ));
     48     drop(cloned);
     49 
     50     let reopened = SqliteStorage::open(OpenOptions::new(paths, OpenMode::ReadWriteExisting))
     51         .await
     52         .expect("reopen after guard release");
     53     assert_eq!(
     54         EventStore::status(&reopened)
     55             .await
     56             .expect("reopened status")
     57             .generation(),
     58         expected
     59     );
     60 }
     61 
     62 #[tokio::test]
     63 async fn fresh_store_requires_explicit_generation_and_exact_expectations() {
     64     let directory = tempfile::tempdir().expect("temporary directory");
     65     let paths = Paths::from_directory(directory.path()).expect("owned paths");
     66     assert!(matches!(
     67         SqliteStorage::open(OpenOptions::new(paths.clone(), OpenMode::Create)).await,
     68         Err(Error::SourceGenerationRequired)
     69     ));
     70     assert!(!paths.runtime().exists());
     71     assert!(!paths.private().exists());
     72 
     73     let expected = generation(41);
     74     let store = SqliteStorage::open(
     75         OpenOptions::new(paths.clone(), OpenMode::Create)
     76             .with_source_generation(expected, 2_000)
     77             .expect("source generation"),
     78     )
     79     .await
     80     .expect("complete fresh store");
     81     drop(store);
     82 
     83     let exact_reopen = SqliteStorage::open(
     84         OpenOptions::new(paths.clone(), OpenMode::ReadWriteExisting)
     85             .with_source_generation(expected, 2_000)
     86             .expect("exact expectation"),
     87     )
     88     .await
     89     .expect("reopen with exact generation expectation");
     90     drop(exact_reopen);
     91 
     92     assert!(matches!(
     93         SqliteStorage::open(
     94             OpenOptions::new(paths, OpenMode::ReadWriteExisting)
     95                 .with_source_generation(generation(42), 2_000)
     96                 .expect("wrong expectation"),
     97         )
     98         .await,
     99         Err(Error::SourceGenerationMismatch)
    100     ));
    101 }