今天來試一下Query 用的 Model
先製作查詢使用的模型DTO
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct ReaderDto {
pub id: String,
pub name: String,
pub books_borrowed: u32,
pub next_due_date: Option<DateTime<Utc>>,
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct ReaderBorrowedRecordDto {
pub book_id: String,
pub book_name: String,
pub borrowed_date: DateTime<Utc>,
pub due_date: DateTime<Utc>,
}
暫時不連實際DB,資料先放Query裡(InMemory:
#[derive(Debug, Default)]
pub struct ReaderQuery {
pub readers: Arc<Mutex<HashMap<String, ReaderDto>>>,
pub reader_borrowed_records: Arc<Mutex<Vec<ReaderBorrowedRecordDto>>>,
}
實作 Query trait :
#[async_trait]
impl Query<Reader> for ReaderQuery {
async fn dispatch(&self, aggregate_id: &str, events: &[EventEnvelope<Reader>]) {
for event in events {
match &event.payload {
ReaderEvent::ReaderCreated { name, id } => {
let mut readers = self.readers.lock().unwrap();
readers.insert(aggregate_id.to_string(), ReaderDto {
id: id.to_string(),
name: name.to_string(),
..Default::default()
});
}
ReaderEvent::BookBorrowed(borrowing) => {
let mut readers = self.readers.lock().unwrap();
let reader = readers.get_mut(aggregate_id).unwrap();
reader.books_borrowed += 1;
if reader.next_due_date.is_none()
|| reader.next_due_date.unwrap() > borrowing.due_date {
reader.next_due_date = Some(borrowing.due_date);
}
}
ReaderEvent::BookReturned(borrowing) => {
let mut readers = self.readers.lock().unwrap();
let reader = readers.get_mut(aggregate_id).unwrap();
reader.books_borrowed -= 1;
if reader.books_borrowed == 0 {
reader.next_due_date = None;
} else if reader.next_due_date.unwrap() == borrowing.due_date {
let mut next_due_date = None;
for record in
self.reader_borrowed_records.lock().unwrap().iter() {
if record.book_id == borrowing.book_id {
continue;
}
if next_due_date.is_none()
|| next_due_date.unwrap() > record.due_date {
next_due_date = Some(record.due_date);
}
}
reader.next_due_date = next_due_date;
}
}
}
}
}
}
原本已借閱書籍dto想放書名,不過先前實作的指令及事件不含書名,變成這裡Query傳入時,要利用book_id再去查詢book的資料,不知道這算不算是寫入時需要的查詢,目前還沒想到好的實作方式,也許之後實作DB 可以透過DB的查詢來處理?