Plugin Execution Order

We have a number of custom plugins and I wish to run one of them before another one. How do I control this and how are they ordered by default?

I can't seem to find anything in the IConfigurablePlugin interface that allows me to do this or any documentation around this.

Parents
  • The order is not guaranteed, you may want to use an orchestration plugin that the other plugins register in their Initialize() method and then the orchestration plugin could handle the AfterInitialization event on the plugin manager ( https://community.telligent.com/community/10/w/api-documentation/60576/pluginmanager-in-process-api-service ) to execute dependent code on the registered plugins in the correct order.

  • Thanks Ben, 

    Do you have any example of using this to register my plugins?
    I’ve looked at the link but it’s not clear to me how I would go about doing this. 
  • In each plugins initialize method, retrieve the registration plugin by its type from plugin manager's Get<T>() method and call a public method on that plugin to register the child plugins requiring orchestration.

    An alternative approach is to define a new plugin interface (just needs to inherit from IPlugin) and provide an OrderNumber and Execute method on it. In an orchestration plugin, in an AfterInitialize handler (handling the event on Plugin Manager), retrieve all implementations of the new plugin interface from plugin manager via it's Get<T>() , order the results, and call execute.

    Let me know if that helps. If not, I'll try to setup a code example.

  • I've read over your response a few times but I'm not 100% sure I understand. I get the idea of an parent plugin that registers the child plugins or an interface with an order number but I'm not sure how this would work as won't my plugins still be picked (since they implement the IConfigurablePlugin interface) and therefore perhaps registered twice, once by my orchestrator / interface with order number and once by the platform? I think a code sample would be really useful if you have one to hand.

  • Here's a code example. It defines a new (custom) plugin type IOrchestratedPlugin and a service plugin, PluginOrchestration, to allow plugins to define an execution order (relative to all other IOrchestratedPlugin implementations). The PluginOrchestration plugin loads all IOchestratedPlugins after plugins are initialized, sorts them by their order number, and calls their Execute() method where the dependent/order-specific logic should be implemented.

    // note: using System.Linq;
    
    public interface IOrchestratedPlugin : Telligent.Evolution.Extensibility.Version1.IPlugin
    {
        int OrderNumber { get; }
        void Execute();
    }
    
    public class PluginOrchestration : Telligent.Evolution.Extensibility.Version1.IPlugin
    {
        public string Name => "Plugin Orchestration";
        public string Description => "Orchestrates plugins to initialize in a specific order";
    
        public void Initialize()
        {
            // Register to execute orchestrated plugins after all plugins have been initialized.
            Telligent.Evolution.Extensibility.Version1.PluginManager.AfterInitialization += PluginManager_AfterInitialization;
        }
    
        private void PluginManager_AfterInitialization(object sender, EventArgs e)
        {
            // Now that all plugins are initialized, load them, order them, and execute them
            foreach (var orchestratedPlugin in Telligent.Evolution.Extensibility.Version1.PluginManager.Get<IOrchestratedPlugin>().OrderBy(x => x.OrderNumber))
            {
                orchestratedPlugin.Execute();
            }
        }
    }
    
    public class MyOrchestratedPlugin1 : IOrchestratedPlugin
    {
        // TODO: Other IPlugin members
    
        public int OrderNumber => 1;
        public void Execute()
        {
            // TODO: Ordered work
        }
    }
    
    public class MyOrchestratedPlugin2 : IOrchestratedPlugin
    {
        // TODO: Other IPlugin members
    
        public int OrderNumber => 2;
        public void Execute()
        {
            // TODO: Ordered work
        }
    }

  • Great, thanks Ben. I'll give this a go. So I guess as the plugins implement IOrchestratedPlugin and not IConfigurablePlugin then this is why the platform doesn't pick up the plugins and regsiter them already?

  • They still need to be enabled when deployed. A plugin could implement IOrchestratedPlugin and IConfigurablePlugin (and any number of other plugin types) as well.

  • I've tested this code and it all seems to be working well. I do have a couple of follow up questions though:

    1) I've moved what was in the Initialize() method of each plugin that implements the IOrchestratedPlugin interface into the new execute() method (so Initialize() is now empty. Is that right? It seems to be working ok. e.g I now have this:

         public void Execute()
            {
                Apis.Get<IUsers>().Events.AfterCreate += Events_AfterCreate;
            }


    2) Is it possible to get the custom plugins to execute before the out of the box ones? If so how would this be achieved?

    2) Could the order parameter be added out of the box to the plugin interface in a future release? I'm sure I'm not the only one who needs to do this.

Reply
  • I've tested this code and it all seems to be working well. I do have a couple of follow up questions though:

    1) I've moved what was in the Initialize() method of each plugin that implements the IOrchestratedPlugin interface into the new execute() method (so Initialize() is now empty. Is that right? It seems to be working ok. e.g I now have this:

         public void Execute()
            {
                Apis.Get<IUsers>().Events.AfterCreate += Events_AfterCreate;
            }


    2) Is it possible to get the custom plugins to execute before the out of the box ones? If so how would this be achieved?

    2) Could the order parameter be added out of the box to the plugin interface in a future release? I'm sure I'm not the only one who needs to do this.

Children
  • 1) I've moved what was in the Initialize() method of each plugin that implements the IOrchestratedPlugin interface into the new execute() method (so Initialize() is now empty. Is that right?

    Execute() should contain any logic that needs to be performed in a specific order. Note that your orchestration plugin should ensure that Execute() is only called once per initialize (as it does now) to allow child plugins to add event handlers in Execute().

    2) Is it possible to get the custom plugins to execute before the out of the box ones? If so how would this be achieved?

    No. Plugin execution order is not guaranteed and the platform does not provide a way to control it. The solution provided in this thread is for dependencies within a known set of plugins and isn't a general use/extensible solution.

    2) Could the order parameter be added out of the box to the plugin interface in a future release? I'm sure I'm not the only one who needs to do this.

    Could I get more details about the use case challenge that led you to this need? The platform has hundreds of plugins that implement both core and extension functionality and we don't have execution dependencies. A platform-defined solution would likely need to identify direct plugin dependencies instead of a concrete order number, but, again I'd appreciate more details about the need.