es-entity 0.10.33

Event Sourcing Entity Framework
Documentation
# Idempotency

Idempotency means that performing the same operation multiple times has the same effect as doing it once.
It’s used to ensure that retrying a request doesn’t cause unintended side effects, such as duplicated `Event`s being persisted.

It is particularly useful in the context of a distributed system where operations could be triggered from an asynchronous event queue (ie pub-sub).
Whenever you would like to have an `exactly-once` processing guarantee - you can easily achieve an `effectively-once` processing by ensuring your mutations are all idempotent.

Making your `Entity` mutations idempotent is very simple when doing Event Sourcing as you can easily check if the event you are about to append already exists in the history.

## Example

To see the issue in action - lets consider the `update_name` mutation without an idempotency check.

```rust
pub enum UserEvent {
    Initialized { id: u64, name: String },
    NameUpdated { name: String },
}

pub struct User {
    events: Vec<UserEvent>
}

impl User {
    pub fn update_name(&mut self, new_name: impl Into<String>) {
        let name = new_name.into();
        self.events.push(UserEvent::NameUpdated { name });
    }
}
```

In the above code we could easily record redundant events by calling the `update_name` mutation multiple times with the same input.
```rust
# pub enum UserEvent {
#     Initialized { id: u64, name: String },
#     NameUpdated { name: String },
# }
# pub struct User {
#     events: Vec<UserEvent>
# }
# impl User {
#     pub fn update_name(&mut self, new_name: impl Into<String>) {
#         let name = new_name.into();
#         self.events.push(UserEvent::NameUpdated { name });
#     }
# }

fn main() {
    let mut user = User { events: vec![] };
    user.update_name("Harrison");

    // Causes a redundant event to be appended
    user.update_name("Harrison");

    assert_eq!(user.events.len(), 2);
}
```

To prevent this we can iterate through the events to check if it has already been applied:

```rust
# pub enum UserEvent {
#     Initialized { id: u64, name: String },
#     NameUpdated { name: String },
# }
# pub struct User {
#     events: Vec<UserEvent>
# }
impl User {
    pub fn update_name(&mut self, new_name: impl Into<String>) {
        let name = new_name.into();
        for event in self.events.iter().rev() {
            match event {
                UserEvent::NameUpdated { name: existing_name } if existing_name == &name => {
                    return;
                }
                _ => ()
            }
        }
        self.events.push(UserEvent::NameUpdated { name });
    }
}

fn main() {
    let mut user = User { events: vec![] };

    user.update_name("Harrison");

    // This update will be ignored
    user.update_name("Harrison");

    assert_eq!(user.events.len(), 1);
}
```

But now we just silently ignore the operation.
Better would be to signal back to the caller whether or not the operation was applied.
For that we use the `Idempotent` type:
```rust
# extern crate es_entity;
# pub enum UserEvent {
#     Initialized { id: u64, name: String },
#     NameUpdated { name: String },
# }
# pub struct User {
#     events: Vec<UserEvent>
# }
use es_entity::Idempotent;
// #[must_use]
// pub enum Idempotent<T> {
//     Executed(T),
//     AlreadyApplied,
// }

impl User {
    pub fn update_name(&mut self, new_name: impl Into<String>) -> Idempotent<()>{
        let name = new_name.into();
        for event in self.events.iter().rev() {
            match event {
                UserEvent::NameUpdated { name: existing_name } if existing_name == &name => {
                    return Idempotent::AlreadyApplied;
                }
                _ => ()
            }
        }
        self.events.push(UserEvent::NameUpdated { name });
        Idempotent::Executed(())
    }
}

fn main() {
    let mut user = User { events: vec![] };
    assert!(user.update_name("Harrison").did_execute());
    assert!(user.update_name("Harrison").was_already_applied());
}
```

To cut down on boilerplate this pattern of iterating the events to check if an event was already applied has been encoded into the `idempotency_guard!` macro:

```rust
# extern crate es_entity;
# pub enum UserEvent {
#     Initialized { id: u64, name: String },
#     NameUpdated { name: String },
# }
# pub struct User {
#     events: Vec<UserEvent>
# }
use es_entity::{idempotency_guard, Idempotent};

impl User {
    pub fn update_name(&mut self, new_name: impl Into<String>) -> Idempotent<()>{
        let name = new_name.into();
        idempotency_guard!(
            // The iterator of events
            self.events.iter().rev(),
            // The pattern match to check whether an operation was already applied
            already_applied: UserEvent::NameUpdated { name: existing_name } if existing_name == &name
        );
        self.events.push(UserEvent::NameUpdated { name });
        Idempotent::Executed(())
    }
}

fn main() {
    let mut user = User { events: vec![] };
    assert!(user.update_name("Harrison").did_execute());
    assert!(user.update_name("Harrison").was_already_applied());
}
```

Finally there is the case where an operation was applied in the past - but it is still legal to re-apply it.
Like changing a name back to what it originally was:
```rust
# extern crate es_entity;
# pub enum UserEvent {
#     Initialized { id: u64, name: String },
#     NameUpdated { name: String },
# }
# pub struct User {
#     events: Vec<UserEvent>
# }
use es_entity::{idempotency_guard, Idempotent};

impl User {
    pub fn update_name(&mut self, new_name: impl Into<String>) -> Idempotent<()>{
        let name = new_name.into();
        idempotency_guard!(
            self.events.iter().rev(),
            already_applied: UserEvent::NameUpdated { name: existing_name } if existing_name == &name,
            // The `resets_on` signifies the pattern where to stop the iteration.
            resets_on: UserEvent::NameUpdated { .. }
        );
        self.events.push(UserEvent::NameUpdated { name });
        Idempotent::Executed(())
    }
}

fn main() {
    let mut user = User { events: vec![] };
    assert!(user.update_name("Harrison").did_execute());
    assert!(user.update_name("Colin").did_execute());
    assert!(user.update_name("Harrison").did_execute());
}
```

Without the `resets_on` argument the second call of `assert!(user.update_name("Harrison").did_execute());` would fail.