3

Scenario:
I'm running some script that changed some attribute values for some products.
Because of performance reasons, I split this into batches.

Problem:
But each time I'm done with a batch the reindexing starts for the products that belong to that batch. Indexes are set to "real time".

Desired result: I want to disable the reindexing during the execution of my script.
But I don't want to set the reindex mode to 'schedule' because my script can take a while and any other operations done via admin need to still trigger the indexing for those specific products.

Main Question:
How can I tell magento at the start of my script "Don't reindex anything during this script, no matter on how the index mode is set!!" ?

Note: The script is a magento command executed either via cli or cron.

1

Great question! In theory this is possible. Magento commands are based on Symfony. You could use Symfony\Component\Filesystem\LockHandler class to create a lock to your command.

Then have a plugin to the reindex manager, where you would check if your command is locked. If your command is locked then it means it's running therefore don't proceed to the reindexing etc.

Note: When your commands ends make sure to release it.

2
  • thanks for the idea. one drawback though. If my command crashes, then reindexing will not be triggered until I manually remove the lock. but I think I can overcome that by setting something in the registry when my command starts instead of using locks. and use that registry value in the plugin. could you explain more about pluginizing the reindex manager. What method should I pluginize from what class? What's the central point of triggering reindexing? – Marius Sep 7 '18 at 14:54
  • No worries. Using registry will also have the same effect if your command crashes. If you use PHP7, you can always wrap your command logic within a try & catch block and have the catch as the fall back to unlock it. Have a look at these classes \Magento\Indexer\Model\Indexer and \Magento\Indexer\Model\Processor for the plugin stuff. – André Ferraz Sep 11 '18 at 21:40
1

I ended up taking an approach that looks a bit dirty, but it does the job.

My script starts with this:

$this->registry->register('skip_indexing', true);

and ends with

$this->registry->unregister('skip_indexing');

where $this->registry is an instance of \Magento\Framework\Registry.

and I've added an after plugin for \Magento\Indexer\Model\Indexer::isScheduled to simulate that the indexer is set "on schedule".

public function afterIsScheduled(\Magento\Indexer\Model\Indexer $subject, $result)
{
    if ($this->registry->registry('skip_indexing')) {
        return true;
    }
    return $result;
}

Not proud of it, but it gets the job done.

5
  • Please let us know if you found a better solution ! – LittleBigDev Jan 21 '20 at 8:46
  • I didn't even look for a better solution. I'm happy with the one above. It's easy to implement and it does not screw up anything else. I got over the part that it looks hacky and moved on. – Marius Jan 21 '20 at 9:08
  • Well, as it is a deprecated class, we'll have - some day - to find sth else. Oh and FYI I used your solution, but I used "running" instead of "scheduled" because on my VERY long import, some reindeing could be launched by Magento because... scheduled ! – LittleBigDev Jan 22 '20 at 14:27
  • You don't need to use registry if that's deprecated. You can have your own class called IndexingState (or something like that) with 2 methods get and set that do the same thing as registry and register from Registry class and you're done. – Marius Jan 22 '20 at 14:50
  • Do you have the full code for the 'after' plugin - ie how/where do we add it? We have the same need as you to disable reindexing while a script executes, else the script takes forever to run. – Chris Apr 6 '20 at 14:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.