[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
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
7dc1718c1d
Коммит
6af032d06a
@@ -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
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user