refactor: use shared state struct
							parent
							
								
									8864925e58
								
							
						
					
					
						commit
						656df06b4e
					
				|  | @ -11,43 +11,60 @@ use sea_orm::{ | |||
|     ActiveModelTrait, ColumnTrait, Condition, ConnectionTrait, DbConn, EntityTrait, JoinType, | ||||
|     ModelTrait, NotSet, QueryFilter, QuerySelect, Related, RelationTrait, Set, TransactionTrait, | ||||
| }; | ||||
| use tokio::{runtime, sync::mpsc::UnboundedReceiver}; | ||||
| use tokio::{ | ||||
|     runtime, | ||||
|     sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}, | ||||
| }; | ||||
| 
 | ||||
| pub enum RepoCommand { | ||||
|     ParsePkg(i32, PathBuf), | ||||
| } | ||||
| 
 | ||||
| pub struct RepoSharedState { | ||||
|     repos_dir: PathBuf, | ||||
|     conn: DbConn, | ||||
|     rx: Mutex<UnboundedReceiver<RepoCommand>>, | ||||
|     tx: UnboundedSender<RepoCommand>, | ||||
|     repos: RwLock<HashMap<i32, (AtomicU32, Arc<Mutex<()>>)>>, | ||||
| } | ||||
| 
 | ||||
| impl RepoSharedState { | ||||
|     pub fn new( | ||||
|         repos_dir: impl AsRef<Path>, | ||||
|         conn: DbConn, | ||||
|         repos: HashMap<i32, (AtomicU32, Arc<Mutex<()>>)>, | ||||
|     ) -> Self { | ||||
|         let (tx, rx) = unbounded_channel(); | ||||
| 
 | ||||
|         Self { | ||||
|             repos_dir: repos_dir.as_ref().to_path_buf(), | ||||
|             conn, | ||||
|             rx: Mutex::new(rx), | ||||
|             tx, | ||||
|             repos: RwLock::new(repos), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// The actor is responsible for mutating the repositories. They receive their commands their
 | ||||
| /// messages and process these commands in both a synchronous and asynchronous way.
 | ||||
| pub struct RepoActor { | ||||
|     repos_dir: PathBuf, | ||||
|     conn: DbConn, | ||||
|     rt: runtime::Handle, | ||||
|     rx: Arc<Mutex<UnboundedReceiver<RepoCommand>>>, | ||||
|     repos: Arc<RwLock<HashMap<i32, (AtomicU32, Arc<Mutex<()>>)>>>, | ||||
|     state: Arc<RepoSharedState>, | ||||
| } | ||||
| 
 | ||||
| impl RepoActor { | ||||
|     pub fn new( | ||||
|         repos_dir: PathBuf, | ||||
|         conn: DbConn, | ||||
|         rt: runtime::Handle, | ||||
|         rx: Arc<Mutex<UnboundedReceiver<RepoCommand>>>, | ||||
|         repos: Arc<RwLock<HashMap<i32, (AtomicU32, Arc<Mutex<()>>)>>>, | ||||
|     ) -> Self { | ||||
|     pub fn new(rt: runtime::Handle, state: Arc<RepoSharedState>) -> Self { | ||||
|         Self { | ||||
|             repos_dir, | ||||
|             conn, | ||||
|             rt, | ||||
|             rx, | ||||
|             repos, | ||||
|             state: Arc::clone(&state), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Run the main actor loop
 | ||||
|     pub fn run(self) { | ||||
|         while let Some(msg) = { | ||||
|             let mut rx = self.rx.lock().unwrap(); | ||||
|             let mut rx = self.state.rx.lock().unwrap(); | ||||
|             rx.blocking_recv() | ||||
|         } { | ||||
|             match msg { | ||||
|  | @ -62,8 +79,9 @@ impl RepoActor { | |||
|         let pkg = package::Package::open(&path)?; | ||||
|         let pkg = self | ||||
|             .rt | ||||
|             .block_on(db::query::package::insert(&self.conn, repo, pkg))?; | ||||
|             .block_on(db::query::package::insert(&self.state.conn, repo, pkg))?; | ||||
|         let dest_path = self | ||||
|             .state | ||||
|             .repos_dir | ||||
|             .join(repo.to_string()) | ||||
|             .join(pkg.id.to_string()); | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| use super::RepoSharedState; | ||||
| use crate::db; | ||||
| 
 | ||||
| use std::{ | ||||
|  | @ -17,10 +18,7 @@ use tokio::{ | |||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct RepoHandle { | ||||
|     repos_dir: PathBuf, | ||||
|     conn: DbConn, | ||||
|     tx: UnboundedSender<super::RepoCommand>, | ||||
|     repos: Arc<RwLock<HashMap<i32, (AtomicU32, Arc<Mutex<()>>)>>>, | ||||
|     state: Arc<RepoSharedState>, | ||||
| } | ||||
| 
 | ||||
| impl RepoHandle { | ||||
|  | @ -32,8 +30,6 @@ impl RepoHandle { | |||
|     ) -> crate::Result<Self> { | ||||
|         std::fs::create_dir_all(repos_dir.as_ref())?; | ||||
| 
 | ||||
|         let (tx, rx) = unbounded_channel(); | ||||
| 
 | ||||
|         let mut repos = HashMap::new(); | ||||
|         let repo_ids: Vec<i32> = rt.block_on( | ||||
|             db::Repo::find() | ||||
|  | @ -47,26 +43,14 @@ impl RepoHandle { | |||
|             repos.insert(id, Default::default()); | ||||
|         } | ||||
| 
 | ||||
|         let rx = Arc::new(Mutex::new(rx)); | ||||
|         let repos = Arc::new(RwLock::new(repos)); | ||||
|         let state = Arc::new(RepoSharedState::new(repos_dir, conn, repos)); | ||||
| 
 | ||||
|         for _ in 0..actors { | ||||
|             let actor = super::RepoActor::new( | ||||
|                 repos_dir.as_ref().to_path_buf(), | ||||
|                 conn.clone(), | ||||
|                 rt.clone(), | ||||
|                 Arc::clone(&rx), | ||||
|                 Arc::clone(&repos), | ||||
|             ); | ||||
|             let actor = super::RepoActor::new(rt.clone(), Arc::clone(&state)); | ||||
| 
 | ||||
|             std::thread::spawn(|| actor.run()); | ||||
|         } | ||||
| 
 | ||||
|         Ok(Self { | ||||
|             repos_dir: repos_dir.as_ref().to_path_buf(), | ||||
|             conn, | ||||
|             tx, | ||||
|             repos, | ||||
|         }) | ||||
|         Ok(Self { state }) | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ mod handle; | |||
| mod manager; | ||||
| pub mod package; | ||||
| 
 | ||||
| pub use actor::{RepoActor, RepoCommand}; | ||||
| pub use actor::{RepoActor, RepoCommand, RepoSharedState}; | ||||
| pub use handle::RepoHandle; | ||||
| pub use manager::RepoMgr; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue