Moved moved system clock requests into the queue.
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
This commit is contained in:
20
src/lib.rs
20
src/lib.rs
@@ -10,7 +10,7 @@ use isolang::Language;
|
|||||||
use message::{Message, MessageAction, MessageID};
|
use message::{Message, MessageAction, MessageID};
|
||||||
use queue::{
|
use queue::{
|
||||||
data_director::{RegMsg, Register},
|
data_director::{RegMsg, Register},
|
||||||
router::Queue,
|
router::{ClockType, Queue, SystemClock, TestClock},
|
||||||
SenderID,
|
SenderID,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
@@ -224,7 +224,14 @@ pub struct MoreThanText {
|
|||||||
|
|
||||||
impl MoreThanText {
|
impl MoreThanText {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let queue = Queue::new();
|
Self::with_clock(SystemClock::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_clock<C>(clock: C) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ClockType>,
|
||||||
|
{
|
||||||
|
let queue = Queue::with_clock(clock);
|
||||||
CreateDoc::start(queue.clone()); // needs to be first.
|
CreateDoc::start(queue.clone()); // needs to be first.
|
||||||
Clock::start(queue.clone());
|
Clock::start(queue.clone());
|
||||||
Session::start(queue.clone());
|
Session::start(queue.clone());
|
||||||
@@ -253,6 +260,7 @@ impl MoreThanText {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct TestMoreThanText {
|
pub struct TestMoreThanText {
|
||||||
|
clock: TestClock,
|
||||||
mtt: MoreThanText,
|
mtt: MoreThanText,
|
||||||
queue: Queue,
|
queue: Queue,
|
||||||
channel: Option<Receiver<Message>>,
|
channel: Option<Receiver<Message>>,
|
||||||
@@ -260,9 +268,11 @@ pub struct TestMoreThanText {
|
|||||||
|
|
||||||
impl TestMoreThanText {
|
impl TestMoreThanText {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mtt = MoreThanText::new();
|
let clock = TestClock::new();
|
||||||
|
let mtt = MoreThanText::with_clock(clock.clone());
|
||||||
let queue = mtt.queue.clone();
|
let queue = mtt.queue.clone();
|
||||||
Self {
|
Self {
|
||||||
|
clock: clock,
|
||||||
mtt: mtt,
|
mtt: mtt,
|
||||||
queue: queue,
|
queue: queue,
|
||||||
channel: None,
|
channel: None,
|
||||||
@@ -312,4 +322,8 @@ impl TestMoreThanText {
|
|||||||
panic!("received {:?} instead of {:?} trigger", msg, action);
|
panic!("received {:?} instead of {:?} trigger", msg, action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn advance_time(&self, duration: Duration) {
|
||||||
|
self.clock.advance(duration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
pub mod data_director;
|
pub mod data_director;
|
||||||
pub mod router;
|
pub mod router;
|
||||||
|
|
||||||
pub use router::SenderID;
|
pub use router::{ClockType, SenderID, SystemClock, TestClock};
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ use crate::{
|
|||||||
message::Message,
|
message::Message,
|
||||||
queue::data_director::{DocRegistry, RegMsg, Register},
|
queue::data_director::{DocRegistry, RegMsg, Register},
|
||||||
};
|
};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
sync::{
|
sync::{
|
||||||
mpsc::{channel, Sender},
|
mpsc::{channel, Sender},
|
||||||
Arc, RwLock,
|
Arc, RwLock,
|
||||||
},
|
},
|
||||||
|
time::Duration,
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -89,16 +91,115 @@ impl Router {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait Now {
|
||||||
|
fn now(&self) -> DateTime<Utc> {
|
||||||
|
Utc::now()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SystemClock;
|
||||||
|
|
||||||
|
impl SystemClock {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Now for SystemClock {}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct TestClock {
|
||||||
|
time: Arc<RwLock<DateTime<Utc>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestClock {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
time: Arc::new(RwLock::new(Utc::now())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn advance(&self, duration: Duration) {
|
||||||
|
let mut current = self.time.write().unwrap();
|
||||||
|
*current += duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Now for TestClock {
|
||||||
|
fn now(&self) -> DateTime<Utc> {
|
||||||
|
let current = self.time.read().unwrap();
|
||||||
|
current.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test_clocks {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn is_now_constant() {
|
||||||
|
let clock = TestClock::new();
|
||||||
|
let read1 = clock.now();
|
||||||
|
let read2 = clock.now();
|
||||||
|
assert_eq!(read1, read2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_time_pass() {
|
||||||
|
let clock = TestClock::new();
|
||||||
|
let current = clock.now();
|
||||||
|
let duration = Duration::from_secs(35);
|
||||||
|
let expected = current + duration;
|
||||||
|
clock.advance(duration);
|
||||||
|
assert_eq!(clock.now(), expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ClockType {
|
||||||
|
Clock(SystemClock),
|
||||||
|
TestClock(TestClock),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Now for ClockType {
|
||||||
|
fn now(&self) -> DateTime<Utc> {
|
||||||
|
match self {
|
||||||
|
Self::Clock(data) => data.now(),
|
||||||
|
Self::TestClock(data) => data.now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SystemClock> for ClockType {
|
||||||
|
fn from(value: SystemClock) -> Self {
|
||||||
|
Self::Clock(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TestClock> for ClockType {
|
||||||
|
fn from(value: TestClock) -> Self {
|
||||||
|
Self::TestClock(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Queue {
|
pub struct Queue {
|
||||||
router: Arc<RwLock<Router>>,
|
router: Arc<RwLock<Router>>,
|
||||||
|
clock: Arc<RwLock<ClockType>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Queue {
|
impl Queue {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
Self::with_clock(SystemClock::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_clock<C>(clock: C) -> Self
|
||||||
|
where
|
||||||
|
C: Into<ClockType>,
|
||||||
|
{
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
let output = Self {
|
let output = Self {
|
||||||
router: Arc::new(RwLock::new(Router::new(tx))),
|
router: Arc::new(RwLock::new(Router::new(tx))),
|
||||||
|
clock: Arc::new(RwLock::new(clock.into())),
|
||||||
};
|
};
|
||||||
DocRegistry::start(output.clone(), rx);
|
DocRegistry::start(output.clone(), rx);
|
||||||
output
|
output
|
||||||
@@ -123,6 +224,11 @@ impl Queue {
|
|||||||
let router = self.router.read().unwrap();
|
let router = self.router.read().unwrap();
|
||||||
router.send(msg.clone());
|
router.send(msg.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn now(&self) -> DateTime<Utc> {
|
||||||
|
let clock = self.clock.read().unwrap();
|
||||||
|
clock.now()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -357,4 +463,16 @@ mod queues {
|
|||||||
_ => unreachable!("got {:?} should have been register", action),
|
_ => unreachable!("got {:?} should have been register", action),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn does_queue_return_time() {
|
||||||
|
let clock = TestClock::new();
|
||||||
|
let queue = Queue::with_clock(clock.clone());
|
||||||
|
let mut expected = clock.now();
|
||||||
|
assert_eq!(queue.now(), expected);
|
||||||
|
let forward = Duration::from_secs(22);
|
||||||
|
clock.advance(forward);
|
||||||
|
expected += forward;
|
||||||
|
assert_eq!(queue.now(), expected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user