cancel
Showing results for 
Search instead for 
Did you mean: 

plugin sort order dependencies

0 Kudos

plugin sort order dependencies

Feature request from airbone42, posted on GitHub Dec 22, 2014

Hi,

I'm currently playing around with the plugin interceptors. Currently the only way to handle the order of plugins is by the sortOrder attribute. Unfortunately that's very lmiited as it only accepts a hardcoded integer value. Especially if you have dependencies between different modules it's very risky to use these, as if some other module changes it's sort order your extension might break.

Would Magento be interested in a solution where you could define a before or after attribute (similar to the layout blocks) to define if a plugin should be run before or after any other specific plugin? For me that would be a great solution to also handle bigger dependency chains and it's less likely to break if when the amount of plugins is growing. What drawbacks can you see in this solution?

18 Comments
apiuser
New Member
Status changed to: Investigating
 
apiuser
New Member

Comment from antonkril, posted on GitHub Dec 22, 2014

What should happen if module that your plugin depends on (goes "after") is not installed?

apiuser
New Member

Comment from airbone42, posted on GitHub Dec 22, 2014

An idea would be to write that in the error.log. I would not throw an exception, so it could be an optional dependency. If it's a hard dependency that module itself should already depend on the other module.

apiuser
New Member

Comment from antonkril, posted on GitHub Dec 22, 2014

And if you want to go both after Plugin A and Plugin B?

apiuser
New Member

Comment from airbone42, posted on GitHub Dec 22, 2014

That's more a question about the syntax. Separate it by some separator or let's do it as sub-elements, not an attribute? I first wanted to ask about the concept of that idea, if there's any reason you didn't think about it? If you think it's a good idea it's definitely time to get one step further and think about a concrete implementation (including syntax and exceptions)

apiuser
New Member

Comment from CodeMonkey90, posted on GitHub Dec 22, 2014

Great idea! I just read the documentation and immediately thought about all the possible problems. I especially fear that everyone will try to make sure his/her plugin is loaded as the first plugin and all plugins will end up having sortOrder="1". Just like in the Magento 1 backend, where everyone tries to make his plugin appear at the top of the configuration page.

BTW: I would just silently ignore plugins which are not installed. Spamming the error.log file is unnecessary, since it makes a lot of sense to make sure your plugin works nicely with some other community plugins which it doesn't depend on.

apiuser
New Member

Comment from antonkril, posted on GitHub Dec 22, 2014

We had these two approaches used in Magento 1. The problem with before/after approach is that sort order of your plugin depends on presence of other plugin in system. But if that plugin is not present, your sort order becomes undefined. So we choose approach with sort order. This way its sort order is always defined. But if you see problems with this, we can discuss syntax for before/after.

apiuser
New Member

Comment from CodeMonkey90, posted on GitHub Dec 22, 2014

Okay, if none of the specified modules exist, then the sort order is undefined, of course. But I don't think that's a problem, since in this case the module developer obviously doesn't care about the sort order.

Problems with the current approach

Two examples to illustrate problems with the current approach that would be solved by the above proposal:

Scenario 1

Imagine a Magento installation with a lot of 3rd party plugins (I maintain one of those). Plugin A and B both have a sort order of 1.¹ Now I need to write a plugin that runs between those two. Entirely impossible!

If you'd implement airbone42's proposal, OTOH, both A and B wouldn't specify any ordering (because their developers obviously don't care about the sort order) and my plugin could specify that it needs to run between those two.

Of course, there could be cases where the ordering requirements of two plugins conflict. But in that case, the two modules are obviously incompatible and cannot be used together anyway.

Scenario 2

I have installed two third-party plugins. The developers of those modules didn't know or care about each others module, but during testing I discover that one of them must run before the other. I can now simply create a third module with a dummy plugin and specify that it must be run between those two: Problem solved.

My Proposal (formal description)

Let plugin developers specify that their plugin needs to run before or after certain other plugins. Build a directed acyclic dependency graph from that information (if the dependency graph has cycles, die with an appropriate error message). Then sort the plugins topologically and execute them in that order.


¹ Which is what most 3rd-party developers are probably going to specify, since they cannot possibly test their module's interaction with any other 3rd-party module. So, in practice, the sort order is neither well-defined nor sensible anyway, even if you use integers.

P.S.: Sorry for the multiple edits

apiuser
New Member

Comment from airbone42, posted on GitHub Dec 23, 2014

Landkeks already explained the problems with the current approach. Especially for supporting the wider community where modules are developed by different companies, which do not know of each other or just won't cooperate the current approach will lead to problems.

I would like to add a possible syntax example. To not mix attributes and elements too much I would move the current sortOrder attribute in a new child-element and set it's value as the attribute of that element. Additionally we could define multiple before and after elements.

<type name="Magento\Backend\App\AbstractAction">
    <plugin name="adminAuthentication" type="Magento\Backend\App\Action\Plugin\Authentication">
        <sortOrder value="100">
            <before value="plugin_name_a" />
            <before value="plugin_name_b" />
            <after value="plugin_name_c" />
        </sortOrder>
    </plugin>
</type>

If this leads to conflicts (e.g. circular dependencies or the sortOrder of a before plugin is higher than the current specified) we should ignore the before and after values and log this as a possible error.

apiuser
New Member

Comment from CodeMonkey90, posted on GitHub Dec 23, 2014

@airbone42 I wonder why you're suggesting we should keep the sortOrder attribute/element at all. I think mixing two different ways of defining the sort order is confusing and a sorting algorithm which takes both into account sounds hard to implement. I'd drop the sortOrder completely and order based on the before and after elements. Those state the intent of the developer more clearly and allow efficient topological sorting.

<type name="Magento\Backend\App\AbstractAction">
    <plugin name="adminAuthentication" type="Magento\Backend\App\Action\Plugin\Authentication">
        <before value="plugin_name_a" />
        <before value="plugin_name_b" />
        <after value="plugin_name_c" />
    </plugin>
</type>

looks better to me.