Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
ui/dist
inject/dist
inject/vendor
generated/
generated/
package-lock.json
package.json
3 changes: 3 additions & 0 deletions crates/bsnext_core/src/server/actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ impl ServerActor {

(shutdown_complete, axum_server_handle_clone, client_sender)
}
pub fn client_sender(&self) -> Option<&tokio::sync::broadcast::Sender<ClientEvent>> {
self.signals.as_ref().and_then(|s| s.client_sender.as_ref())
}
}

impl actix::Actor for ServerActor {
Expand Down
35 changes: 35 additions & 0 deletions crates/bsnext_core/src/server/handler_notification.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::server::actor::ServerActor;
use bsnext_dto::{ClientEvent, DisplayMessageDTO};
use bsnext_input::bs_live_built_in_task::ClientNotification;

#[derive(actix::Message, Debug)]
#[rtype(result = "()")]
pub enum Notification {
Any(ClientNotification),
}

impl actix::Handler<Notification> for ServerActor {
type Result = ();

fn handle(&mut self, msg: Notification, _ctx: &mut Self::Context) -> Self::Result {
let Some(client_sender) = self.client_sender() else {
return tracing::error!("signals not ready, should they be?");
};

match msg {
Notification::Any(ClientNotification::DisplayMessage(dm)) => {
let msg = DisplayMessageDTO {
message: dm.message,
reason: dm.reason,
};
match client_sender.send(ClientEvent::DisplayMessage(msg)) {
Ok(_) => tracing::debug!("send ClientEvent::DisplayMessage to clients"),
Err(e) => {
tracing::error!("did not send ClientEvent::DisplayMessage to clients");
tracing::error!(?e)
}
}
}
}
}
}
1 change: 1 addition & 0 deletions crates/bsnext_core/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod error;
pub mod handler_change;
pub mod handler_client_config;
pub mod handler_listen;
pub mod handler_notification;
pub mod handler_patch;
pub mod handler_routes_updated;
pub mod handler_stop;
Expand Down
3 changes: 3 additions & 0 deletions crates/bsnext_core/src/server/router/pub_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ async fn post_events(
ClientEvent::WsConnection(_) => {
todo!("handle ClientEvent::WsConnection in incoming event handler?")
}
ClientEvent::DisplayMessage(_) => {
todo!("handle ClientEvent::DisplayMessage in incoming event handler...")
}
};
match recv
.send(IncomingEvents::FilesChanged(FilesChanged {
Expand Down
27 changes: 27 additions & 0 deletions crates/bsnext_core/src/servers_supervisor/file_changed_handler.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::server::handler_change::{Change, ChangeWithSpan};
use crate::server::handler_notification::Notification;
use crate::servers_supervisor::actor::ServersSupervisor;
use actix::AsyncContext;
use bsnext_fs::FsEventContext;
use bsnext_input::bs_live_built_in_task::ClientNotification;
use std::path::PathBuf;

#[derive(actix::Message)]
Expand Down Expand Up @@ -59,3 +62,27 @@ impl actix::Handler<FilesChanged> for ServersSupervisor {
}
}
}

#[derive(Debug, Clone, actix::Message)]
#[rtype(result = "()")]
pub enum ServersNotification {
FilesChanged(FilesChanged),
ClientNotification(ClientNotification),
}

impl actix::Handler<ServersNotification> for ServersSupervisor {
type Result = ();

fn handle(&mut self, msg: ServersNotification, ctx: &mut Self::Context) -> Self::Result {
tracing::debug!("looking at {} handlers", self.handlers.len());
match msg {
ServersNotification::FilesChanged(fc) => ctx.notify(fc),
ServersNotification::ClientNotification(notification) => {
for child in self.handlers.values() {
let server_msg = Notification::Any(notification.to_owned());
child.actor_address.do_send(server_msg);
}
}
}
}
}
8 changes: 8 additions & 0 deletions crates/bsnext_dto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,14 @@ pub enum ClientEvent {
Change(ChangeDTO),
WsConnection(ClientConfigDTO),
Config(ClientConfigDTO),
DisplayMessage(DisplayMessageDTO),
}

#[typeshare::typeshare]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct DisplayMessageDTO {
pub message: String,
pub reason: Option<String>,
}

#[typeshare::typeshare]
Expand Down
34 changes: 30 additions & 4 deletions crates/bsnext_input/src/bs_live_built_in_task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use std::str::FromStr;
Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Clone, serde::Deserialize, serde::Serialize,
)]
pub enum BsLiveBuiltInTask {
#[serde(rename = "notify-clients")]
NotifyClients(ClientNotification),
#[serde(rename = "notify-server")]
NotifyServer,
#[serde(rename = "ext-event")]
Expand All @@ -14,10 +16,18 @@ pub enum BsLiveBuiltInTask {
impl FromStr for BsLiveBuiltInTask {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"notify-server" => Ok(Self::NotifyServer),
"ext-event" => Ok(Self::PublishExternalEvent),
_ => Err(anyhow::anyhow!("not a valid bslive builtin task")),
match s.split_once(":") {
Some(("notify-clients", message)) => Ok(Self::NotifyClients(
ClientNotification::DisplayMessage(DisplayMessage {
message: message.to_owned(),
reason: None,
}),
)),
_ => match s {
"notify-server" => Ok(Self::NotifyServer),
"ext-event" => Ok(Self::PublishExternalEvent),
_ => Err(anyhow::anyhow!("not a valid bslive builtin task")),
},
}
}
}
Expand All @@ -26,9 +36,25 @@ impl Display for BsLiveBuiltInTask {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
BsLiveBuiltInTask::NotifyServer => write!(f, "BsLiveTask::NotifyServer"),
BsLiveBuiltInTask::NotifyClients(..) => write!(f, "BsLiveTask::NotifyClients"),
BsLiveBuiltInTask::PublishExternalEvent => {
write!(f, "BsLiveTask::PublishExternalEvent")
}
}
}
}

