Skip to content

Latest commit

 

History

History

README.md

EventBrokerDemo

Publish/Subscribe communication between plugins via the EventBroker.

Architecture

EventBrokerDemo.exe
|   DCC_UsePackage = rtl;fmx;FMXPluginFramework
|
+-- Register TEventBroker
+-- TBPLLoader.LoadAll(plugins.json)
|
+-- PluginAlpha.bpl    -> subscribed to 'alpha' + 'broadcast'
+-- PluginBeta.bpl     -> subscribed to 'beta' + 'broadcast'
+-- PluginGamma.bpl    -> subscribed to 'gamma' + 'broadcast'
+-- PluginAndromeda.bpl -> subscribed to 'andromeda' + 'andromeda.show' + 'broadcast'
|
+-- MainForm: Buttons publish topics
    +-- Alpha / Beta / Gamma / Andromeda -> targeted topic
    +-- Open Andromeda -> 'andromeda.show'
    +-- Broadcast -> all plugins react

What This Demo Shows

  • IEventBroker: Publish/Subscribe for loose plugin coupling
  • Sender info via AData: TStringList with Values['sender'] as context
  • 4 plugins with frames: Each plugin displays received events in its own TMemo
  • Broadcast pattern: A topic that reaches all plugins simultaneously
  • Ring pattern: Plugins can react to events from other plugins

Files

File Purpose
EventBrokerDemo.dpr Host app with EventBroker registration
Source/uMain.pas + .fmx MainForm with buttons + plugin frames side by side
EventBrokerDemo.groupproj Build: Framework -> 4 Plugins -> App
plugins.json Plugin list (Alpha, Beta, Gamma, Andromeda)
../DemoPlugins/PluginAlpha/ Plugin with frame + EventBroker subscriber
../DemoPlugins/PluginBeta/ Plugin with frame + EventBroker subscriber
../DemoPlugins/PluginGamma/ Plugin with frame + EventBroker subscriber
../DemoPlugins/PluginAndromeda/ Plugin with frame + EventBroker subscriber

How It Works

  1. Host registers TEventBroker as IEventBroker service
  2. Plugins subscribe to their topics in Initialize
  3. Buttons in the MainForm publish topics with sender info
  4. Plugins receive events and log them in their frames
  5. Shutdown: ClearAll -> UnloadAll -> ReleaseInstance

IEventBroker Interface

IEventBroker -- Publish/Subscribe

IEventBroker = interface
  procedure Subscribe(const ATopic: string; const ACallback: TEventCallback);
  procedure Unsubscribe(const ATopic: string; const ACallback: TEventCallback);
  procedure Publish(const ATopic: string; const AData: TObject = nil);
end;

Subscribe

procedure TMyPlugin.Initialize;
var Svc: IInterface;
begin
  if TServiceRegistry.Instance.GetService(IEventBroker, Svc) then
    (Svc as IEventBroker).Subscribe('my.topic', HandleEvent);
end;

Publish with Sender Info

var
  Data: TStringList;
begin
  Data := TStringList.Create;
  try
    Data.Values['sender'] := 'MyPlugin';
    EventBroker.Publish('my.topic', Data);
  finally
    Data.Free;
  end;
end;

Thread Safety

Callbacks are collected inside the lock, then invoked outside the lock. This means:

  • A subscriber can safely unsubscribe from within its own callback
  • One failing callback doesn't block others
  • No deadlocks from re-entrant calls