diff --git a/its/crates/application/src/use_case.rs b/its/crates/application/src/use_case.rs index be8f624e..3189c6c7 100644 --- a/its/crates/application/src/use_case.rs +++ b/its/crates/application/src/use_case.rs @@ -1,18 +1,12 @@ mod event_dto; +mod issue_repository; -use self::event_dto::*; - -use std::{ - fs::File, - io::{BufRead, BufReader, BufWriter, Write}, - path::{Path, PathBuf}, - str::FromStr, -}; +pub use self::issue_repository::*; use domain::{ IssueAggregate, IssueAggregateCommand, IssueAggregateCreateIssue, IssueAggregateError, IssueAggregateEvent, IssueAggregateFinishIssue, IssueCreated, IssueFinished, IssueId, - IssueNumber, IssueTitle, + IssueTitle, }; use limited_date_time::Instant; use thiserror::Error; @@ -47,113 +41,6 @@ pub enum IssueManagementContextError { Unknown, } -#[derive(Debug, Error)] -pub enum RepositoryError { - #[error("IO")] - IO, -} - -#[derive(Debug, Default)] -pub struct IssueRepository {} - -impl IssueRepository { - pub fn find_by_id( - &self, - issue_id: &IssueId, - ) -> Result, RepositoryError> { - let file_path = PathBuf::from_str("its.jsonl").map_err(|_| RepositoryError::IO)?; - if !file_path.exists() { - return Ok(None); - } - - let file = File::open(file_path.as_path()).map_err(|_| RepositoryError::IO)?; - let buf_reader = BufReader::new(file); - let mut events: Vec = vec![]; - for line in buf_reader.lines() { - let line = line.map_err(|_| RepositoryError::IO)?; - let dto = serde_json::from_str::<'_, EventDto>(line.as_str()) - .map_err(|_| RepositoryError::IO)?; - let event = IssueAggregateEvent::try_from(dto).map_err(|_| RepositoryError::IO)?; - events.push(event); - } - - let filtered = events - .into_iter() - .filter(|e| match e { - IssueAggregateEvent::Created(event) => event.issue_id() == issue_id, - IssueAggregateEvent::Finished(event) => event.issue_id() == issue_id, - }) - .collect::>(); - - if filtered.is_empty() { - Ok(None) - } else { - IssueAggregate::from_events(&filtered) - .map(Some) - .map_err(|_| RepositoryError::IO) - } - } - - pub fn save(&self, event: IssueAggregateEvent) -> Result<(), RepositoryError> { - let file_path = PathBuf::from_str("its.jsonl").map_err(|_| RepositoryError::IO)?; - let mut events = self.events(file_path.as_path())?; - - events.push(event); - - let file = File::create(file_path.as_path()).map_err(|_| RepositoryError::IO)?; - let mut buf_writer = BufWriter::new(file); - for event in events { - let dto = EventDto::from(event); - let line = serde_json::to_string(&dto).map_err(|_| RepositoryError::IO)?; - buf_writer - .write(line.as_bytes()) - .map_err(|_| RepositoryError::IO)?; - buf_writer - .write("\n".as_bytes()) - .map_err(|_| RepositoryError::IO)?; - } - Ok(()) - } - - pub fn next_issue_number(&self) -> Result { - let file_path = PathBuf::from_str("its.jsonl").map_err(|_| RepositoryError::IO)?; - let events = self.events(file_path.as_path())?; - let mut max: Option = None; - for event in events { - match event { - IssueAggregateEvent::Created(event) => { - max = Some( - max.unwrap_or_else(|| event.issue_id().clone()) - .max(event.issue_id().clone()), - ) - } - IssueAggregateEvent::Finished(_) => {} - } - } - Ok(max - .map(|id| id.issue_number().next_number()) - .unwrap_or_else(IssueNumber::start_number)) - } - - fn events(&self, file_path: &Path) -> Result, RepositoryError> { - Ok(if file_path.exists() { - let file = File::open(file_path).map_err(|_| RepositoryError::IO)?; - let buf_reader = BufReader::new(file); - let mut events: Vec = vec![]; - for line in buf_reader.lines() { - let line = line.map_err(|_| RepositoryError::IO)?; - let dto = serde_json::from_str::<'_, EventDto>(line.as_str()) - .map_err(|_| RepositoryError::IO)?; - let event = IssueAggregateEvent::try_from(dto).map_err(|_| RepositoryError::IO)?; - events.push(event); - } - events - } else { - vec![] - }) - } -} - pub fn issue_management_context_use_case( command: IssueManagementContextCommand, ) -> Result { diff --git a/its/crates/application/src/use_case/issue_repository.rs b/its/crates/application/src/use_case/issue_repository.rs new file mode 100644 index 00000000..017b3583 --- /dev/null +++ b/its/crates/application/src/use_case/issue_repository.rs @@ -0,0 +1,118 @@ +use std::{ + fs::File, + io::{BufRead, BufReader, BufWriter, Write}, + path::{Path, PathBuf}, + str::FromStr, +}; + +use domain::{IssueAggregate, IssueAggregateEvent, IssueId, IssueNumber}; +use thiserror::Error; + +use crate::use_case::event_dto::EventDto; + +#[derive(Debug, Error)] +pub enum RepositoryError { + #[error("IO")] + IO, +} + +#[derive(Debug, Default)] +pub struct IssueRepository {} + +impl IssueRepository { + pub fn find_by_id( + &self, + issue_id: &IssueId, + ) -> Result, RepositoryError> { + let file_path = PathBuf::from_str("its.jsonl").map_err(|_| RepositoryError::IO)?; + if !file_path.exists() { + return Ok(None); + } + + let file = File::open(file_path.as_path()).map_err(|_| RepositoryError::IO)?; + let buf_reader = BufReader::new(file); + let mut events: Vec = vec![]; + for line in buf_reader.lines() { + let line = line.map_err(|_| RepositoryError::IO)?; + let dto = serde_json::from_str::<'_, EventDto>(line.as_str()) + .map_err(|_| RepositoryError::IO)?; + let event = IssueAggregateEvent::try_from(dto).map_err(|_| RepositoryError::IO)?; + events.push(event); + } + + let filtered = events + .into_iter() + .filter(|e| match e { + IssueAggregateEvent::Created(event) => event.issue_id() == issue_id, + IssueAggregateEvent::Finished(event) => event.issue_id() == issue_id, + }) + .collect::>(); + + if filtered.is_empty() { + Ok(None) + } else { + IssueAggregate::from_events(&filtered) + .map(Some) + .map_err(|_| RepositoryError::IO) + } + } + + pub fn save(&self, event: IssueAggregateEvent) -> Result<(), RepositoryError> { + let file_path = PathBuf::from_str("its.jsonl").map_err(|_| RepositoryError::IO)?; + let mut events = self.events(file_path.as_path())?; + + events.push(event); + + let file = File::create(file_path.as_path()).map_err(|_| RepositoryError::IO)?; + let mut buf_writer = BufWriter::new(file); + for event in events { + let dto = EventDto::from(event); + let line = serde_json::to_string(&dto).map_err(|_| RepositoryError::IO)?; + buf_writer + .write(line.as_bytes()) + .map_err(|_| RepositoryError::IO)?; + buf_writer + .write("\n".as_bytes()) + .map_err(|_| RepositoryError::IO)?; + } + Ok(()) + } + + pub fn next_issue_number(&self) -> Result { + let file_path = PathBuf::from_str("its.jsonl").map_err(|_| RepositoryError::IO)?; + let events = self.events(file_path.as_path())?; + let mut max: Option = None; + for event in events { + match event { + IssueAggregateEvent::Created(event) => { + max = Some( + max.unwrap_or_else(|| event.issue_id().clone()) + .max(event.issue_id().clone()), + ) + } + IssueAggregateEvent::Finished(_) => {} + } + } + Ok(max + .map(|id| id.issue_number().next_number()) + .unwrap_or_else(IssueNumber::start_number)) + } + + fn events(&self, file_path: &Path) -> Result, RepositoryError> { + Ok(if file_path.exists() { + let file = File::open(file_path).map_err(|_| RepositoryError::IO)?; + let buf_reader = BufReader::new(file); + let mut events: Vec = vec![]; + for line in buf_reader.lines() { + let line = line.map_err(|_| RepositoryError::IO)?; + let dto = serde_json::from_str::<'_, EventDto>(line.as_str()) + .map_err(|_| RepositoryError::IO)?; + let event = IssueAggregateEvent::try_from(dto).map_err(|_| RepositoryError::IO)?; + events.push(event); + } + events + } else { + vec![] + }) + } +}