ClockOrdered

Struct ClockOrdered 

Source
pub struct ClockOrdered<T> { /* private fields */ }
Expand description

The ClockOrdered type.

It is used to store a value in redis and load it in sync. It tracks automatically an ordering number to ensure that the value is only stored if the order is greater than the current order, mostly from other instances. The value is only stored if the order is greater than the current order.

This helps to synchronize the value between multiple instances without any locking mechanism. But can results in more network traffic in benefit of less wait time because of locks. Mostly used in situations, where your value changes rarely but read often. Another use case is, when it is okay for you, that the value could be not the latest or computing a derived value multiple times is acceptable.

Implementations§

Source§

impl<T> ClockOrdered<T>

Source

pub fn new(data: Generic<T>) -> Self

Creates a new ClockOrdered. The value is loaded from redis directly.

Source

pub fn store(&mut self, val: T) -> Result<(), ClockOrderedError>

Stores the value in the redis server. The value is only stored if the ordering_number is greater than the current number. The order is incremented by one before each store.

§Example
use dtypes::redis::types::Generic;
use dtypes::redis::sync::ClockOrdered;

let client = redis::Client::open("redis://localhost:6379").unwrap();
let mut i32 = Generic::with_value(1, "test_add_clock_ordered_example1", client.clone());
let mut clock_ordered = ClockOrdered::new(i32);
clock_ordered.store(2).unwrap();
assert_eq!(*clock_ordered, 2);

The store can fail if the order is not greater than the current order. This happens, if the value was set from another instance before.

§Example
use std::thread;
use dtypes::redis::types::Generic;
use dtypes::redis::sync::ClockOrdered;

let client = redis::Client::open("redis://localhost:6379").unwrap();
let client2 = client.clone();

thread::scope(|s| {
    let t1 = s.spawn(|| {
        let mut i32: Generic<i32> = Generic::new("test_add_clock_ordered_example2", client2);
        let mut clock_ordered = ClockOrdered::new(i32);
        while let Err(_) = clock_ordered.store(2) {}
        assert_eq!(*clock_ordered, 2);
    });
    let mut i32: Generic<i32> = Generic::new("test_add_clock_ordered_example2", client);
    let mut clock_ordered = ClockOrdered::new(i32);
    while let Err(_) = clock_ordered.store(3) {}
    assert_eq!(*clock_ordered, 3);
    t1.join().unwrap();
});
Source

pub fn store_blocking(&mut self, val: T) -> Result<(), ClockOrderedError>

Stores the value in the redis server and blocks until succeeds. Everything else is equal to ClockOrdered::store.

§Example
use std::thread;
use dtypes::redis::types::Generic;
use dtypes::redis::sync::ClockOrdered;

let client = redis::Client::open("redis://localhost:6379").unwrap();
let client2 = client.clone();

thread::scope(|s| {
    let t1 = s.spawn(|| {
        let mut i32: Generic<i32> = Generic::new("test_add_clock_ordered_example3", client2);
        let mut clock_ordered = ClockOrdered::new(i32);
        clock_ordered.store_blocking(2).unwrap();
        assert_eq!(*clock_ordered, 2);
    });
    let mut i32: Generic<i32> = Generic::new("test_add_clock_ordered_example3", client);
    let mut clock_ordered = ClockOrdered::new(i32);
    clock_ordered.store_blocking(3).unwrap();
    assert_eq!(*clock_ordered, 3);
    t1.join().unwrap();
});
Source

pub fn load(&mut self)

Loads the value from the redis server. This is done automatically on creation. Mostly used for synchronization. Reset the counter to order from redis or 0.

Methods from Deref<Target = Generic<T>>§

Source

pub fn store(&mut self, value: T)

The store method sets the value of the type.

