From 4fa6ea4dd0c3217500b33bcb180ee30fbb1ae6b4 Mon Sep 17 00:00:00 2001 From: jtimperio Date: Fri, 6 Sep 2024 19:03:43 -0700 Subject: [PATCH] RC1 (#3) * Cleanup based on feedback * Add batching and performance upgrades * More tests and Readme Cleanup * Rework the whole damn thing * Cleanup docs --- Cargo.lock | 222 ++- Cargo.toml | 4 +- README.md | 54 +- docs/Queue-Speed-With-Prioritize.png | Bin 64295 -> 65121 bytes docs/Queue-Speed-Without-Prioritize.png | Bin 63590 -> 65896 bytes ...me-to-Send-and-Receive-VS-Bucket-Count.png | Bin 20695 -> 20810 bytes docs/bench-report-no-repro.csv | 400 +++--- docs/bench-report-repro.csv | 400 +++--- graphs/Cargo.toml | 8 + graphs/src/main.rs | 14 +- src/bpq.rs | 35 - src/disk.rs | 203 +++ src/lib.rs | 1252 ++++++++++------- src/pq.rs | 367 ++--- src/pq/ftime.rs | 23 +- src/schema.rs | 178 +++ 16 files changed, 1978 insertions(+), 1182 deletions(-) delete mode 100644 src/bpq.rs create mode 100644 src/disk.rs create mode 100644 src/schema.rs diff --git a/Cargo.lock b/Cargo.lock index b3d88e4..823c582 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -53,6 +53,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bincode" version = "1.3.3" @@ -88,9 +94,9 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.1.15" +version = "1.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "a93fe60e2fc87b6ba2c117f67ae14f66e3fc7d6a1e612a25adb238cc980eadb3" dependencies = [ "shlex", ] @@ -143,6 +149,63 @@ dependencies = [ "memchr", ] +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "getrandom" version = "0.2.15" @@ -163,6 +226,25 @@ checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "graphs" version = "0.1.0" +dependencies = [ + "chrono", + "csv", + "rand", + "rpq", + "tokio", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hermit-abi" @@ -170,6 +252,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -193,6 +281,34 @@ dependencies = [ "cc", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", + "serde", +] + [[package]] name = "itoa" version = "1.0.11" @@ -257,6 +373,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-traits" version = "0.2.19" @@ -310,6 +432,12 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.20" @@ -387,7 +515,7 @@ dependencies = [ [[package]] name = "rpq" -version = "0.1.3" +version = "0.2.0" dependencies = [ "bincode", "chrono", @@ -395,6 +523,7 @@ dependencies = [ "rand", "redb", "serde", + "serde_with", "tokio", "uuid", ] @@ -419,24 +548,66 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.5.0", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "shlex" version = "1.3.0" @@ -468,6 +639,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "2.0.77" @@ -479,6 +656,37 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tokio" version = "1.40.0" diff --git a/Cargo.toml b/Cargo.toml index fea41e4..06909bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rpq" -version = "0.1.3" +version = "0.2.0" edition = "2021" authors = ["Justin Timperio"] description = "A high performance embeddable double priority queue with complex priority ordering guarantees" @@ -25,6 +25,7 @@ csv = "1.3.0" rand = "0.8.4" redb = "2.1.1" serde = { version = "1.0.208", features = ["derive"] } +serde_with = { version = "3.9.0", features = ["chrono"] } tokio = { version = "1.10.0", features = ["full"] } uuid = { version = "1.10.0", features = ["v4"] } @@ -33,3 +34,4 @@ inherits = "release" [workspace] members = ["graphs"] +name = "rpq-graphs" diff --git a/README.md b/README.md index afa393b..ebd1eb5 100644 --- a/README.md +++ b/README.md @@ -42,10 +42,10 @@ RPQ is a concurrency safe, embeddable priority queue that can be used in a varie ## Benchmarks Due to the fact that most operations are done in constant time O(1) or logarithmic time O(log n), with the exception of the prioritize function which happens in linear time O(n), all RPQ operations are extremely fast. A single RPQ can handle a few million transactions a second and can be tuned depending on your work load. I have included some basic benchmarks using C++, Rust, Zig, and Go to measure RPQ's performance against the standard implementations of other languages that can be found here at: [pq-bench](https://github.com/JustinTimperio/pq-bench). -| | | -|-------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------| -| ![Time-Spent](https://github.com/JustinTimperio/pq-bench/blob/master/docs/Time-Spent-vs-Implementation.png) | ![Queue-Speed-WITHOUT-Reprioritize](./docs/Queue-Speed-Without-Prioritize.png) | -| ![TODO: Queue-Speed-WITH-Reprioritize](./docs/Queue-Speed-With-Prioritize.png) | ![Time-to-Send-and-Recive-VS-Bucket-Count](./docs/Time-to-Send-and-Receive-VS-Bucket-Count.png) | +| | | +|-------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------| +| ![Time-Spent](https://github.com/JustinTimperio/pq-bench/blob/master/docs/Time-Spent-vs-Implementation.png) | ![Queue-Speed-WITHOUT-Reprioritize](./docs/Queue-Speed-Without-Prioritize.png) | +| ![TODO: Queue-Speed-WITH-Reprioritize](./docs/Queue-Speed-With-Prioritize.png) | ![Time-to-Send-and-Receive-VS-Bucket-Count](./docs/Time-to-Send-and-Receive-VS-Bucket-Count.png) | ## Usage RPQ is a embeddable priority queue that is meant to be used at the core of critical workloads where complex ordering are required in combination with large volumes of data. The best way to us RPQ is to import the Crate and use the API to interact with the queue. @@ -54,13 +54,15 @@ TODO: Publish to crates.io ```toml [dependencies] -rpq = "0.1.3" +rpq = "0.2.0" ``` ### API Reference - `RPQ::new(options: RPQOptions) -> Result<(RPQ, usize), Error>` - Creates a new RPQ with the given options and returns the number of restored items. - `enqueue(mut item: Item) -> Result<(), Error>` - Enqueues a new item into the RPQ. + - `enqueue_batch(mut items: Vec) -> Result<(), Error>` - Enqueues a batch of items into the RPQ. - `dequeue() -> Result` - Dequeues the next item from the RPQ. + - `dequeue_batch(count: usize) -> Result, Error>` - Dequeues a batch of items from the RPQ. - `prioritize() -> Result<(usize, usize), Error>` - Prioritizes the items in the RPQ and returns the number of timed out and reprioritized items. - `len() -> usize` - Returns the number of items in the RPQ. - `active_buckets() -> usize` - Returns the number of active buckets in the RPQ. @@ -71,23 +73,20 @@ rpq = "0.1.3" #### Example Usage ```rust -use std::sync::Arc; -use std::time::{Duration, Instant}; -use rpq::pq::Item; -use rpq::{RPQOptions, RPQ}; +use chrono::Duration; +use rpq::{schema::RPQOptions, schema::Item, RPQ}; #[tokio::main(flavor = "multi_thread")] async fn main() { - let message_count = 10_000_000; + let message_count = 1_000_000; let options = RPQOptions { - bucket_count: 10, - disk_cache_enabled: false, - database_path: "/tmp/rpq.redb".to_string(), - lazy_disk_cache: false, - lazy_disk_max_delay: Duration::from_secs(5), - lazy_disk_cache_batch_size: 5000, - buffer_size: 1_000_000, + max_priority: 10, + disk_cache_enabled: true, + database_path: "/tmp/rpq-prioritize.redb".to_string(), + lazy_disk_cache: true, + lazy_disk_write_delay: Duration::seconds(5), + lazy_disk_cache_batch_size: 10_000, }; let r = RPQ::new(options).await; @@ -99,10 +98,8 @@ async fn main() { } } - let (rpq, _) = r.unwrap(); + let (rpq, _restored_items) = r.unwrap(); - let timer = Instant::now(); - let send_timer = Instant::now(); for i in 0..message_count { let item = Item::new( i % 10, @@ -110,7 +107,7 @@ async fn main() { false, None, false, - Some(Duration::from_secs(5)), + None, ); let result = rpq.enqueue(item).await; if result.is_err() { @@ -119,9 +116,6 @@ async fn main() { } } - let send_elapsed = send_timer.elapsed().as_secs_f64(); - - let receive_timer = Instant::now(); for _i in 0..message_count { let result = rpq.dequeue().await; if result.is_err() { @@ -130,17 +124,7 @@ async fn main() { } } - let receive_elapsed = receive_timer.elapsed().as_secs_f64(); - - println!( - "Time to insert {} messages: {}s", - message_count, send_elapsed - ); - println!( - "Time to receive {} messages: {}s", - message_count, receive_elapsed - ); - println!("Total Time: {}s", timer.elapsed().as_secs_f64()); + rpq.close().await; } ``` diff --git a/docs/Queue-Speed-With-Prioritize.png b/docs/Queue-Speed-With-Prioritize.png index 97e7f6bc168e97e4a0168fe9bd668d2127856447..1afde8b499b07c5d9c05a066b48a77e3ed770a1c 100644 GIT binary patch literal 65121 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 z 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 P{Z9Y1p-$eZtGE9jIh98+ literal 64295 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 diff --git a/docs/Queue-Speed-Without-Prioritize.png b/docs/Queue-Speed-Without-Prioritize.png index fc07ab8c8a51cc87c3f075a2b97731a4342721f7..fb5a8627df3e38a0cccf6a300314989cb3b8cd2c 100644 GIT binary patch literal 65896 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 IU%B)D0sML&R{#J2 literal 63590 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 W<|7*b^|EG-?pcE~1*d+!^}hh%e&$vH diff --git a/docs/Time-to-Send-and-Receive-VS-Bucket-Count.png b/docs/Time-to-Send-and-Receive-VS-Bucket-Count.png index b1607ec71485dba10ce41b4b5abd117a631dff57..c6a5981c9f07a27b7cf396fdc1dbd69b74aa8fd4 100644 GIT binary patch literal 20810 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 gr|bW9)fqfO@&0i_@% literal 20695 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 e|M$15Olqv6+O`k4xk6sa>, -} - -impl BucketPriorityQueue { - pub fn new() -> BucketPriorityQueue { - BucketPriorityQueue { - bucket_ids: RwLock::new(BTreeSet::new()), - } - } - - pub fn len(&self) -> usize { - self.bucket_ids.read().unwrap().len() - } - - pub fn peek(&self) -> Option { - self.bucket_ids.read().unwrap().first().cloned() - } - - pub fn add_bucket(&self, bucket_id: usize) { - // If the bucket already exists, return - if self.bucket_ids.read().unwrap().contains(&bucket_id) { - return; - } - - self.bucket_ids.write().unwrap().insert(bucket_id); - } - - pub fn remove_bucket(&self, bucket_id: &usize) { - self.bucket_ids.write().unwrap().remove(&bucket_id); - } -} diff --git a/src/disk.rs b/src/disk.rs new file mode 100644 index 0000000..5dffd2b --- /dev/null +++ b/src/disk.rs @@ -0,0 +1,203 @@ +use std::error::Error; +use std::io::Error as IoError; +use std::io::ErrorKind; +use std::vec::Vec; + +use redb::{Database, ReadableTableMetadata, TableDefinition}; +use serde::de::DeserializeOwned; +use serde::Serialize; + +use crate::schema; + +pub struct DiskCache { + db: Database, + phantom: std::marker::PhantomData, +} + +const DB: TableDefinition<&str, &[u8]> = TableDefinition::new("rpq"); + +impl DiskCache +where + T: Serialize + DeserializeOwned, +{ + pub fn new(path: &str) -> DiskCache { + let db = Database::create(path).unwrap(); + + // Create the initial table + let ctxn = db.begin_write().unwrap(); + ctxn.open_table(DB).unwrap(); + ctxn.commit().unwrap(); + + DiskCache { + db, + phantom: std::marker::PhantomData, + } + } + + pub fn commit_batch(&self, write_cache: &mut Vec>) -> Result<(), Box> + where + T: Serialize + DeserializeOwned, + { + let write_txn = self.db.begin_write().unwrap(); + for item in write_cache.iter() { + let mut table = write_txn.open_table(DB).unwrap(); + let b = item.to_bytes(); + if b.is_err() { + return Err(Box::::from(IoError::new( + ErrorKind::InvalidInput, + "Error converting item to bytes", + ))); + } + + let b = b.unwrap(); + let key = item.get_disk_uuid().unwrap(); + + let was_written = table.insert(key.as_str(), &b[..]); + if was_written.is_err() { + return Err(Box::::from(IoError::new( + ErrorKind::InvalidInput, + "Error writing item to disk cache", + ))); + } + } + + write_txn.commit().unwrap(); + write_cache.clear(); + Ok(()) + } + + pub fn delete_batch( + &self, + delete_cache: &mut Vec>, + ) -> Result<(), Box> + where + T: Serialize + DeserializeOwned, + { + let write_txn = self.db.begin_write().unwrap(); + for item in delete_cache.iter() { + let mut table = write_txn.open_table(DB).unwrap(); + let key = item.get_disk_uuid().unwrap(); + let was_deleted = table.remove(key.as_str()); + if was_deleted.is_err() { + return Err(Box::::from(IoError::new( + ErrorKind::InvalidInput, + "Error deleting item from disk cache", + ))); + } + } + write_txn.commit().unwrap(); + + delete_cache.clear(); + Ok(()) + } + + pub fn commit_single(&self, item: schema::Item) -> Result<(), Box> + where + T: Serialize + DeserializeOwned, + { + let write_txn = self.db.begin_write().unwrap(); + { + let mut table = write_txn.open_table(DB).unwrap(); + let b = item.to_bytes(); + + if b.is_err() { + return Err(Box::::from(IoError::new( + ErrorKind::InvalidInput, + "Error converting item to bytes", + ))); + } + let b = b.unwrap(); + + let disk_uuid = item.get_disk_uuid(); + if disk_uuid.is_none() { + return Err(Box::::from(IoError::new( + ErrorKind::InvalidInput, + "Error getting disk uuid", + ))); + } + + let was_written = table.insert(disk_uuid.unwrap().as_str(), &b[..]); + if was_written.is_err() { + return Err(Box::::from(IoError::new( + ErrorKind::InvalidInput, + "Error writing item to disk cache", + ))); + } + } + write_txn.commit().unwrap(); + + Ok(()) + } + + pub fn delete_single(&self, key: &str) -> Result<(), Box> + where + T: Serialize + DeserializeOwned, + { + let write_txn = self.db.begin_write().unwrap(); + { + let mut table = write_txn.open_table(DB).unwrap(); + let was_removed = table.remove(key); + if was_removed.is_err() { + return Err(Box::::from(IoError::new( + ErrorKind::InvalidInput, + "Error deleting item from disk cache", + ))); + } + } + write_txn.commit().unwrap(); + + Ok(()) + } + + pub fn return_items_from_disk(&self) -> Result>, Box> + where + T: Serialize + DeserializeOwned, + { + let mut items = Vec::new(); + let read_txn = self.db.begin_read().unwrap(); + let table = read_txn.open_table(DB).unwrap(); + + let cursor = match table.range::<&str>(..) { + Ok(range) => range, + Err(e) => { + return Err(Box::::from(e)); + } + }; + + // Restore the items from the disk cache + for (_i, entry) in cursor.enumerate() { + match entry { + Ok((_key, value)) => { + let item = schema::Item::from_bytes(value.value()); + + if item.is_err() { + println!("Error reading from disk cache: {:?}", item.err()); + return Err(Box::::from(IoError::new( + ErrorKind::InvalidInput, + "Error reading from disk cache", + ))); + } + + // Mark the item as restored + let mut i = item.unwrap(); + i.set_restored(); + items.push(i); + } + Err(e) => { + return Err(Box::::from(e)); + } + } + } + _ = read_txn.close(); + + Ok(items) + } + + /// Returns the number of items in the database + pub fn items_in_db(&self) -> usize { + let read_txn = self.db.begin_read().unwrap(); + let table = read_txn.open_table(DB).unwrap(); + let count = table.len().unwrap(); + count as usize + } +} diff --git a/src/lib.rs b/src/lib.rs index faf5d99..a29405f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,36 +9,70 @@ //! The RPQ should always be created with the new function like so: //! //! ```rust -//! use rpq::{RPQ, RPQOptions}; -//! use std::time; +//! use chrono::Duration; +//! use rpq::{schema::RPQOptions, schema::Item, RPQ}; //! -//! #[tokio::main] +//! #[tokio::main(flavor = "multi_thread")] //! async fn main() { +//! let message_count = 1_000; +//! //! let options = RPQOptions { -//! max_priority: 10, -//! disk_cache_enabled: false, -//! database_path: "/tmp/rpq.db".to_string(), -//! lazy_disk_cache: true, -//! lazy_disk_write_delay: time::Duration::from_secs(5), -//! lazy_disk_cache_batch_size: 10_000, -//! buffer_size: 1_000_000, +//! max_priority: 10, +//! disk_cache_enabled: true, +//! database_path: "/tmp/rpq-prioritize.redb".to_string(), +//! lazy_disk_cache: true, +//! lazy_disk_write_delay: Duration::seconds(5), +//! lazy_disk_cache_batch_size: 10_000, //! }; //! -//! let r = RPQ::::new(options).await; -//! if r.is_err() { -//! // handle logic -//! } +//! let r = RPQ::new(options).await; +//! match r { +//! Ok(_) => {} +//! Err(e) => { +//! println!("Error Creating RPQ: {}", e); +//! return; +//! } +//! } +//! +//! let (rpq, _restored_items) = r.unwrap(); +//! +//! for i in 0..message_count { +//! let item = Item::new( +//! i % 10, +//! i, +//! false, +//! None, +//! false, +//! None, +//! ); +//! +//! let result = rpq.enqueue(item).await; +//! if result.is_err() { +//! println!("Error Enqueuing: {}", result.err().unwrap()); +//! return; +//! } +//! } +//! +//! for _i in 0..message_count { +//! let result = rpq.dequeue().await; +//! if result.is_err() { +//! println!("Error Dequeuing: {}", result.err().unwrap()); +//! return; +//! } +//! } +//! +//! rpq.close().await; //! } //! ``` //! //! # Architecture Notes -//! In many ways, RPQ slighty compromises the performance of a traditional priority queue in order to provide +//! In many ways, RPQ slightly compromises the performance of a traditional priority queue in order to provide //! a variety of features that are useful when absorbing distributed load from many down or upstream services. -//! It employs a fairly novel techinique that allows it to lazily write and delete items from a disk cache while +//! It employs a fairly novel technique that allows it to lazily write and delete items from a disk cache while //! still maintaining data in memory. This basically means that a object can be added to the queue and then removed -//! without the disk commit ever blocking the processes sending or reciving the data. In the case that a batch of data +//! without the disk commit ever blocking the processes sending or receiving the data. In the case that a batch of data //! has already been removed from the queue before it is written to disk, the data is simply discarded. This -//! dramaically reduces the amount of time spent doing disk commits and allows for much better performance in the +//! dramatically reduces the amount of time spent doing disk commits and allows for much better performance in the //! case that you need disk caching and still want to maintain a high peak throughput. //! //! ```text @@ -78,93 +112,60 @@ //! │ Item │ //! └──────┘ //! ``` -use core::time; use std::collections::HashMap; use std::error::Error; use std::io::Error as IoError; use std::io::ErrorKind; use std::result::Result; -use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; -use redb::{Database, ReadableTableMetadata, TableDefinition}; use serde::de::DeserializeOwned; use serde::Serialize; -use tokio::sync::mpsc::{channel, Receiver, Sender}; +use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}; use tokio::sync::watch; use tokio::sync::Mutex; use tokio::task::JoinHandle; use tokio::time::interval; -mod bpq; +mod disk; pub mod pq; +pub mod schema; -const DB: TableDefinition<&str, &[u8]> = TableDefinition::new("rpq"); - -/// RPQ hold private items and configuration for the RPQ. -/// You don't need to interact with the items in this struct directly, -/// but instead via the implementations attched to the RPQ struct. -pub struct RPQ { +/// RPQ holds private items and configuration for the RPQ. +pub struct RPQ { // options is the configuration for the RPQ - options: RPQOptions, - // non_empty_buckets is a binary heap of priorities - non_empty_buckets: bpq::BucketPriorityQueue, - // buckets is a map of priorities to a binary heap of items - buckets: Arc>>, - - // items_in_queues is the number of items across all queues - items_in_queues: AtomicUsize, + options: schema::RPQOptions, + + // queue is the main queue that holds the items + queue: Mutex>, + // disk_cache maintains a cache of items that are in the queue - disk_cache: Option>, + disk_cache: Arc>>, + // lazy_disk_channel is the channel for lazy disk writes - lazy_disk_writer_sender: Arc>>, + lazy_disk_writer_sender: UnboundedSender>, // lazy_disk_reader is the receiver for lazy disk writes - lazy_disk_writer_receiver: Mutex>>, + lazy_disk_writer_receiver: Mutex>>, // lazy_disk_delete_sender is the sender for lazy disk deletes - lazy_disk_delete_sender: Arc>>, + lazy_disk_delete_sender: Arc>>, // lazy_disk_delete_receiver is the receiver for lazy disk deletes - lazy_disk_delete_receiver: Mutex>>, - - // batch_handler is the handler for batches - batch_handler: Mutex, - // batch_counter is the counter for batches - batch_counter: Mutex, - // batch_shutdown_receiver is the receiver for the shutdown signal - batch_shutdown_receiver: watch::Receiver, - // batch_shutdown_sender is the sender for the shutdown signal - batch_shutdown_sender: watch::Sender, - - // shutdown_receiver is the receiver for the shutdown signal - shutdown_receiver: watch::Receiver, - // shutdown_sender is the sender for the shutdown signal - shutdown_sender: watch::Sender, - // sync_handles is a map of priorities to sync handles - sync_handles: Mutex>>, -} - -/// RPQOptions is the configuration for the RPQ -pub struct RPQOptions { - /// Holds the number of priorities(buckets) that this RPQ will accept for this queue. - pub max_priority: usize, - /// Enables or disables the disk cache using redb as the backend to store items - pub disk_cache_enabled: bool, - /// Holds the path to where the disk cache database will be persisted - pub database_path: String, - /// Enables or disables lazy disk writes and deletes. The speed can be quite variable depending - /// on the disk itself and how often you are emptying the queue in combination with the write delay - pub lazy_disk_cache: bool, - /// Sets the delay between lazy disk writes. This delays items from being commited to the disk cache. - /// If you are pulling items off the queue faster than this delay, many times can be skip the write to disk, - /// massively increasing the throughput of the queue. - pub lazy_disk_write_delay: time::Duration, - /// Sets the number of items that will be written to the disk cache in a single batch. This can be used to - /// tune the performance of the disk cache depending on your specific workload. - pub lazy_disk_cache_batch_size: usize, - /// Sets the size of the channnel that is used to buffer items before they are written to the disk cache. - /// This can block your queue if the thread pulling items off the channel becomes fully saturated. Typically you - /// should set this value in proportion to your largest write peaks. I.E. if your peak write is 10,000,000 items per second, - /// and your average write is 1,000,000 items per second, you should set this value to 20,000,000 to ensure that no blocking occurs. - pub buffer_size: usize, + lazy_disk_delete_receiver: Mutex>>, + + // lazy_disk_sync_handles is a map of priorities to sync handles + lazy_disk_sync_handles: Mutex>>, + // lazy_disk_batch_handler is the handler for batches + lazy_disk_batch_handler: Mutex, + // lazy_disk_batch_counter is the counter for batches + lazy_disk_batch_counter: Mutex, + + // lazy_disk_batch_shutdown_receiver is the receiver for the shutdown signal + lazy_disk_batch_shutdown_receiver: watch::Receiver, + // lazy_disk_batch_shutdown_sender is the sender for the shutdown signal + lazy_disk_batch_shutdown_sender: watch::Sender, + // lazy_disk_shutdown_receiver is the receiver for the shutdown signal + lazy_disk_shutdown_receiver: watch::Receiver, + // lazy_disk_shutdown_sender is the sender for the shutdown signal + lazy_disk_shutdown_sender: watch::Sender, } struct BatchHandler { @@ -181,15 +182,13 @@ struct BatchCounter { batch_number: usize, } -impl RPQ +impl RPQ where T: Serialize + DeserializeOwned + 'static, { /// Creates a new RPQ with the given options and returns the RPQ and the number of items restored from the disk cache - pub async fn new(options: RPQOptions) -> Result<(Arc>, usize), Box> { + pub async fn new(options: schema::RPQOptions) -> Result<(Arc>, usize), Box> { // Create base structures - let mut buckets = HashMap::new(); - let items_in_queues = AtomicUsize::new(0); let sync_handles = Vec::new(); let (shutdown_sender, shutdown_receiver) = watch::channel(false); let (batch_shutdown_sender, batch_shutdown_receiver) = watch::channel(false); @@ -203,107 +202,69 @@ where }; // Create the lazy disk sync channel - let (lazy_disk_writer_sender, lazy_disk_writer_receiver) = - channel(options.buffer_size as usize); - let (lazy_disk_delete_sender, lazy_disk_delete_receiver) = - channel(options.buffer_size as usize); + let (lazy_disk_writer_sender, lazy_disk_writer_receiver) = unbounded_channel(); + let (lazy_disk_delete_sender, lazy_disk_delete_receiver) = unbounded_channel(); + let lazy_disk_delete_sender = Arc::new(lazy_disk_delete_sender); + let lazy_disk_delete_sender_clone = Arc::clone(&lazy_disk_delete_sender); // Capture some variables let path = options.database_path.clone(); let disk_cache_enabled = options.disk_cache_enabled; let lazy_disk_cache = options.lazy_disk_cache; + let max_priority = options.max_priority; - // Create the buckets - for i in 0..options.max_priority { - buckets.insert(i, pq::PriorityQueue::new()); - } - - let disk_cache: Option>; - if disk_cache_enabled { - let db = Database::create(&path).unwrap(); - let db = Arc::new(db); - disk_cache = Some(db); + let disk_cache = if disk_cache_enabled { + Arc::new(Some(disk::DiskCache::new(&path))) } else { - disk_cache = None; - } + Arc::new(None) + }; + + let disk_cache_clone_one = Arc::clone(&disk_cache); + let disk_cache_clone_two = Arc::clone(&disk_cache); // Create the RPQ let rpq = RPQ { options, - non_empty_buckets: bpq::BucketPriorityQueue::new(), - buckets: Arc::new(buckets), - items_in_queues, - disk_cache, - lazy_disk_writer_sender: Arc::new(lazy_disk_writer_sender), + queue: Mutex::new(pq::PriorityQueue::new( + max_priority, + disk_cache_enabled, + lazy_disk_cache, + lazy_disk_delete_sender_clone, + disk_cache_clone_one, + )), + + disk_cache: disk_cache_clone_two, + + lazy_disk_sync_handles: Mutex::new(sync_handles), + lazy_disk_writer_sender: lazy_disk_writer_sender, lazy_disk_writer_receiver: Mutex::new(lazy_disk_writer_receiver), - lazy_disk_delete_sender: Arc::new(lazy_disk_delete_sender), + lazy_disk_delete_sender: lazy_disk_delete_sender, lazy_disk_delete_receiver: Mutex::new(lazy_disk_delete_receiver), - sync_handles: Mutex::new(sync_handles), - shutdown_receiver, - shutdown_sender, - batch_handler: Mutex::new(batch_handler), - batch_shutdown_sender: batch_shutdown_sender, - batch_shutdown_receiver: batch_shutdown_receiver, - batch_counter: Mutex::new(batch_counter), + lazy_disk_shutdown_receiver: shutdown_receiver, + lazy_disk_shutdown_sender: shutdown_sender, + lazy_disk_batch_handler: Mutex::new(batch_handler), + lazy_disk_batch_counter: Mutex::new(batch_counter), + lazy_disk_batch_shutdown_sender: batch_shutdown_sender, + lazy_disk_batch_shutdown_receiver: batch_shutdown_receiver, }; let rpq = Arc::new(rpq); // Restore the items from the disk cache let mut restored_items: usize = 0; if disk_cache_enabled { - // Create a the initial table - let ctxn = rpq.disk_cache.as_ref().unwrap().begin_write().unwrap(); - ctxn.open_table(DB).unwrap(); - ctxn.commit().unwrap(); - - let read_txn = rpq.disk_cache.as_ref().unwrap().begin_read().unwrap(); - let table = read_txn.open_table(DB).unwrap(); - - let cursor = match table.range::<&str>(..) { - Ok(range) => range, - Err(e) => { - return Err(Box::::from(e)); - } - }; - - for (_i, entry) in cursor.enumerate() { - match entry { - Ok((_key, value)) => { - let item = pq::Item::from_bytes(value.value()); - - if item.is_err() { - return Err(Box::::from(IoError::new( - ErrorKind::InvalidInput, - "Error reading from disk cache", - ))); - } - - // Mark the item as restored - let mut i = item.unwrap(); - i.set_restored(); - let result = rpq.enqueue(i).await; - if result.is_err() { - return Err(Box::::from(IoError::new( - ErrorKind::InvalidInput, - "Error enqueueing item from the disk cache", - ))); - } - restored_items += 1; - } - Err(e) => { - return Err(Box::::from(e)); - } - } + let result = rpq.restore_from_disk().await; + if result.is_err() { + return Err(Box::::from(result.err().unwrap())); } - _ = read_txn.close(); + restored_items = result?; if lazy_disk_cache { - let mut handles = rpq.sync_handles.lock().await; + let mut handles = rpq.lazy_disk_sync_handles.lock().await; let rpq_clone = Arc::clone(&rpq); handles.push(tokio::spawn(async move { let result = rpq_clone.lazy_disk_writer().await; if result.is_err() { - println!("Error in lazy disk writer: {:?}", result.err().unwrap()); + panic!("Error in lazy disk writer: {:?}", result.err().unwrap()); } })); @@ -311,7 +272,7 @@ where handles.push(tokio::spawn(async move { let result = rpq_clone.lazy_disk_deleter().await; if result.is_err() { - println!("Error in lazy disk deleter: {:?}", result.err().unwrap()); + panic!("Error in lazy disk deleter: {:?}", result.err().unwrap()); } })); } @@ -320,30 +281,11 @@ where } /// Adds an item to the RPQ and returns an error if one occurs otherwise it returns () - pub async fn enqueue(&self, mut item: pq::Item) -> Result<(), Box> { - // Check if the item priority is greater than the bucket count - if item.priority >= self.options.max_priority { - return Result::Err(Box::::from(IoError::new( - ErrorKind::InvalidInput, - "Priority is greater than bucket count", - ))); - } - let priority = item.priority; - - // Get the bucket and enqueue the item - let bucket = self.buckets.get(&item.priority); - - if bucket.is_none() { - return Result::Err(Box::::from(IoError::new( - ErrorKind::InvalidInput, - "Bucket does not exist", - ))); - } - + pub async fn enqueue(&self, mut item: schema::Item) -> Result<(), Box> { // If the disk cache is enabled, send the item to the lazy disk writer if self.options.disk_cache_enabled { // Increment the batch number - let mut batch_counter = self.batch_counter.lock().await; + let mut batch_counter = self.lazy_disk_batch_counter.lock().await; batch_counter.message_counter += 1; if batch_counter.message_counter % self.options.lazy_disk_cache_batch_size == 0 { batch_counter.batch_number += 1; @@ -356,7 +298,7 @@ where item.set_disk_uuid(); if self.options.lazy_disk_cache { let lazy_disk_writer_sender = &self.lazy_disk_writer_sender; - let was_sent = lazy_disk_writer_sender.send(item.clone()).await; + let was_sent = lazy_disk_writer_sender.send(item.clone()); match was_sent { Ok(_) => {} Err(e) => { @@ -364,65 +306,104 @@ where } } } else { - let result = self.commit_single(item.clone()); - match result { - Ok(_) => {} - Err(e) => { - return Result::Err(e); + let db = self.disk_cache.as_ref(); + match db { + None => { + return Err(Box::::from(IoError::new( + ErrorKind::InvalidInput, + "Error getting disk cache", + ))); + } + Some(db) => { + let result = db.commit_single(item.clone()); + match result { + Ok(_) => {} + Err(e) => { + return Err(Box::::from(e)); + } + } } } } } } - // Enqueue the item and update - bucket.unwrap().enqueue(item); - self.non_empty_buckets.add_bucket(priority); + // Enqueue the item + self.queue.lock().await.enqueue(item); Ok(()) } - /// Returns a Result with the next item in the RPQ or an error if one occurs - pub async fn dequeue(&self) -> Result>, Box> { - // Fetch the bucket - let bucket_id = self.non_empty_buckets.peek(); - if bucket_id.is_none() { - return Result::Err(Box::::from(IoError::new( - ErrorKind::InvalidInput, - "No items in queue", - ))); - } - let bucket_id = bucket_id.unwrap(); - - // Fetch the queue - let queue = self.buckets.get(&bucket_id); - if queue.is_none() { - return Result::Err(Box::::from(IoError::new( - ErrorKind::InvalidInput, - "No items in queue", - ))); + /// Adds a batch of items to the RPQ and returns an error if one occurs otherwise it returns () + pub async fn enqueue_batch( + &self, + mut items: Vec>, + ) -> Result<(), Box> { + let mut queue = self.queue.lock().await; + for item in items.iter_mut() { + // If the disk cache is enabled, send the item to the lazy disk writer + if self.options.disk_cache_enabled { + // Increment the batch number + let mut batch_counter = self.lazy_disk_batch_counter.lock().await; + batch_counter.message_counter += 1; + if batch_counter.message_counter % self.options.lazy_disk_cache_batch_size == 0 { + batch_counter.batch_number += 1; + } + let bn = batch_counter.batch_number; + drop(batch_counter); + + item.set_batch_id(bn); + if !item.was_restored() { + item.set_disk_uuid(); + if self.options.lazy_disk_cache { + let lazy_disk_writer_sender = &self.lazy_disk_writer_sender; + let was_sent = lazy_disk_writer_sender.send(item.clone()); + match was_sent { + Ok(_) => {} + Err(e) => { + return Err(Box::::from(e)); + } + } + } else { + let db = self.disk_cache.as_ref(); + match db { + None => { + return Err(Box::::from(IoError::new( + ErrorKind::InvalidInput, + "Error getting disk cache", + ))); + } + Some(db) => { + let result = db.commit_single(item.clone()); + match result { + Ok(_) => {} + Err(e) => { + return Err(Box::::from(e)); + } + } + } + } + } + } + } + + // Enqueue the item + queue.enqueue(item.clone()); } + Ok(()) + } - // Fetch the item from the bucket - let item = queue.unwrap().dequeue(); + /// Returns a Result with the next item in the RPQ or an error if one occurs + pub async fn dequeue(&self) -> Result>, Box> { + let item = self.queue.lock().await.dequeue(); if item.is_none() { - return Result::Err(Box::::from(IoError::new( - ErrorKind::InvalidInput, - "No items in queue", - ))); + return Ok(None); } - self.items_in_queues.fetch_sub(1, Ordering::SeqCst); let item = item.unwrap(); - // If the bucket is empty, remove it from the non_empty_buckets - if queue.unwrap().len() == 0 { - self.non_empty_buckets.remove_bucket(&bucket_id); - } - if self.options.disk_cache_enabled { - let item_clone = item.clone(); if self.options.lazy_disk_cache { let lazy_disk_delete_sender = &self.lazy_disk_delete_sender; - let was_sent = lazy_disk_delete_sender.send(item_clone).await; + let was_sent = lazy_disk_delete_sender.send(item.clone()); match was_sent { Ok(_) => {} Err(e) => { @@ -430,9 +411,30 @@ where } } } else { - let result = self.delete_single(item_clone.get_disk_uuid().unwrap().as_ref()); - if result.is_err() { - return Result::Err(result.err().unwrap()); + let id = match item.get_disk_uuid() { + Some(id) => id, + None => { + return Result::Err(Box::new(IoError::new( + ErrorKind::InvalidInput, + "Error getting disk uuid", + ))); + } + }; + + let db = self.disk_cache.as_ref(); + match db { + None => { + return Result::Err(Box::new(IoError::new( + ErrorKind::InvalidInput, + "Error getting disk cache", + ))); + } + Some(db) => { + let result = db.delete_single(&id); + if result.is_err() { + return Result::Err(result.err().unwrap()); + } + } } } } @@ -440,50 +442,151 @@ where Ok(Some(item)) } - /// Prioritize reorders the items in each bucket based on the values spesified in the item. - /// It returns a tuple with the number of items removed and the number of items escalated or and error if one occurs. - pub async fn prioritize(&self) -> Result<(usize, usize), Box> { - let mut removed: usize = 0; - let mut escalated: usize = 0; - - for (_, active_bucket) in self.buckets.iter() { - match active_bucket.prioritize() { - Ok((r, e)) => { - removed += r; - escalated += e; - } - Err(err) => { - return Err(Box::::from(err)); + /// Returns a Result with a batch of items in the RPQ or an error if one occurs + pub async fn dequeue_batch( + &self, + count: usize, + ) -> Result>>, Box> { + let mut items = Vec::new(); + let mut queue = self.queue.lock().await; + for _ in 0..count { + let item = queue.dequeue(); + if item.is_none() { + break; + } + let item = item.unwrap(); + + if self.options.disk_cache_enabled { + if self.options.lazy_disk_cache { + let lazy_disk_delete_sender = &self.lazy_disk_delete_sender; + let was_sent = lazy_disk_delete_sender.send(item.clone()); + match was_sent { + Ok(_) => {} + Err(e) => { + return Result::Err(Box::new(e)); + } + } + } else { + let id = match item.get_disk_uuid() { + Some(id) => id, + None => { + return Result::Err(Box::new(IoError::new( + ErrorKind::InvalidInput, + "Error getting disk uuid", + ))); + } + }; + + let db = self.disk_cache.as_ref(); + match db { + None => { + return Result::Err(Box::new(IoError::new( + ErrorKind::InvalidInput, + "Error getting disk cache", + ))); + } + Some(db) => { + let result = db.delete_single(&id); + if result.is_err() { + return Result::Err(result.err().unwrap()); + } + } + } } } + items.push(item); + } + if items.is_empty() { + return Ok(None); + } + Ok(Some(items)) + } + + /// Prioritize reorders the items in each bucket based on the values specified in the item. + /// It returns a tuple with the number of items removed and the number of items escalated or and error if one occurs. + pub async fn prioritize(&self) -> Result<(usize, usize), Box> { + self.queue.lock().await.prioritize() + } + + /// Returns the number of items in the RPQ across all buckets + pub async fn len(&self) -> usize { + self.queue.lock().await.items_in_queue() + } + + /// Returns the number of active buckets in the RPQ (buckets with items) + pub async fn active_buckets(&self) -> usize { + self.queue.lock().await.active_buckets() + } + + /// Returns the number of pending batches in the RPQ for both the writer or the deleter + pub async fn unsynced_batches(&self) -> usize { + let batch_handler = self.lazy_disk_batch_handler.lock().await; + batch_handler + .synced_batches + .iter() + .chain(batch_handler.deleted_batches.iter()) + .filter(|&(_, synced_or_deleted)| !*synced_or_deleted) + .count() + } + + /// Returns the number of items in the disk cache which can be helpful for debugging or monitoring + pub fn items_in_db(&self) -> usize { + if self.disk_cache.is_none() { + return 0; + } + + let db = self.disk_cache.as_ref(); + match db { + None => 0, + Some(db) => db.items_in_db(), + } + } + + /// Closes the RPQ and waits for all the async tasks to finish + pub async fn close(&self) { + self.lazy_disk_shutdown_sender.send(true).unwrap(); + + let mut handles = self.lazy_disk_sync_handles.lock().await; + while let Some(handle) = handles.pop() { + handle.await.unwrap(); } - self.items_in_queues.fetch_sub(removed, Ordering::SeqCst); - Ok((removed, escalated)) } async fn lazy_disk_writer(&self) -> Result<(), Box> { - let mut awaiting_batches = HashMap::>>::new(); - let mut ticker = interval(self.options.lazy_disk_write_delay); + let mut awaiting_batches = HashMap::>>::new(); + let mut ticker = interval(self.options.lazy_disk_write_delay.to_std().unwrap()); let mut receiver = self.lazy_disk_writer_receiver.lock().await; - let mut shutdown_receiver = self.shutdown_receiver.clone(); + let mut shutdown_receiver = self.lazy_disk_shutdown_receiver.clone(); loop { // Check if the write cache is full or the ticker has ticked tokio::select! { // Flush the cache if the ticker has ticked _ = ticker.tick() => { - let mut batch_handler = self.batch_handler.lock().await; + let mut batch_handler = self.lazy_disk_batch_handler.lock().await; for (id, batch) in awaiting_batches.iter_mut() { if batch.len() >= self.options.lazy_disk_cache_batch_size { if *batch_handler.deleted_batches.get(id).unwrap_or(&false) { batch.clear(); } else { - let result = self.commit_batch(batch); - if result.is_err() { - return Err(Box::::from(result.err().unwrap())); + let db = self.disk_cache.as_ref(); + match db { + None => { + return Result::Err(Box::new(IoError::new( + ErrorKind::InvalidInput, + "Error getting disk cache", + ))); + } + Some(db) => { + let result = db.commit_batch(batch); + if result.is_err() { + return Err(Box::::from(result.err().unwrap())); + } + } } } + batch_handler.synced_batches.insert(*id, true); batch_handler.deleted_batches.insert(*id, false); } @@ -512,7 +615,7 @@ where // Commit the remaining batches for (id, batch) in awaiting_batches.iter_mut() { - let mut batch_handler = self.batch_handler.lock().await; + let mut batch_handler = self.lazy_disk_batch_handler.lock().await; if *batch_handler.deleted_batches.get(id).unwrap_or(&false) { batch.clear(); @@ -521,12 +624,24 @@ where batch_handler.synced_batches.insert(*id, true); batch_handler.deleted_batches.insert(*id, false); - let result = self.commit_batch(batch); - if result.is_err() { - return Err(Box::::from(result.err().unwrap())); + + let db = self.disk_cache.as_ref(); + match db { + None => { + return Result::Err(Box::new(IoError::new( + ErrorKind::InvalidInput, + "Error getting disk cache", + ))); + } + Some(db) => { + let result = db.commit_batch(batch); + if result.is_err() { + return Err(Box::::from(result.err().unwrap())); + } + } } } - self.batch_shutdown_sender.send(true).unwrap(); + self.lazy_disk_batch_shutdown_sender.send(true).unwrap(); break Ok(()); } @@ -535,13 +650,12 @@ where } async fn lazy_disk_deleter(&self) -> Result<(), Box> { - let mut awaiting_batches = HashMap::>>::new(); - let mut restored_items: Vec> = Vec::new(); + let mut awaiting_batches = HashMap::>>::new(); + let mut restored_items: Vec> = Vec::new(); let mut receiver = self.lazy_disk_delete_receiver.lock().await; - let mut shutdown_receiver = self.batch_shutdown_receiver.clone(); + let mut shutdown_receiver = self.lazy_disk_batch_shutdown_receiver.clone(); loop { - // Check if the write cache is full or the ticker has ticked tokio::select! { item = receiver.recv() => { // Check if the item was restored @@ -550,29 +664,51 @@ where restored_items.push(item); if restored_items.len() >= self.options.lazy_disk_cache_batch_size { - let result = self.delete_batch(&mut restored_items); - if result.is_err() { - return Err(Box::::from(result.err().unwrap())); + let db = self.disk_cache.as_ref(); + match db { + None => { + return Result::Err(Box::new(IoError::new( + ErrorKind::InvalidInput, + "Error getting disk cache", + ))); + } + Some(db) => { + let result = db.delete_batch(&mut restored_items); + if result.is_err() { + return Err(Box::::from(result.err().unwrap())); + } + } } - restored_items.clear(); } continue; } // If the item was not restored, add it to the batch let batch_bucket = item.get_batch_id(); - let batch = awaiting_batches.entry(batch_bucket).or_insert(Vec::new()); + let mut batch = awaiting_batches.entry(batch_bucket).or_insert(Vec::new()); batch.push(item); // Check if the batch is full if batch.len() >= self.options.lazy_disk_cache_batch_size { - let mut batch_handler = self.batch_handler.lock().await; + let mut batch_handler = self.lazy_disk_batch_handler.lock().await; let was_synced = batch_handler.synced_batches.get(&batch_bucket).unwrap_or(&false); if *was_synced { - let result = self.delete_batch(batch); - if result.is_err() { - return Err(Box::::from(result.err().unwrap())); + let db = self.disk_cache.as_ref(); + match db { + None => { + return Result::Err(Box::new(IoError::new( + ErrorKind::InvalidInput, + "Error getting disk cache", + ))); + } + Some(db) => { + let result = db.delete_batch(&mut batch); + if result.is_err() { + return Err(Box::::from(result.err().unwrap())); + } + } } + awaiting_batches.remove(&batch_bucket); } else { batch.clear(); @@ -604,20 +740,41 @@ where // Commit the remaining batches if !restored_items.is_empty() { - let result = self.delete_batch(&mut restored_items); - if result.is_err() { - return Err(Box::::from(result.err().unwrap())); - } - restored_items.clear(); + let db = self.disk_cache.as_ref(); + match db { + None => { + return Result::Err(Box::new(IoError::new( + ErrorKind::InvalidInput, + "Error getting disk cache", + ))); + } + Some(db) => { + let result = db.delete_batch(&mut restored_items); + if result.is_err() { + return Err(Box::::from(result.err().unwrap())); + } + } + } } - for (id, batch) in awaiting_batches.iter_mut() { - let mut batch_handler = self.batch_handler.lock().await; + for (id, mut batch) in awaiting_batches.iter_mut() { + let mut batch_handler = self.lazy_disk_batch_handler.lock().await; let was_synced = batch_handler.synced_batches.get(id).unwrap_or(&false); if *was_synced { - let result = self.delete_batch(batch); - if result.is_err() { - return Err(Box::::from(result.err().unwrap())); - } + let db = self.disk_cache.as_ref(); + match db { + None => { + return Result::Err(Box::new(IoError::new( + ErrorKind::InvalidInput, + "Error getting disk cache", + ))); + } + Some(db) => { + let result = db.delete_batch(&mut batch); + if result.is_err() { + return Err(Box::::from(result.err().unwrap())); + } + } + } } else { batch.clear(); } @@ -631,218 +788,231 @@ where } } - fn commit_batch(&self, write_cache: &mut Vec>) -> Result<(), Box> { - let write_txn = self.disk_cache.as_ref().unwrap().begin_write().unwrap(); - for item in write_cache.iter() { - let mut table = write_txn.open_table(DB).unwrap(); - // Convert to bytes - let b = item.to_bytes(); - if b.is_err() { + async fn restore_from_disk(&self) -> Result> { + let db = self.disk_cache.as_ref(); + match db { + None => { return Err(Box::::from(IoError::new( ErrorKind::InvalidInput, - "Error converting item to bytes", + "Error getting disk cache", ))); } + Some(db) => { + let restored_items = db.return_items_from_disk(); + if restored_items.is_err() { + return Err(Box::::from(restored_items.err().unwrap())); + } + let restored_items = restored_items?; + let total_items = restored_items.len(); - let b = b.unwrap(); - let key = item.get_disk_uuid().unwrap(); + let mut queue = self.queue.lock().await; + for item in restored_items.iter() { + queue.enqueue(item.clone()); + } - let was_written = table.insert(key.as_str(), &b[..]); - if was_written.is_err() { - return Err(Box::::from(IoError::new( - ErrorKind::InvalidInput, - "Error writing item to disk cache", - ))); + Ok(total_items) } } - - write_txn.commit().unwrap(); - write_cache.clear(); - Ok(()) } +} - fn delete_batch(&self, delete_cache: &mut Vec>) -> Result<(), Box> { - let write_txn = self.disk_cache.as_ref().unwrap().begin_write().unwrap(); - for item in delete_cache.iter() { - let mut table = write_txn.open_table(DB).unwrap(); - let key = item.get_disk_uuid().unwrap(); - let was_deleted = table.remove(key.as_str()); - if was_deleted.is_err() { - return Err(Box::::from(IoError::new( - ErrorKind::InvalidInput, - "Error deleting item from disk cache", - ))); - } - } +#[cfg(test)] +mod tests { + use super::*; + use chrono::Duration; + use rand::Rng; + use std::sync::atomic::Ordering; + use std::{ + collections::VecDeque, + error::Error, + sync::atomic::{AtomicBool, AtomicUsize}, + }; - write_txn.commit().unwrap(); - delete_cache.clear(); - Ok(()) - } + #[tokio::test(flavor = "multi_thread")] + async fn order_test() { + let message_count = 1_000_000; - fn commit_single(&self, item: pq::Item) -> Result<(), Box> { - let write_txn = self.disk_cache.as_ref().unwrap().begin_write().unwrap(); - { - let mut table = write_txn.open_table(DB).unwrap(); - let b = item.to_bytes(); + let options = schema::RPQOptions { + max_priority: 10, + disk_cache_enabled: false, + database_path: "/tmp/rpq-order.redb".to_string(), + lazy_disk_cache: false, + lazy_disk_write_delay: Duration::seconds(5), + lazy_disk_cache_batch_size: 5_000, + }; - if b.is_err() { - return Err(Box::::from(IoError::new( - ErrorKind::InvalidInput, - "Error converting item to bytes", - ))); - } + let r: Result<(Arc>, usize), Box> = RPQ::new(options).await; + assert!(r.is_ok()); + let (rpq, _restored_items) = r.unwrap(); - let key = item.get_disk_uuid().unwrap(); - let b = b.unwrap(); + let mut expected_data = HashMap::new(); + for i in 0..message_count { + let item = schema::Item::new(i % 10, i, false, None, false, Some(Duration::seconds(5))); + let result = rpq.enqueue(item).await; + assert!(result.is_ok()); + let v = expected_data.entry(i % 10).or_insert(VecDeque::new()); + v.push_back(i); + } - let was_written = table.insert(key.as_str(), &b[..]); - if was_written.is_err() { - return Err(Box::::from(IoError::new( - ErrorKind::InvalidInput, - "Error writing item to disk cache", - ))); - } + for _i in 0..message_count { + let item = rpq.dequeue().await; + assert!(item.is_ok()); + let item = item.unwrap().unwrap(); + let v = expected_data.get_mut(&item.priority).unwrap(); + let expected_data = v.pop_front().unwrap(); + assert!(item.data == expected_data); } - write_txn.commit().unwrap(); - Ok(()) + rpq.close().await; + assert_eq!(rpq.len().await, 0); } - fn delete_single(&self, key: &str) -> Result<(), Box> { - let write_txn = self.disk_cache.as_ref().unwrap().begin_write().unwrap(); - { - let mut table = write_txn.open_table(DB).unwrap(); - let was_written = table.remove(key); - if was_written.is_err() { - return Err(Box::::from(IoError::new( - ErrorKind::InvalidInput, - "Error deleting item from disk cache", - ))); - } - } + #[tokio::test(flavor = "multi_thread")] + async fn prioritize_test() { + let message_count = 1_000_000; + let sent_counter = Arc::new(AtomicUsize::new(0)); + let received_counter = Arc::new(AtomicUsize::new(0)); + let removed_counter = Arc::new(AtomicUsize::new(0)); + let total_escalated = Arc::new(AtomicUsize::new(0)); - write_txn.commit().unwrap(); - Ok(()) - } + let options = schema::RPQOptions { + max_priority: 10, + disk_cache_enabled: true, + database_path: "/tmp/rpq-prioritize.redb".to_string(), + lazy_disk_cache: true, + lazy_disk_write_delay: Duration::seconds(5), + lazy_disk_cache_batch_size: 5_000, + }; - /// Returns the number of items in the RPQ across all buckets - pub async fn len(&self) -> usize { - let mut len = 0 as usize; - for (_, active_bucket) in self.buckets.iter() { - len += active_bucket.len(); - } - len - } + let r: Result<(Arc>, usize), Box> = RPQ::new(options).await; + assert!(r.is_ok()); + let (rpq, _restored_items) = r.unwrap(); - /// Returns the number of active buckets in the RPQ (buckets with items) - pub fn active_buckets(&self) -> usize { - self.non_empty_buckets.len() - } + let rpq_clone = Arc::clone(&rpq); + let (shutdown_sender, mut shutdown_receiver) = watch::channel(false); + let removed_clone = Arc::clone(&removed_counter); + let escalated_clone = Arc::clone(&total_escalated); + tokio::spawn(async move { + tokio::select! { + _ = shutdown_receiver.changed() => { + return; + }, + _ = async { + loop { + tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; + let results = rpq_clone.prioritize().await; - /// Returns the number of pending batches in the RPQ for both the writer or the deleter - pub async fn unsynced_batches(&self) -> usize { - let mut unsynced_batches = 0; - let batch_handler = self.batch_handler.lock().await; - for (_, synced) in batch_handler.synced_batches.iter() { - if !*synced { - unsynced_batches += 1; - } - } - for (_, deleted) in batch_handler.deleted_batches.iter() { - if !*deleted { - unsynced_batches += 1; + if results.is_ok() { + let (removed, escalated) = results.unwrap(); + removed_clone.fetch_add(removed, Ordering::SeqCst); + escalated_clone.fetch_add(escalated, Ordering::SeqCst); + } else { + println!("Error: {:?}", results.err().unwrap()); + } + } + } => {} } - } - unsynced_batches - } + }); - /// Returns the number of items in the disk cache which can be helpful for debugging or monitoring - pub fn items_in_db(&self) -> usize { - if self.disk_cache.is_none() { - return 0; + for i in 0..message_count { + let item = schema::Item::new( + i % 10, + i, + true, + Some(Duration::seconds(rand::thread_rng().gen_range(1..10))), + true, + Some(Duration::seconds(10)), + ); + let result = rpq.enqueue(item).await; + assert!(result.is_ok()); + sent_counter.fetch_add(1, Ordering::SeqCst); } - let read_txn = self.disk_cache.as_ref().unwrap().begin_read().unwrap(); - let table = read_txn.open_table(DB).unwrap(); - let count = table.len().unwrap(); - count as usize - } - /// Closes the RPQ and waits for all the async tasks to finish - pub async fn close(&self) { - self.shutdown_sender.send(true).unwrap(); + loop { + if removed_counter.load(Ordering::SeqCst) + received_counter.load(Ordering::SeqCst) + == sent_counter.load(Ordering::SeqCst) + { + break; + } - let mut handles = self.sync_handles.lock().await; - while let Some(handle) = handles.pop() { - handle.await.unwrap(); + tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; + let item = rpq.dequeue().await; + assert!(item.is_ok()); + let item = item.unwrap(); + if item.is_none() { + continue; + } + received_counter.fetch_add(1, Ordering::SeqCst); } - } -} -#[cfg(test)] -mod tests { - use super::*; - use core::time; - use std::{ - collections::VecDeque, - error::Error, - sync::atomic::{AtomicBool, AtomicUsize}, - }; + shutdown_sender.send(true).unwrap(); + rpq.close().await; + assert_eq!(rpq.len().await, 0); + assert_eq!(rpq.items_in_db(), 0); + println!( + "Sent: {}, Received: {}, Removed: {}, Escalated: {}", + sent_counter.load(Ordering::SeqCst), + received_counter.load(Ordering::SeqCst), + removed_counter.load(Ordering::SeqCst), + total_escalated.load(Ordering::SeqCst) + ); + } #[tokio::test(flavor = "multi_thread")] - async fn order_test() { - let message_count = 1_000_000; + async fn disk_write_test() { + let message_count = 500_000; - let options = RPQOptions { + let options = schema::RPQOptions { max_priority: 10, - disk_cache_enabled: false, - database_path: "/tmp/rpq.redb".to_string(), - lazy_disk_cache: false, - lazy_disk_write_delay: time::Duration::from_secs(5), - lazy_disk_cache_batch_size: 5000, - buffer_size: 1_000_000, + disk_cache_enabled: true, + database_path: "/tmp/rpq-write.redb".to_string(), + lazy_disk_cache: true, + lazy_disk_write_delay: Duration::seconds(1), + lazy_disk_cache_batch_size: 5_000, }; let r: Result<(Arc>, usize), Box> = RPQ::new(options).await; - if r.is_err() { - panic!("Error creating RPQ"); - } + assert!(r.is_ok()); let (rpq, _restored_items) = r.unwrap(); let mut expected_data = HashMap::new(); for i in 0..message_count { - let item = pq::Item::new( + let item = schema::Item::new( i % 10, i, - false, - None, - false, - Some(std::time::Duration::from_secs(5)), + true, + Some(Duration::seconds(1)), + true, + Some(Duration::seconds(5)), ); let result = rpq.enqueue(item).await; - if result.is_err() { - panic!("Error enqueueing item"); - } + assert!(result.is_ok()); let v = expected_data.entry(i % 10).or_insert(VecDeque::new()); v.push_back(i); } + tokio::time::sleep(tokio::time::Duration::from_secs(10)).await; + assert!(rpq.len().await == message_count); + assert!(rpq.items_in_db() != 0); + for _i in 0..message_count { let item = rpq.dequeue().await; - if item.is_err() { - panic!("Item is None"); - } + assert!(item.is_ok()); let item = item.unwrap().unwrap(); let v = expected_data.get_mut(&item.priority).unwrap(); let expected_data = v.pop_front().unwrap(); assert!(item.data == expected_data); } + + rpq.close().await; + assert_eq!(rpq.len().await, 0); + assert_eq!(rpq.items_in_db(), 0); } #[tokio::test(flavor = "multi_thread")] - async fn e2e_test() { + async fn e2e_no_batch() { // Set Message Count - let message_count = 10_000_000 as usize; + let message_count = 10_000_250 as usize; // Set Concurrency let send_threads = 4 as usize; @@ -852,23 +1022,19 @@ mod tests { let received_counter = Arc::new(AtomicUsize::new(0)); let removed_counter = Arc::new(AtomicUsize::new(0)); let total_escalated = Arc::new(AtomicUsize::new(0)); - let finshed_sending = Arc::new(AtomicBool::new(false)); - let max_retries = 1000; + let finished_sending = Arc::new(AtomicBool::new(false)); // Create the RPQ - let options = RPQOptions { + let options = schema::RPQOptions { max_priority: bucket_count, disk_cache_enabled: true, - database_path: "/tmp/rpq.redb".to_string(), + database_path: "/tmp/rpq-e2e-nobatch.redb".to_string(), lazy_disk_cache: true, - lazy_disk_write_delay: time::Duration::from_secs(5), - lazy_disk_cache_batch_size: 10000, - buffer_size: 1_000_000, + lazy_disk_write_delay: Duration::seconds(5), + lazy_disk_cache_batch_size: 10_000, }; let r = RPQ::new(options).await; - if r.is_err() { - panic!("Error creating RPQ"); - } + assert!(r.is_ok()); let (rpq, restored_items) = r.unwrap(); // Launch the monitoring thread @@ -883,7 +1049,7 @@ mod tests { }, _ = async { loop { - tokio::time::sleep(time::Duration::from_secs(10)).await; + tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; let results = rpq_clone.prioritize().await; if !results.is_ok() { @@ -901,7 +1067,6 @@ mod tests { // Enqueue items println!("Launching {} Send Threads", send_threads); let mut send_handles = Vec::new(); - let send_timer = std::time::Instant::now(); for _ in 0..send_threads { let rpq_clone = Arc::clone(&rpq); let sent_clone = Arc::clone(&sent_counter); @@ -912,43 +1077,37 @@ mod tests { break; } - let item = pq::Item::new( - //rand::thread_rng().gen_range(0..bucket_count), + let item = schema::Item::new( sent_clone.load(Ordering::SeqCst) % bucket_count, 0, - false, - None, - false, - Some(std::time::Duration::from_secs(5)), + true, + Some(Duration::seconds(1)), + true, + Some(Duration::seconds(5)), ); let result = rpq_clone.enqueue(item).await; - if result.is_err() { - panic!("Error enqueueing item"); - } + assert!(result.is_ok()); sent_clone.fetch_add(1, Ordering::SeqCst); } - println!("Finished Sending"); })); } // Dequeue items println!("Launching {} Receive Threads", receive_threads); let mut receive_handles = Vec::new(); - let receive_timer = std::time::Instant::now(); for _ in 0..receive_threads { // Clone all the shared variables let rpq_clone = Arc::clone(&rpq); let received_clone = Arc::clone(&received_counter); let sent_clone = Arc::clone(&sent_counter); let removed_clone = Arc::clone(&removed_counter); - let finshed_sending_clone = Arc::clone(&finshed_sending); + let finished_sending_clone = Arc::clone(&finished_sending); // Spawn the thread receive_handles.push(tokio::spawn(async move { - let mut counter = 0; loop { - if finshed_sending_clone.load(Ordering::SeqCst) { + if finished_sending_clone.load(Ordering::SeqCst) { if received_clone.load(Ordering::SeqCst) + removed_clone.load(Ordering::SeqCst) >= sent_clone.load(Ordering::SeqCst) + restored_items @@ -958,15 +1117,10 @@ mod tests { } let item = rpq_clone.dequeue().await; - if item.is_err() { - if counter >= max_retries { - panic!("Reached max retries waiting for items!"); - } - counter += 1; - std::thread::sleep(time::Duration::from_millis(100)); + assert!(item.is_ok()); + if item.unwrap().is_none() { continue; } - counter = 0; received_clone.fetch_add(1, Ordering::SeqCst); } })); @@ -976,34 +1130,182 @@ mod tests { for handle in send_handles { handle.await.unwrap(); } - let send_time = send_timer.elapsed().as_secs_f64(); - finshed_sending.store(true, Ordering::SeqCst); + finished_sending.store(true, Ordering::SeqCst); // Wait for receive threads to finish for handle in receive_handles { handle.await.unwrap(); } - let receive_time = receive_timer.elapsed().as_secs_f64(); shutdown_sender.send(true).unwrap(); + println!("Total Time: {}s", total_timer.elapsed().as_secs_f64()); // Close the RPQ println!("Waiting for RPQ to close"); rpq.close().await; println!( - "Sent: {}, Received: {}, Removed: {}, Escalated: {}", + "Sent: {}, Received: {}, Removed: {}, Escalated: {} Restored: {:?}", sent_counter.load(Ordering::SeqCst), received_counter.load(Ordering::SeqCst), removed_counter.load(Ordering::SeqCst), - total_escalated.load(Ordering::SeqCst) + total_escalated.load(Ordering::SeqCst), + restored_items ); + + assert_eq!(rpq.items_in_db(), 0); + } + + #[tokio::test(flavor = "multi_thread")] + async fn e2e_batch() { + // Set Message Count + let message_count = 10_000_250 as usize; + + // Set Concurrency + let send_threads = 4 as usize; + let receive_threads = 4 as usize; + let bucket_count = 10 as usize; + let sent_counter = Arc::new(AtomicUsize::new(0)); + let received_counter = Arc::new(AtomicUsize::new(0)); + let removed_counter = Arc::new(AtomicUsize::new(0)); + let total_escalated = Arc::new(AtomicUsize::new(0)); + let finshed_sending = Arc::new(AtomicBool::new(false)); + + // Create the RPQ + let options = schema::RPQOptions { + max_priority: bucket_count, + disk_cache_enabled: true, + database_path: "/tmp/rpq-e2e-batch.redb".to_string(), + lazy_disk_cache: true, + lazy_disk_write_delay: Duration::seconds(5), + lazy_disk_cache_batch_size: 10_000, + }; + let r = RPQ::new(options).await; + assert!(r.is_ok()); + let (rpq, restored_items) = r.unwrap(); + + // Launch the monitoring thread + let rpq_clone = Arc::clone(&rpq); + let (shutdown_sender, mut shutdown_receiver) = watch::channel(false); + let removed_clone = Arc::clone(&removed_counter); + let escalated_clone = Arc::clone(&total_escalated); + tokio::spawn(async move { + tokio::select! { + _ = shutdown_receiver.changed() => { + return; + }, + _ = async { + loop { + tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; + let results = rpq_clone.prioritize().await; + + if !results.is_ok() { + let (removed, escalated) = results.unwrap(); + removed_clone.fetch_add(removed, Ordering::SeqCst); + escalated_clone.fetch_add(escalated, Ordering::SeqCst); + } + } + } => {} + } + }); + + let total_timer = std::time::Instant::now(); + + // Enqueue items + println!("Launching {} Batch Send Threads", send_threads); + let mut send_handles = Vec::new(); + for _ in 0..send_threads { + let rpq_clone = Arc::clone(&rpq); + let sent_clone = Arc::clone(&sent_counter); + + send_handles.push(tokio::spawn(async move { + loop { + if sent_clone.load(Ordering::SeqCst) >= message_count { + break; + } + + let mut batch = Vec::new(); + for i in 0..1000 { + let item = schema::Item::new( + sent_clone.load(Ordering::SeqCst) % bucket_count, + i, + true, + Some(Duration::seconds(1)), + true, + Some(Duration::seconds(5)), + ); + + batch.push(item); + sent_clone.fetch_add(1, Ordering::SeqCst); + } + + let result = rpq_clone.enqueue_batch(batch).await; + assert!(result.is_ok()); + } + println!("Finished Sending"); + })); + } + + // Dequeue items + println!("Launching {} Batch Receive Threads", receive_threads); + let mut receive_handles = Vec::new(); + for _ in 0..receive_threads { + // Clone all the shared variables + let rpq_clone = Arc::clone(&rpq); + let received_clone = Arc::clone(&received_counter); + let sent_clone = Arc::clone(&sent_counter); + let removed_clone = Arc::clone(&removed_counter); + let finished_sending_clone = Arc::clone(&finshed_sending); + + // Spawn the thread + receive_handles.push(tokio::spawn(async move { + loop { + if finished_sending_clone.load(Ordering::SeqCst) { + if received_clone.load(Ordering::SeqCst) + + removed_clone.load(Ordering::SeqCst) + >= sent_clone.load(Ordering::SeqCst) + restored_items + { + break; + } + } + + let item = rpq_clone.dequeue_batch(1000).await; + assert!(item.is_ok()); + let item = item.unwrap(); + if item.is_none() { + continue; + } + for _i in item.unwrap() { + received_clone.fetch_add(1, Ordering::SeqCst); + } + } + })); + } + + // Wait for send threads to finish + for handle in send_handles { + handle.await.unwrap(); + } + + finshed_sending.store(true, Ordering::SeqCst); + // Wait for receive threads to finish + for handle in receive_handles { + handle.await.unwrap(); + } + shutdown_sender.send(true).unwrap(); + println!("Total Time: {}s", total_timer.elapsed().as_secs_f64()); println!( - "Send Time: {}s, Receive Time: {}s, Total Time: {}s", - send_time, - receive_time, - total_timer.elapsed().as_secs_f64() + "Sent: {}, Received: {}, Removed: {}, Escalated: {} Restored: {}", + sent_counter.load(Ordering::SeqCst), + received_counter.load(Ordering::SeqCst), + removed_counter.load(Ordering::SeqCst), + total_escalated.load(Ordering::SeqCst), + restored_items ); + // Close the RPQ + println!("Waiting for RPQ to close"); + rpq.close().await; + assert_eq!(rpq.items_in_db(), 0); } } diff --git a/src/pq.rs b/src/pq.rs index eeebb3c..badf99f 100644 --- a/src/pq.rs +++ b/src/pq.rs @@ -1,259 +1,200 @@ +use std::collections::BTreeSet; +use std::collections::VecDeque; use std::error::Error; -use std::time::Duration; -use std::{collections::VecDeque, sync::RwLock}; -use std::{io::Error as IoError, io::ErrorKind as IoErrorKind}; +use std::time::Duration as StdDuration; +use std::{sync::Arc, vec::Vec}; -use bincode::{deserialize, serialize}; -use chrono::{DateTime, Utc}; use serde::de::DeserializeOwned; -use serde::{Deserialize, Serialize}; +use serde::Serialize; +use tokio::sync::mpsc::UnboundedSender; mod ftime; +use crate::disk::DiskCache; +use crate::schema::Item; /// PriorityQueue is a struct that holds methods for inserting, removing, and prioritizing items /// in a queue. Items are stored in a VecDeque and are prioritized based on metadata provided by the user. /// Items can be escalated or timed out based on the should_escalate and can_timeout fields. -pub struct PriorityQueue { - items: RwLock>>, - ftime: ftime::CachedTime, +pub struct PriorityQueue { + items: Vec>>, + active_buckets: BTreeSet, + ftime: Arc, + len: usize, + db: Arc>>, + disk_enabled: bool, + lazy_disk_enabled: bool, + lazy_disk_deleter: Arc>>, } -impl PriorityQueue { +impl PriorityQueue { /// This function creates a new PriorityQueue. - pub fn new() -> PriorityQueue { - PriorityQueue { - items: RwLock::new(VecDeque::new()), - ftime: ftime::CachedTime::new(Duration::from_millis(50)), + pub fn new( + buckets: usize, + disk_enabled: bool, + lazy_disk_enabled: bool, + lazy_disk_deleter: Arc>>, + db: Arc>>, + ) -> PriorityQueue { + let mut pq = PriorityQueue { + items: Vec::new(), + active_buckets: BTreeSet::new(), + ftime: ftime::CachedTime::new(StdDuration::from_millis(50)), + len: 0 as usize, + disk_enabled, + lazy_disk_enabled, + lazy_disk_deleter, + db, + }; + + for i in 0..buckets { + pq.items.insert(i, VecDeque::new()); } + + pq } /// Returns the number of items in this queue - pub fn len(&self) -> usize { - self.items.read().unwrap().len() + pub fn items_in_queue(&self) -> usize { + self.len + } + + pub fn active_buckets(&self) -> usize { + self.active_buckets.len() } /// Adds an item to the queue at the end of the VecDeque - pub fn enqueue(&self, item: Item) { + pub fn enqueue(&mut self, item: Item) { let mut item = item; - // Set the internal fields item.submitted_at = self.ftime.get_time().into(); item.last_escalation = None; - // Add the item to the queue - self.items.write().unwrap().push_back(item); + // Insert the item into the queue + let priority = item.priority; + self.active_buckets.insert(priority); + self.items.get_mut(priority).unwrap().push_back(item); + self.len += 1; } /// Removes and returns the item with the highest priority - pub fn dequeue(&self) -> Option> { - self.items.write().unwrap().pop_front() + pub fn dequeue(&mut self) -> Option> { + // This should really only ever loop once if the first pulled bucket is a miss + loop { + let bucket = self.active_buckets.first(); + if bucket.is_none() { + return None; + } + let item = self.items.get_mut(*bucket.unwrap()).unwrap().pop_front(); + if item.is_none() { + self.active_buckets.pop_first(); + continue; + } + self.len -= 1; + return item; + } } /// Prioritizes the items in the queue based on the priority, escalation rate, and timeout /// Returns a tuple of the number of items removed and the number of items swapped - pub fn prioritize(&self) -> Result<(usize, usize), Box> { - let mut items = self.items.write().unwrap(); - let mut to_remove = Vec::new(); - let mut to_swap = Vec::new(); - let mut was_error = false; - - for (index, item) in items.iter_mut().enumerate() { - // Timeout items that have been in the queue for too long - if item.can_timeout { - if let (Some(timeout), Some(submitted_at)) = (item.timeout, item.submitted_at) { - let current_time_millis = self.ftime.get_time().timestamp_millis(); - let submitted_time_millis = submitted_at.timestamp_millis(); - let elapsed_time = current_time_millis - submitted_time_millis; - - // Downcast u128 to i64 to compare with the timeout - if timeout.as_millis() <= i64::MAX as u128 { - if elapsed_time >= timeout.as_millis() as i64 { - to_remove.push(index); - continue; + pub fn prioritize(&mut self) -> Result<(usize, usize), Box> + where + T: Serialize + DeserializeOwned, + { + let mut removed = 0 as usize; + let mut swapped = 0 as usize; + + for (_, bucket) in self.items.iter_mut().enumerate() { + bucket.retain(|item| { + let mut keep = true; + + // Timeout items that have been in the queue for too long + if item.can_timeout { + if let (Some(timeout), Some(submitted_at)) = (item.timeout, item.submitted_at) { + let current_time = self.ftime.get_time(); + let elapsed = current_time - submitted_at; + + if elapsed >= timeout { + keep = false; + removed += 1; + self.len -= 1; + + if self.disk_enabled { + let db = self.db.as_ref(); + match db { + Some(db) => { + if self.lazy_disk_enabled { + self.lazy_disk_deleter.send(item.clone()).unwrap(); + } else { + let _ = db.delete_single( + item.get_disk_uuid().as_ref().unwrap(), + ); + } + } + None => {} + } + } } - } else { - was_error = true; } } - } - - // Escalate items that have been in the queue for too long - if item.should_escalate { - let current_time_millis = self.ftime.get_time().timestamp_millis(); - let submitted_time_millis = item.submitted_at.unwrap().timestamp_millis(); - let escalation_rate_millis = item.escalation_rate.unwrap().as_millis(); - - // Downcast u128 to i64 to compare with the timeout - if !item.timeout.unwrap().as_millis() <= i64::MAX as u128 { - // Check if we have ever escalated this item - if item.last_escalation.is_none() { - let elapsed_time = current_time_millis - submitted_time_millis; - - if elapsed_time > escalation_rate_millis as i64 { - item.last_escalation = Some(self.ftime.get_time()); - if index > 0 { - to_swap.push(index); + keep + }); + + let mut index = 0; + let mut last_item_was_escalated = false; + let mut last_last_was_escalated = false; + + while index < bucket.len() { + let item = bucket.get_mut(index).unwrap(); + + if item.should_escalate { + if item.submitted_at.is_some() && item.escalation_rate.is_some() { + let current_time = self.ftime.get_time(); + let context = (!last_item_was_escalated && !last_last_was_escalated) + || (last_item_was_escalated && !last_last_was_escalated); + + // Check if we have ever escalated this item + if item.last_escalation.is_none() { + let elapsed_time = current_time - item.submitted_at.unwrap(); + + if elapsed_time >= item.escalation_rate.unwrap() { + if context { + item.last_escalation = Some(self.ftime.get_time()); + if index > 0 { + bucket.swap(index, index - 1); + } + last_last_was_escalated = last_item_was_escalated; + last_item_was_escalated = true; + swapped += 1; + } + } else { + last_last_was_escalated = last_item_was_escalated; + last_item_was_escalated = false; } - } - } else { - let last_escalation_time_millis = - item.last_escalation.unwrap().timestamp_millis(); - let time_since_last_escalation = - current_time_millis - last_escalation_time_millis; - // Check if we need to escalate this item again - if time_since_last_escalation >= escalation_rate_millis as i64 { - item.last_escalation = Some(self.ftime.get_time()); - if index > 0 { - to_swap.push(index); + // We have escalated this item before + } else { + let elapsed_time = current_time - item.last_escalation.unwrap(); + if elapsed_time >= item.escalation_rate.unwrap() { + if context { + item.last_escalation = Some(self.ftime.get_time()); + if index > 0 { + bucket.swap(index, index - 1); + } + last_last_was_escalated = last_item_was_escalated; + last_item_was_escalated = true; + swapped += 1; + } + } else { + last_last_was_escalated = last_item_was_escalated; + last_item_was_escalated = false; } } } - } else { - was_error = true; } + index += 1; } } - let removed = to_remove.len(); - let swapped = to_swap.len(); - - // Perform removals and swaps - for index in to_remove.iter().rev() { - items.remove(*index); - } - for index in to_swap { - items.swap(index, index - 1); - } - - if was_error { - return Err(Box::::from(IoError::new( - IoErrorKind::InvalidInput, - "Timeout or escalation rate is too large", - ))); - } - Ok((removed, swapped)) } } - -/// Item holds the data that you want to store along with the metadata needed to manage the item. -/// The priority field is used to determine the order in which items are dequeued. The lower the -/// value, the higher the priority. Items will NOT escalate to a new priority level but instead -/// items will be escalated up or down within there same priority level. AKA, items are not promoted -/// to a higher priority level no matter how long they are in the queue. -#[derive(Serialize, Deserialize, Clone)] -pub struct Item { - // User-provided fields - /// The priority of the item. Lower values are higher priority. - /// Be sure that this value does not exceed the max_priority value set when creating the queue. - pub priority: usize, - /// The data associated with the item. - pub data: T, - /// Whether the item should be escalated over time. - pub should_escalate: bool, - /// The rate at which the item should be escalated. - pub escalation_rate: Option, - /// Whether the item should be timed out. - pub can_timeout: bool, - /// The timeout duration for the item. - pub timeout: Option, - - // Internal - disk_uuid: Option, - submitted_at: Option>, - last_escalation: Option>, - batch_id: usize, - was_restored: bool, -} - -impl Item { - /// This function creates a new Item with the provided fields. - pub fn new( - priority: usize, - data: T, - should_escalate: bool, - escalation_rate: Option, - can_timeout: bool, - timeout: Option, - ) -> Self { - Item { - // User-provided fields - priority, - data, - should_escalate, - escalation_rate, - can_timeout, - timeout, - - // Private with fn access - batch_id: 0, - was_restored: false, - disk_uuid: None, - - // Internal fields - submitted_at: None, - last_escalation: None, - } - } - - // This function is for internal use only. It sets the disk_uuid field to a random UUID. - pub fn set_disk_uuid(&mut self) { - self.disk_uuid = Some(uuid::Uuid::new_v4().to_string()); - } - - // This function is for internal use only. It returns the disk_uuid field. - pub fn get_disk_uuid(&self) -> Option { - self.disk_uuid.clone() - } - - /// This function is for internal use only. It sets the batch_id field. - pub fn set_batch_id(&mut self, batch_id: usize) { - self.batch_id = batch_id; - } - - /// This function is for internal use only. It returns the batch_id field. - pub fn get_batch_id(&self) -> usize { - self.batch_id - } - - /// This function is for internal use only. It sets the was_restored field to true. - pub fn set_restored(&mut self) { - self.was_restored = true; - } - - /// This function is for internal use only. It returns the was_restored field. - pub fn was_restored(&self) -> bool { - self.was_restored - } - - /// This function is for internal use only. It returns creates a new Item from a serialized byte array. - pub fn from_bytes(bytes: &[u8]) -> Result, Box> - where - T: Serialize + DeserializeOwned, - { - let b = bytes.to_vec(); - if b.is_empty() { - return Err(Box::::from(IoError::new( - IoErrorKind::InvalidInput, - "Empty byte array", - ))); - } - Ok(deserialize(&b).unwrap()) - } - - /// This function is for internal use only. It returns a serialized byte array from an Item. - pub fn to_bytes(&self) -> Result, Box> - where - T: Serialize + DeserializeOwned, - { - let b = serialize(&self).unwrap(); - if b.is_empty() { - return Err(Box::::from(IoError::new( - IoErrorKind::InvalidInput, - "Empty byte array", - ))); - } - Ok(b) - } -} diff --git a/src/pq/ftime.rs b/src/pq/ftime.rs index 57735d3..b2ef346 100644 --- a/src/pq/ftime.rs +++ b/src/pq/ftime.rs @@ -1,32 +1,39 @@ use chrono::{DateTime, Utc}; use std::sync::Arc; +use std::sync::RwLock; use std::time::Duration; use tokio::time::sleep; #[derive(Clone)] pub struct CachedTime { - time: Arc>, + time: Arc>>, } impl CachedTime { - pub fn new(update_interval: Duration) -> Self { + pub fn new(update_interval: Duration) -> Arc { let cached_time = CachedTime { - time: Arc::new(Utc::now()), + time: Arc::new(RwLock::new(Utc::now())), }; + let arc = Arc::new(cached_time); + let arc_clone = arc.clone(); - let mut clone = cached_time.clone(); - clone.time = Arc::new(Utc::now()); tokio::spawn(async move { loop { sleep(update_interval).await; - clone.time = Arc::new(Utc::now()); + arc_clone.update_time(); } }); - cached_time + arc + } + + pub fn update_time(&self) { + let mut time = self.time.write().unwrap(); + let new_time = Utc::now(); + *time = new_time; } pub fn get_time(&self) -> DateTime { - self.time.as_ref().clone().into() + self.time.read().unwrap().clone() } } diff --git a/src/schema.rs b/src/schema.rs new file mode 100644 index 0000000..3f46b9a --- /dev/null +++ b/src/schema.rs @@ -0,0 +1,178 @@ +use std::error::Error; +use std::io::Error as IoError; +use std::io::ErrorKind as IoErrorKind; + +use bincode::{deserialize, serialize}; +use chrono::{DateTime, Duration, Utc}; +use serde::de::DeserializeOwned; +use serde::{Deserialize, Serialize}; +use serde_with::{serde_as, DurationMilliSeconds}; + +/// RPQOptions is the configuration for the RPQ +pub struct RPQOptions { + /// Holds the number of priorities(buckets) that this RPQ will accept for this queue. + pub max_priority: usize, + /// Enables or disables the disk cache using redb as the backend to store items + pub disk_cache_enabled: bool, + /// Holds the path to where the disk cache database will be persisted + pub database_path: String, + /// Enables or disables lazy disk writes and deletes. The speed can be quite variable depending + /// on the disk itself and how often you are emptying the queue in combination with the write delay + pub lazy_disk_cache: bool, + /// Sets the delay between lazy disk writes. This delays items from being commit'ed to the disk cache. + /// If you are pulling items off the queue faster than this delay, many times can be skip the write to disk, + /// massively increasing the throughput of the queue. + pub lazy_disk_write_delay: Duration, + /// Sets the number of items that will be written to the disk cache in a single batch. This can be used to + /// tune the performance of the disk cache depending on your specific workload. + pub lazy_disk_cache_batch_size: usize, +} + +/// Item holds the data that you want to store along with the metadata needed to manage the item. +/// The priority field is used to determine the order in which items are dequeued. The lower the +/// value, the higher the priority. Items will NOT escalate to a new priority level but instead +/// items will be escalated up or down within there same priority level. AKA, items are not promoted +/// to a higher priority level no matter how long they are in the queue. +#[serde_as] +#[derive(Serialize, Deserialize, Clone)] +pub struct Item { + // User-provided fields + /// The priority of the item. Lower values are higher priority. + /// Be sure that this value does not exceed the max_priority value set when creating the queue. + pub priority: usize, + /// The data associated with the item. + pub data: T, + /// Whether the item should be escalated over time. + pub should_escalate: bool, + /// The rate at which the item should be escalated. + #[serde_as(as = "Option>")] + pub escalation_rate: Option, + /// Whether the item should be timed out. + pub can_timeout: bool, + /// The timeout duration for the item. + #[serde_as(as = "Option>")] + pub timeout: Option, + + // Internal + /// INTERNAL USE ONLY: The UUID of the item when it is stored on disk. + pub disk_uuid: Option, + /// INTERNAL USE ONLY: The time the item was submitted to the queue. + pub submitted_at: Option>, + /// INTERNAL USE ONLY: The last time the item was escalated. + pub last_escalation: Option>, + /// INTERNAL USE ONLY: The batch_id of the item if committed to disk in a batch. + pub batch_id: usize, + /// INTERNAL USE ONLY: Whether the item was restored from disk. + pub was_restored: bool, +} + +impl Item { + /// This function creates a new Item with the provided fields. + pub fn new( + priority: usize, + data: T, + should_escalate: bool, + escalation_rate: Option, + can_timeout: bool, + timeout: Option, + ) -> Self { + Item { + // User-provided fields + priority, + data, + should_escalate, + escalation_rate, + can_timeout, + timeout, + + // Private with fn access + batch_id: 0, + was_restored: false, + disk_uuid: None, + + // Internal fields + submitted_at: None, + last_escalation: None, + } + } + + // This function is for internal use only. It sets the disk_uuid field to a random UUID. + pub fn set_disk_uuid(&mut self) { + self.disk_uuid = Some(uuid::Uuid::new_v4().to_string()); + } + + // This function is for internal use only. It returns the disk_uuid field. + pub fn get_disk_uuid(&self) -> Option { + self.disk_uuid.clone() + } + + /// This function is for internal use only. It sets the batch_id field. + pub fn set_batch_id(&mut self, batch_id: usize) { + self.batch_id = batch_id; + } + + /// This function is for internal use only. It returns the batch_id field. + pub fn get_batch_id(&self) -> usize { + self.batch_id + } + + /// This function is for internal use only. It sets the was_restored field to true. + pub fn set_restored(&mut self) { + self.was_restored = true; + } + + /// This function is for internal use only. It returns the was_restored field. + pub fn was_restored(&self) -> bool { + self.was_restored + } + + /// This function is for internal use only. It returns creates a new Item from a serialized byte array. + pub fn from_bytes(bytes: &[u8]) -> Result, Box> + where + T: Serialize + DeserializeOwned, + { + let b = bytes.to_vec(); + if b.is_empty() { + return Err(Box::::from(IoError::new( + IoErrorKind::InvalidInput, + "Empty byte array", + ))); + } + + let d = deserialize(&b); + match d { + Err(e) => { + return Err(Box::::from(IoError::new( + IoErrorKind::InvalidInput, + format!("Failed to deserialize item: {}", e), + ))); + } + _ => {} + } + + Ok(d.unwrap()) + } + + /// This function is for internal use only. It returns a serialized byte array from an Item. + pub fn to_bytes(&self) -> Result, Box> + where + T: Serialize + DeserializeOwned, + { + let b = serialize(&self); + if b.is_err() { + return Err(Box::::from(IoError::new( + IoErrorKind::InvalidInput, + "Failed to serialize item", + ))); + } + let b = b.unwrap(); + if b.is_empty() { + return Err(Box::::from(IoError::new( + IoErrorKind::InvalidInput, + "Output empty byte array", + ))); + } + + Ok(b) + } +}