Docs / ArchitectureKit / Rust / Fundamentals / Defining Commands

Defining Commands

A command describes what someone wants to do. Define it as a struct and implement the Command trait with two methods: subject, which returns the subject the command acts on, and preconditions, which returns the conditions under which its events may be written.

This makes the struct a Command:

#[derive(Clone)]
struct AcquireBook {
  book: Subject,
  title: String,
  author: String,
  isbn: String,
}

impl Command for AcquireBook {
  fn subject(&self) -> Subject {
    self.book.clone()
  }

  fn preconditions(&self) -> Vec<Precondition> {
    vec![Precondition::on_state_read()]
  }
}

#[derive(Clone)]
struct BorrowBook {
  book: Subject,
  reader_id: String,
  borrowed_until: String,
}

impl Command for BorrowBook {
  fn subject(&self) -> Subject {
    self.book.clone()
  }

  fn preconditions(&self) -> Vec<Precondition> {
    vec![Precondition::on_state_read()]
  }
}

#[derive(Clone)]
struct ReturnBook {
  book: Subject,
}

impl Command for ReturnBook {
  fn subject(&self) -> Subject {
    self.book.clone()
  }

  fn preconditions(&self) -> Vec<Precondition> {
    vec![Precondition::on_state_read()]
  }
}

on_state_read makes sure that the events are only written if the state the command is decided on still holds. For the other preconditions, see Using Preconditions.

The subject is a Subject, which is a path that EventSourcingDB accepts, such as /books/42. A value that is no such path can not be a Subject at all, so the command holds its subject as one, and a value that can not be part of a subject is refused when the command is built, not when it is executed. Subject::new panics for such a value, which fits a subject written in the code, while parse and SubjectScheme::try_build refuse it with an error, which fits one that comes from a request (see Composing Subjects).

Note that a command derives Clone, since executing it may decide on it once more after a conflict, which takes the command anew (see Guarding Against Concurrent Changes).