Skip to main content

Group

Struct Group 

Source
pub struct Group<K, V, S = RandomState> { /* private fields */ }
Expand description

Group represents a class of work and forms a namespace in which units of work can be executed with duplicate suppression.

Implementations§

Source§

impl<K, V> Group<K, V, RandomState>
where K: Eq + Hash, V: Clone,

Source

pub fn new() -> Self

Creates a new Group with the default hasher.

Source§

impl<K, V, S> Group<K, V, S>
where K: Eq + Hash, V: Clone, S: BuildHasher,

Source

pub fn with_hasher(hasher: S) -> Self

Creates a new Group with the given hasher.

Source

pub async fn work<F>(&self, key: K, func: F) -> V
where F: AsyncFnOnce() -> V,

Executes and returns the results of the given function, making sure that only one execution is in-flight for a given key at a time.

If a duplicate comes in, the duplicate caller waits for the original to complete and receives the same results.

If the computation is cancelled or panics, another caller waiting for the same key may retry it.

Once the function completes, the key, if not forgotten, is removed from the group, allowing future calls with the same key to execute the function again.

§Examples
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::time::Duration;

use mea::singleflight::Group;

let group = Group::new();
let counter = Arc::new(AtomicUsize::new(0));

let c1 = counter.clone();
let fut1 = group.work("key", || async move {
    c1.fetch_add(1, Ordering::SeqCst);
    // simulate heavy work to avoid immediate completion
    tokio::time::sleep(Duration::from_millis(100)).await;
    "result"
});

let c2 = counter.clone();
let fut2 = group.work("key", || async move {
    c2.fetch_add(1, Ordering::SeqCst);
    // simulate heavy work to avoid immediate completion
    tokio::time::sleep(Duration::from_millis(100)).await;
    "result"
});

let (r1, r2) = tokio::join!(fut1, fut2);

assert_eq!(r1, "result");
assert_eq!(r2, "result");
assert_eq!(counter.load(Ordering::SeqCst), 1);
Source

pub async fn try_work<E, F>(&self, key: K, func: F) -> Result<V, E>
where F: AsyncFnOnce() -> Result<V, E>,

Executes and returns the results of the given function, making sure that only one execution is in-flight for a given key at a time.

If a duplicate comes in, the duplicate caller waits for the original to complete and receives the same results.

If the computation returns an error, it is returned to that caller. After an error, cancellation, or panic, another caller may retry the computation.

Once the function completes successfully, the key, if not forgotten, is removed from the group, allowing future calls with the same key to execute the function again.

§Examples
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::time::Duration;

use mea::singleflight::Group;

let group = Group::new();

let fut1 = group.try_work("key", || async move {
    // simulate heavy work to avoid immediate completion
    tokio::time::sleep(Duration::from_millis(100)).await;
    Err::<_, &'static str>("fut1")
});

let fut2 = group.try_work("key", || async move {
    // simulate heavy work to avoid immediate completion
    tokio::time::sleep(Duration::from_millis(200)).await;
    Ok::<_, &'static str>("fut2")
});

let (r1, r2) = tokio::join!(fut1, fut2);

assert_eq!(r1, Err("fut1"));
assert_eq!(r2, Ok("fut2"));
Source

pub fn forget<Q>(&self, key: &Q)
where K: Borrow<Q>, Q: Hash + Eq + ?Sized,

Forgets about the given key.

Future calls to work for this key will call the function rather than waiting for an earlier call to complete. Existing calls to work for this key are not affected.

Trait Implementations§

Source§

impl<K: Debug, V: Debug, S: Debug> Debug for Group<K, V, S>

Source§

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

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

impl<K, V, S> Default for Group<K, V, S>
where K: Eq + Hash, V: Clone, S: BuildHasher + Default,

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<K, V, S = RandomState> !Freeze for Group<K, V, S>

§

impl<K, V, S> RefUnwindSafe for Group<K, V, S>

§

impl<K, V, S> Send for Group<K, V, S>
where S: Send, K: Sync + Send, V: Sync + Send,

§

impl<K, V, S> Sync for Group<K, V, S>
where S: Send, K: Sync + Send, V: Sync + Send,

§

impl<K, V, S> Unpin for Group<K, V, S>
where S: Unpin,

§

impl<K, V, S> UnsafeUnpin for Group<K, V, S>
where S: UnsafeUnpin,

§

impl<K, V, S> UnwindSafe for Group<K, V, S>

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<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.