use tokio::sync::broadcast;
use crate::{
assets,
types::{JoinHandle, Result},
BinaryApp, CargoShellBuilder, DirectoryWatcher, Operator, ParrellelOps, ProjectDefinition,
StreamTCPApp,
};
use std::{sync, time};
pub struct HttpDevService {
pub project: ProjectDefinition,
pub package_changes: broadcast::Sender<()>,
pub package_built: broadcast::Sender<()>,
pub package_started: broadcast::Sender<()>,
}
impl HttpDevService {
pub fn new(project: ProjectDefinition) -> Self {
let (package_changes, _) = broadcast::channel::<()>(2);
let (package_started, _) = broadcast::channel::<()>(2);
let (package_built, _) = broadcast::channel::<()>(2);
Self {
project,
package_built,
package_changes,
package_started,
}
}
}
impl HttpDevService {
pub async fn start(&mut self, canceller: broadcast::Receiver<()>) -> Result<JoinHandle<()>> {
let package_started = &self.package_started;
self.project.and_proxy_routes(move |routes| {
routes
.entry(assets::RELOADER_SCRIPT_ENDPOINT.to_string())
.or_insert(sync::Arc::new(assets::sse_endpoint_script));
routes
.entry(assets::RELOADER_SSE_ENDPOINT.to_string())
.or_insert(assets::create_sse_endpoint_handler(package_started.clone()));
});
let project_directory_watcher = DirectoryWatcher::new(
self.project.watch_directory.clone(),
self.package_changes.clone(),
);
let app_builder = CargoShellBuilder::shared(
self.project.clone(),
self.package_built.clone(),
self.package_changes.clone(),
);
let app_runner = BinaryApp::shared(
self.project.clone(),
self.package_built.clone(),
self.package_started.clone(),
);
let service_proxy =
StreamTCPApp::shared(time::Duration::from_secs(1), self.project.proxy.clone());
let command = ParrellelOps::new(vec![
Box::new(app_builder),
Box::new(app_runner),
Box::new(service_proxy),
Box::new(project_directory_watcher),
]);
let command_op = command.run(canceller);
self.package_changes
.send(())
.expect("should have delivered trigger message");
Ok(command_op)
}
}