#[derive(
Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Clone, serde::Deserialize, serde::Serialize,
)]
pub enum ClientNotification {
DisplayMessage(DisplayMessage),
}

#[derive(
Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Clone, serde::Deserialize, serde::Serialize,
)]
pub struct DisplayMessage {
pub message: String,
pub reason: Option<String>,
}
8 changes: 4 additions & 4 deletions crates/bsnext_system/src/capabilities/servers_addr.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
use crate::capabilities::Capabilities;
use actix::{Handler, Recipient, ResponseFuture};
use bsnext_core::servers_supervisor::file_changed_handler::FilesChanged;
use bsnext_core::servers_supervisor::file_changed_handler::ServersNotification;

#[derive(actix::Message)]
#[rtype(result = "Result<Recipient<FilesChanged>, anyhow::Error>")]
#[rtype(result = "Result<Recipient<ServersNotification>, anyhow::Error>")]
pub struct RequestServersAddr;

impl Handler<RequestServersAddr> for Capabilities {
type Result = ResponseFuture<Result<Recipient<FilesChanged>, anyhow::Error>>;
type Result = ResponseFuture<Result<Recipient<ServersNotification>, anyhow::Error>>;

#[tracing::instrument(skip_all, name = "RequestServersAddr")]
fn handle(&mut self, _msg: RequestServersAddr, _ctx: &mut Self::Context) -> Self::Result {
let addr: Recipient<FilesChanged> = self.servers_addr.clone().recipient();
let addr: Recipient<ServersNotification> = self.servers_addr.clone().recipient();
Box::pin(async move { Ok(addr) })
}
}
10 changes: 10 additions & 0 deletions crates/bsnext_system/src/tasks/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::external_event_sender::ExternalEventSenderWithLogging;
use crate::tasks::notify_clients::NotifyClientsReady;
use crate::tasks::notify_servers::NotifyServersReady;
use crate::tasks::sh_cmd::ShCmd;
use crate::tasks::task_spec::{TaskSpec, TreeDisplay};
Expand All @@ -15,6 +16,7 @@ use std::hash::{DefaultHasher, Hash, Hasher};