Examples found in repository?
examples/2services.rs (line 15)
5fn main() {
6    thread::scope(|s| {
7        let client = redis::Client::open("redis://localhost:6379").unwrap();
8        let client2 = client.clone();
9
10        let t1 = s.spawn(move || {
11            let mut string = String::with_value("Hello".to_string(), "test", client);
12            println!("Thread1: {}", string.cached().unwrap());
13            assert_eq!(string, "Hello");
14            sleep(std::time::Duration::from_secs(1));
15            string.store("World".to_string());
16            println!("Thread1: {}", string.cached().unwrap());
17            assert_eq!(string, "World");
18        });
19
20        let t2 = s.spawn(move || {
21            sleep(std::time::Duration::from_micros(100));
22            let mut string = String::with_load("test", client2);
23            println!("Thread2: {}", string.cached().unwrap());
24            assert_eq!(string, "Hello");
25            sleep(std::time::Duration::from_secs(2));
26            string.acquire();
27            println!("Thread2: {}", string.cached().unwrap());
28            assert_eq!(string, "World");
29        });
30        t1.join().expect("Failed to join thread1");
31        t2.join().expect("Failed to join thread2");
32    });
33}
Source

pub fn acquire(&mut self) -> &T

The acquire method returns a reference to the value stored in the type. Loads it from the redis directly.

§Example
use dtypes::redis::types::Di32 as i32;

let client = redis::Client::open("redis://localhost:6379").unwrap();
let mut i32 = i32::with_value(1, "test_add", client.clone());
i32 = i32 + i32::with_value(2, "test_add2", client);
assert_eq!(i32.acquire(), &3);
Examples found in repository?
examples/2services.rs (line 26)
5fn main() {
6    thread::scope(|s| {
7        let client = redis::Client::open("redis://localhost:6379").unwrap();
8        let client2 = client.clone();
9
10        let t1 = s.spawn(move || {
11            let mut string = String::with_value("Hello".to_string(), "test", client);
12            println!("Thread1: {}", string.cached().unwrap());
13            assert_eq!(string, "Hello");
14            sleep(std::time::Duration::from_secs(1));
15            string.store("World".to_string());
16            println!("Thread1: {}", string.cached().unwrap());
17            assert_eq!(string, "World");
18        });
19
20        let t2 = s.spawn(move || {
21            sleep(std::time::Duration::from_micros(100));
22            let mut string = String::with_load("test", client2);
23            println!("Thread2: {}", string.cached().unwrap());
24            assert_eq!(string, "Hello");
25            sleep(std::time::Duration::from_secs(2));
26            string.acquire();
27            println!("Thread2: {}", string.cached().unwrap());
28            assert_eq!(string, "World");
29        });
30        t1.join().expect("Failed to join thread1");
31        t2.join().expect("Failed to join thread2");
32    });
33}
Source

pub fn cached(&self) -> Option<&T>

The get method returns a reference to the value stored in the type.

Examples found in repository?
examples/2services.rs (line 12)
5fn main() {
6    thread::scope(|s| {
7        let client = redis::Client::open("redis://localhost:6379").unwrap();
8        let client2 = client.clone();
9
10        let t1 = s.spawn(move || {
11            let mut string = String::with_value("Hello".to_string(), "test", client);
12            println!("Thread1: {}", string.cached().unwrap());
13            assert_eq!(string, "Hello");
14            sleep(std::time::Duration::from_secs(1));
15            string.store("World".to_string());
16            println!("Thread1: {}", string.cached().unwrap());
17            assert_eq!(string, "World");
18        });
19
20        let t2 = s.spawn(move || {
21            sleep(std::time::Duration::from_micros(100));
22            let mut string = String::with_load("test", client2);
23            println!("Thread2: {}", string.cached().unwrap());
24            assert_eq!(string, "Hello");
25            sleep(std::time::Duration::from_secs(2));
26            string.acquire();
27            println!("Thread2: {}", string.cached().unwrap());
28            assert_eq!(string, "World");
29        });
30        t1.join().expect("Failed to join thread1");
31        t2.join().expect("Failed to join thread2");
32    });
33}

Trait Implementations§

Source§

impl<T: Debug> Debug for ClockOrdered<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T> Deref for ClockOrdered<T>

Source§

type Target = Generic<T>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl<T> DerefMut for ClockOrdered<T>

Source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.

Auto Trait Implementations§

§

impl<T> Freeze for ClockOrdered<T>
where T: Freeze,

§

impl<T> RefUnwindSafe for ClockOrdered<T>
where T: RefUnwindSafe,

§

impl<T> Send for ClockOrdered<T>
where T: Send,

§

impl<T> Sync for ClockOrdered<T>
where T: Sync,

§

impl<T> Unpin for ClockOrdered<T>
where T: Unpin,

§

impl<T> UnwindSafe for ClockOrdered<T>
where T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.