[MM-35077] Add basic support for plugin intra-cluster communication (#17495)

* Add basic support for plugin intra-cluster communication

* Some renaming for added clarity

* Allow sending cluster event to specific nodes

* Improve naming and documentation

* Improve logging
Этот коммит содержится в:
Claudio Costa
2021-04-28 19:59:32 +02:00
коммит произвёл GitHub
родитель 7dc1718c1d
Коммит 6af032d06a
15 изменённых файлов: 236 добавлений и 4 удалений

Просмотреть файл

@@ -120,6 +120,10 @@ func (c *ClusterMock) SendClusterMessage(msg *model.ClusterMessage) {
c.Busy.ClusterEventChanged(sbs)
}
func (c *ClusterMock) SendClusterMessageToNode(nodeID string, msg *model.ClusterMessage) error {
return nil
}
func (c *ClusterMock) StartInterNodeCommunication() {}
func (c *ClusterMock) StopInterNodeCommunication() {}
func (c *ClusterMock) RegisterClusterMessageHandler(event string, crm einterfaces.ClusterMessageHandler) {

Просмотреть файл

@@ -20,6 +20,7 @@ func (a *App) registerAppClusterMessageHandlers() {
a.Cluster().RegisterClusterMessageHandler(model.CLUSTER_EVENT_CLEAR_SESSION_CACHE_FOR_ALL_USERS, a.clusterClearSessionCacheForAllUsersHandler)
a.Cluster().RegisterClusterMessageHandler(model.CLUSTER_EVENT_INSTALL_PLUGIN, a.clusterInstallPluginHandler)
a.Cluster().RegisterClusterMessageHandler(model.CLUSTER_EVENT_REMOVE_PLUGIN, a.clusterRemovePluginHandler)
a.Cluster().RegisterClusterMessageHandler(model.CLUSTER_EVENT_PLUGIN_EVENT, a.clusterPluginEventHandler)
}
func (a *App) clusterClearSessionCacheForUserHandler(msg *model.ClusterMessage) {
@@ -34,6 +35,35 @@ func (a *App) clusterInstallPluginHandler(msg *model.ClusterMessage) {
a.InstallPluginFromData(model.PluginEventDataFromJson(strings.NewReader(msg.Data)))
}
func (a *App) clusterPluginEventHandler(msg *model.ClusterMessage) {
env := a.GetPluginsEnvironment()
if env == nil {
return
}
if msg.Props == nil {
mlog.Warn("ClusterMessage.Props for plugin event should not be nil")
return
}
pluginID := msg.Props["PluginID"]
eventID := msg.Props["EventID"]
if pluginID == "" || eventID == "" {
mlog.Warn("Invalid ClusterMessage.Props values for plugin event",
mlog.String("plugin_id", pluginID), mlog.String("event_id", eventID))
return
}
hooks, err := env.HooksForPlugin(pluginID)
if err != nil {
mlog.Warn("Getting hooks for plugin failed", mlog.String("plugin_id", pluginID), mlog.Err(err))
return
}
hooks.OnPluginClusterEvent(a.PluginContext(), model.PluginClusterEvent{
Id: eventID,
Data: []byte(msg.Data),
})
}
func (a *App) clusterRemovePluginHandler(msg *model.ClusterMessage) {
a.RemovePluginFromData(model.PluginEventDataFromJson(strings.NewReader(msg.Data)))
}

Просмотреть файл

@@ -1063,3 +1063,34 @@ func (api *PluginAPI) DeleteCommand(commandID string) error {
return nil
}
// PublishPluginClusterEvent broadcasts a plugin event to all other running instances of
// the calling plugin.
func (api *PluginAPI) PublishPluginClusterEvent(ev model.PluginClusterEvent,
opts model.PluginClusterEventSendOptions) error {
if api.app.Cluster() == nil {
return nil
}
msg := &model.ClusterMessage{
Event: model.CLUSTER_EVENT_PLUGIN_EVENT,
SendType: opts.SendType,
WaitForAllToSend: false,
Props: map[string]string{
"PluginID": api.id,
"EventID": ev.Id,
},
Data: string(ev.Data),
}
// If TargetId is empty we broadcast to all other cluster nodes.
if opts.TargetId == "" {
api.app.Cluster().SendClusterMessage(msg)
} else {
if err := api.app.Cluster().SendClusterMessageToNode(opts.TargetId, msg); err != nil {
return fmt.Errorf("failed to send message to cluster node %q: %w", opts.TargetId, err)
}
}
return nil
}