split EventBus into DaemonBus + MessageBus
DaemonBus (was EventBus): typed events for system/IPC layer. MessageBus: channel-based pub/sub for UI/extension coordination. Messages carry publisher (auto-stamped from extension ID), channel (required), timestamp, and payload. Subscribe by publisher, channel, or both — zero collision across extensions. Extension context gains publish() and subscribe() convenience methods that auto-stamp the extension's ID as publisher. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,8 +2,8 @@ import 'dart:async';
|
||||
|
||||
import 'package:clide/kernel/src/events/types.dart';
|
||||
|
||||
class EventBus {
|
||||
EventBus();
|
||||
class DaemonBus {
|
||||
DaemonBus();
|
||||
|
||||
final StreamController<ClideEventEnvelope> _controller =
|
||||
StreamController<ClideEventEnvelope>.broadcast();
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import 'dart:async';
|
||||
|
||||
class Message {
|
||||
Message({
|
||||
required this.publisher,
|
||||
required this.channel,
|
||||
required this.data,
|
||||
}) : timestamp = DateTime.now();
|
||||
|
||||
final String publisher;
|
||||
final String channel;
|
||||
final DateTime timestamp;
|
||||
final Map<String, Object?> data;
|
||||
|
||||
String get address => '$publisher/$channel';
|
||||
}
|
||||
|
||||
class MessageBus {
|
||||
final _controller = StreamController<Message>.broadcast();
|
||||
|
||||
void publish(String publisher, String channel, Map<String, Object?> data) {
|
||||
_controller.add(Message(publisher: publisher, channel: channel, data: data));
|
||||
}
|
||||
|
||||
Stream<Message> subscribe({String? publisher, String? channel}) {
|
||||
return _controller.stream.where((m) {
|
||||
if (publisher != null && m.publisher != publisher) return false;
|
||||
if (channel != null && m.channel != channel) return false;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
_controller.close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user