Issues (50)

src/Traits/IndexingTraits/IndexingTrait.php (5 issues)

Labels
Severity
1
<?php
2
3
namespace Firesphere\SearchBackend\Traits\IndexingTraits;
4
5
use Exception;
6
use Firesphere\SearchBackend\Helpers\IndexingHelper;
7
use HttpException;
8
use SilverStripe\Control\Controller;
9
use SilverStripe\Control\Director;
10
use SilverStripe\Control\HTTPRequest;
11
use SilverStripe\ORM\DB;
12
use Solarium\Exception\HttpException as SolrException;
0 ignored issues
show
The type Solarium\Exception\HttpException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
14
trait IndexingTrait
15
{
16
    /**
17
     * Set up the requirements for this task
18
     *
19
     * @param HTTPRequest $request Current request
20
     * @return array
21
     */
22
    protected function taskSetup(HTTPRequest $request): array
23
    {
24
        $vars = $request->getVars();
25
        $debug = $this->isDebug() || isset($vars['debug']);
0 ignored issues
show
It seems like isDebug() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

25
        $debug = $this->/** @scrutinizer ignore-call */ isDebug() || isset($vars['debug']);
Loading history...
26
        // Forcefully set the debugging to whatever the outcome of the above is
27
        $this->setDebug($debug, true);
0 ignored issues
show
It seems like setDebug() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

27
        $this->/** @scrutinizer ignore-call */ 
28
               setDebug($debug, true);
Loading history...
28
        $group = $vars['group'] ?? 0;
29
        $start = $vars['start'] ?? 0;
30
        $group = ($start > $group) ? $start : $group;
31
        $isGroup = isset($vars['group']);
32
33
        return [$vars, $group, $isGroup];
34
    }
35
36
    /**
37
     * Index the classes for a specific index
38
     *
39
     * @param array $classes Classes that need indexing
40
     * @param bool $isGroup Indexing a specific group?
41
     * @param int $group Group to index
42
     * @return int|bool
43
     * @throws Exception
44
     * @throws HTTPException|HttpClientException|SolrException
45
     */
46
    protected function indexClassForIndex(array $classes, bool $isGroup, int $group)
47
    {
48
        $groups = 0;
49
        foreach ($classes as $class) {
50
            $groups = $this->indexClass($isGroup, $class, $group);
0 ignored issues
show
The method indexClass() does not exist on Firesphere\SearchBackend...ingTraits\IndexingTrait. Did you maybe mean indexClassForIndex()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

50
            /** @scrutinizer ignore-call */ 
51
            $groups = $this->indexClass($isGroup, $class, $group);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
51
        }
52
53
        return $groups;
54
    }
55
56
    /**
57
     * Check if PCNTL is available and/or useable.
58
     * The unittest param is from phpunit.xml.dist, meant to bypass the exit(0) call
59
     * The pcntl parameter check is for unit tests, but PHPUnit does not support PCNTL (yet)
60
     *
61
     * @return bool
62
     */
63
    private function hasPCNTL(): bool
64
    {
65
        return Director::is_cli() &&
66
            function_exists('pcntl_fork') &&
67
            (Controller::curr()->getRequest()->getVar('unittest') === 'pcntl' ||
68
                !Controller::curr()->getRequest()->getVar('unittest'));
69
    }
70
71
    /**
72
     * For each core, spawn a child process that will handle a separate group.
73
     * This speeds up indexing through CLI massively.
74
     *
75
     * @codeCoverageIgnore Can't be tested because PCNTL is not available
76
     * @param string $class Class to index
77
     * @param int $group Group to index
78
     * @param int $groups Total amount of groups
79
     * @return int Last group indexed
80
     * @throws Exception
81
     * @throws HTTPException
82
     */
83
    private function spawnChildren(string $class, int $group, int $groups): int
84
    {
85
        $start = $group;
86
        $pids = [];
87
        $cores = IndexingHelper::getCores();
88
        // for each core, start a grouped indexing
89
        for ($i = 0; $i < $cores; $i++) {
90
            $start = $group + $i;
91
            if ($start < $groups) {
92
                $this->runForkedChild($class, $pids, $start);
93
            }
94
        }
95
        // Wait for each child to finish
96
        // It needs to wait for them independently,
97
        // or it runs out of memory for some reason
98
        foreach ($pids as $pid) {
99
            pcntl_waitpid($pid, $status);
100
        }
101
102
        return $start;
103
    }
104
105
    /**
106
     * Create a fork and run the child
107
     *
108
     * @codeCoverageIgnore Can't be tested because PCNTL is not available
109
     * @param string $class Class to index
110
     * @param array $pids Array of all the child Process IDs
111
     * @param int $start Start point for the objects
112
     * @return void
113
     * @throws HTTPException
114
     * @throws ValidationException
115
     */
116
    private function runForkedChild(string $class, array &$pids, int $start): void
117
    {
118
        $pid = pcntl_fork();
119
        // PID needs to be pushed before anything else, for some reason
120
        $pids[] = $pid;
121
        $config = DB::getConfig();
122
        DB::connect($config);
123
        $this->runChild($class, $pid, $start);
0 ignored issues
show
It seems like runChild() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

123
        $this->/** @scrutinizer ignore-call */ 
124
               runChild($class, $pid, $start);
Loading history...
124
    }
125
}
126