refactor(msg-bus): prefer MessageBus as Realtime

This commit is contained in:
Edouard Vanbelle
2026-09-11 00:25:25 +02:00
parent 1d280c161c
commit 7918fff47b
51 changed files with 295 additions and 227 deletions
+15 -15
View File
@@ -703,12 +703,12 @@ impl AppServiceFactory {
resource_access_hook: Option<
Arc<dyn crate::application::ports::resource_access_hook::ResourceAccessHook>,
>,
bus: &Arc<crate::infrastructure::services::in_process_realtime_bus::InProcessRealtimeBus>,
bus: &Arc<crate::infrastructure::services::in_process_message_bus::InProcessMessageBus>,
) -> ApplicationServices {
// Upcast the concrete bus once — service builders take the
// trait object so the wire remains stable across future bus
// impls.
let bus_trait: Arc<dyn crate::application::ports::realtime_ports::RealtimeBus> =
let bus_trait: Arc<dyn crate::application::ports::message_bus_ports::MessageBus> =
bus.clone();
// Main services
@@ -732,9 +732,9 @@ impl AppServiceFactory {
// already runs. Without this, a Move that would push the
// destination past its cap succeeds silently.
.with_storage_usage(storage_usage.clone())
// Realtime fan-out on `create_folder_with_perms` — the
// Bus fan-out on `create_folder_with_perms` — the
// parent-folder subscribers see new sub-folders live.
.with_realtime_bus(bus_trait.clone()),
.with_message_bus(bus_trait.clone()),
);
// Built before the upload/management services so the plugin lifecycle
@@ -782,10 +782,10 @@ impl AppServiceFactory {
core.dedup_service.clone(),
storage_usage.clone(),
)
// Realtime fan-out — every successful `upload_file_streaming`
// Bus fan-out — every successful `upload_file_streaming`
// publishes a `FileCreated` event on the parent folder's
// topic so open folder views refresh live.
.with_realtime_bus(bus_trait.clone());
.with_message_bus(bus_trait.clone());
if let Some(hook) = resource_access_hook.clone() {
svc = svc.with_resource_access_hook(hook);
}
@@ -826,11 +826,11 @@ impl AppServiceFactory {
// Destination-drive quota pre-check on cross-drive file
// MOVE. Same rationale as the folder side above.
.with_storage_usage(storage_usage.clone())
// Realtime fan-out on delete / rename / move — each hook
// Bus fan-out on delete / rename / move — each hook
// publishes on the affected folder topic (move fans out on
// BOTH source and destination) so folder-view subscribers
// see the mutation live.
.with_realtime_bus(bus_trait.clone());
.with_message_bus(bus_trait.clone());
if let Some(hook) = resource_access_hook.clone() {
svc = svc.with_resource_access_hook(hook);
}
@@ -1794,15 +1794,15 @@ impl AppServiceFactory {
crate::application::services::external_mount_router::MountRouter::new(mount_registry),
);
// Realtime bus: single instance for the app lifetime, wired
// Message bus: single instance for the app lifetime, wired
// with a no-op replicator (multi-instance broker is a follow-up
// per `docs/plan/message-bus.md § Roadmap`). Constructed here
// so `create_application_services` can hand it to services that
// publish after their DB commits (`FolderService`,
// `FileUploadService`, …). Spawns its own GC task in
// `with_replicator` — no supervisor setup required.
let bus = crate::infrastructure::services::in_process_realtime_bus::InProcessRealtimeBus::with_replicator(
Arc::new(crate::application::ports::realtime_ports::NoopReplicator),
let bus = crate::infrastructure::services::in_process_message_bus::InProcessMessageBus::with_replicator(
Arc::new(crate::application::ports::message_bus_ports::NoopReplicator),
);
let mut apps = self.create_application_services(
@@ -3209,19 +3209,19 @@ pub struct AppState {
/// method (which still owns the authorization check).
pub mount_router:
Arc<crate::application::services::external_mount_router::MountRouter>,
/// Realtime message bus. Always present — an empty bus (no
/// Message bus. Always present — an empty bus (no
/// subscribers, no publishes) costs a single `DashMap` allocation.
/// The WS handler reads `subscribe`; service publish hooks
/// (`FolderService::create_folder_with_perms`,
/// `FileManagementService`'s file-create commit) call `publish`
/// AFTER their DB transaction commits.
///
/// Stored as the concrete type (not `Arc<dyn RealtimeBus>`) so the
/// Stored as the concrete type (not `Arc<dyn MessageBus>`) so the
/// GC task's `Weak<Self>` lifecycle is legible from di.rs. Consumers
/// that only need the trait obtain it via
/// `Arc::clone(&state.bus) as Arc<dyn RealtimeBus>`.
/// `Arc::clone(&state.bus) as Arc<dyn MessageBus>`.
pub bus: Arc<
crate::infrastructure::services::in_process_realtime_bus::InProcessRealtimeBus,
crate::infrastructure::services::in_process_message_bus::InProcessMessageBus,
>,
pub auth_service: Option<AuthServices>,
/// OPAQUE aPAKE substrate (RFC 9807). Populated only when