pub mod comms;
mod into_recipient;
pub mod notify_clients;
pub mod notify_servers;
pub mod resolve;
pub mod sh_cmd;
Expand Down Expand Up @@ -88,6 +90,11 @@ impl AsActor for RunnableWithComms {
let actor = a.start();
actor.recipient()
}
Runnable::BsLiveTask(BsLiveBuiltInTask::NotifyClients(client)) => {
let a = NotifyClientsReady::new(self.ctx.capabilities.recipient(), client);
let actor = a.start();
actor.recipient()
}
Runnable::BsLiveTask(BsLiveBuiltInTask::PublishExternalEvent) => {
let actor = ExternalEventSenderWithLogging::new(self.ctx.capabilities.recipient());
let addr = actor.start();
Expand Down Expand Up @@ -124,6 +131,9 @@ impl From<&RunOptItem> for Runnable {
BsLiveBuiltInTask::PublishExternalEvent => {
Self::BsLiveTask(BsLiveBuiltInTask::PublishExternalEvent)
}
BsLiveBuiltInTask::NotifyClients(notify_clients) => {
Self::BsLiveTask(BsLiveBuiltInTask::NotifyClients(notify_clients.to_owned()))
}
},
RunOptItem::Sh(sh) => Self::Sh(ShCmd::from(sh)),
RunOptItem::ShImplicit(sh) => Self::Sh(ShCmd::new(sh.into())),
Expand Down
68 changes: 68 additions & 0 deletions crates/bsnext_system/src/tasks/notify_clients.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use crate::capabilities::servers_addr::RequestServersAddr;
use actix::{Actor, Handler, Recipient, ResponseFuture};
use bsnext_core::servers_supervisor::file_changed_handler::ServersNotification;
use bsnext_input::bs_live_built_in_task::ClientNotification;
use bsnext_task::invocation::Invocation;
use bsnext_task::invocation_result::InvocationResult;
use bsnext_task::task_trigger::{TaskTrigger, TaskTriggerSource};

pub struct NotifyClientsReady {
addr: Recipient<RequestServersAddr>,
notification: ClientNotification,
}

impl NotifyClientsReady {
pub fn new(addr: Recipient<RequestServersAddr>, notification: ClientNotification) -> Self {
Self { addr, notification }
}
}

impl Actor for NotifyClientsReady {
type Context = actix::Context<Self>;
}

impl Handler<Invocation> for NotifyClientsReady {
type Result = ResponseFuture<InvocationResult>;

fn handle(&mut self, invocation: Invocation, _ctx: &mut Self::Context) -> Self::Result {
tracing::debug!("NotifyClientsReady::TaskCommand");
let addr = self.addr.clone();
let spec_id = invocation.path().to_owned();
Box::pin({
let mut source = self.notification.to_owned();
let ClientNotification::DisplayMessage(ref mut dm) = source;
let trigger = invocation.trigger();
dm.reason = Some(trigger_str(trigger));
async move {
let f = do_it(addr, &source).await;
match f {
Ok(_) => InvocationResult::ok(spec_id),
Err(_) => InvocationResult::err_message(spec_id, "couldn't notify servers"),
}
}
})
}
}

fn trigger_str(trigger: &TaskTrigger) -> String {
match trigger.source() {
TaskTriggerSource::FsChanges(fs) => fs
.changes()
.iter()
.map(|pb| format!("{}", pb.display()))
.collect::<Vec<_>>()
.join(","),
TaskTriggerSource::Exec(_) => "exec".to_string(),
}
}

async fn do_it(
addr: Recipient<RequestServersAddr>,
notification: &ClientNotification,
) -> anyhow::Result<()> {
let next = addr.send(RequestServersAddr).await??;
next.do_send(ServersNotification::ClientNotification(
notification.to_owned(),
));
Ok(())
}
6 changes: 3 additions & 3 deletions crates/bsnext_system/src/tasks/notify_servers.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::capabilities::servers_addr::RequestServersAddr;
use actix::{Actor, Handler, Recipient, ResponseFuture};
use bsnext_core::servers_supervisor::file_changed_handler::FilesChanged;
use bsnext_core::servers_supervisor::file_changed_handler::{FilesChanged, ServersNotification};
use bsnext_task::invocation::Invocation;
use bsnext_task::invocation_result::InvocationResult;
use bsnext_task::task_trigger::{FsChangesTrigger, TaskTriggerSource};
Expand Down Expand Up @@ -50,9 +50,9 @@ async fn do_it(
trigger: &FsChangesTrigger,
) -> anyhow::Result<()> {
let next = addr.send(RequestServersAddr).await??;
next.do_send(FilesChanged {
next.do_send(ServersNotification::FilesChanged(FilesChanged {
paths: trigger.changes().to_owned(),
ctx: trigger.fs_ctx().to_owned(),
});
}));
Ok(())
}
2 changes: 1 addition & 1 deletion crates/bsnext_system/src/watchables/route_watchable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub fn to_route_watchables(input: &Input) -> Vec<RouteWatchable> {
spec.only = spec.only.or_else(|| input.config.global_fs_only.to_owned());

// respect a given spec's 'debounce' (eg: if provided by user), otherwise try to use the global
spec.debounce = spec.debounce.or_else(|| input.config.global_fs_debounce);
spec.debounce = spec.debounce.or(input.config.global_fs_debounce);

let run = to_task_spec(&spec);
let route_path = r.path.as_str().to_owned();
Expand Down
8 changes: 7 additions & 1 deletion generated/dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ export interface DebounceDTO {
ms: string;
}

export interface DisplayMessageDTO {
message: string;
reason?: string;
}

export interface FileChangedDTO {
path: string;
}
Expand Down Expand Up @@ -219,7 +224,8 @@ export enum ChangeKind {
export type ClientEvent =
| { kind: "Change", payload: ChangeDTO }
| { kind: "WsConnection", payload: ClientConfigDTO }
| { kind: "Config", payload: ClientConfigDTO };
| { kind: "Config", payload: ClientConfigDTO }
| { kind: "DisplayMessage", payload: DisplayMessageDTO };

export enum EventLevel {
External = "BSLIVE_EXTERNAL",
Expand Down
9 changes: 9 additions & 0 deletions generated/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ var debounceDTOSchema = z.object({
kind: z.string(),
ms: z.string()
});
var displayMessageDTOSchema = z.object({
message: z.string(),
reason: z.string().optional()
});
var fileChangedDTOSchema = z.object({
path: z.string()
});
Expand Down Expand Up @@ -235,6 +239,10 @@ var clientEventSchema = z.discriminatedUnion("kind", [
z.object({
kind: z.literal("Config"),
payload: clientConfigDTOSchema
}),
z.object({
kind: z.literal("DisplayMessage"),
payload: displayMessageDTOSchema
})
]);
var eventLevelSchema = z.nativeEnum(EventLevel);
Expand Down Expand Up @@ -443,6 +451,7 @@ export {
clientEventSchema,
connectInfoSchema,
debounceDTOSchema,
displayMessageDTOSchema,
eventLevelSchema,
externalEventsDTOSchema,
fileChangedDTOSchema,
Expand Down
Loading
Loading