Passed
Push — feature/Logging ( d4b3c6...39dd77 )
by Simon
04:52
created

SolrConfigureTask::getStore()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 4
c 4
b 0
f 0
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
4
namespace Firesphere\SolrSearch\Tasks;
5
6
use Exception;
7
use Firesphere\SolrSearch\Helpers\SolrLogger;
8
use Firesphere\SolrSearch\Indexes\BaseIndex;
9
use Firesphere\SolrSearch\Interfaces\ConfigStore;
10
use Firesphere\SolrSearch\Models\SolrLog;
11
use Firesphere\SolrSearch\Services\SolrCoreService;
12
use Firesphere\SolrSearch\Stores\FileConfigStore;
13
use Firesphere\SolrSearch\Stores\PostConfigStore;
14
use Firesphere\SolrSearch\Traits\LoggerTrait;
15
use GuzzleHttp\Exception\RequestException;
16
use ReflectionException;
17
use RuntimeException;
18
use SilverStripe\Control\HTTPRequest;
19
use SilverStripe\Core\Injector\Injector;
20
use SilverStripe\Dev\BuildTask;
21
use SilverStripe\ORM\ValidationException;
22
23
class SolrConfigureTask extends BuildTask
24
{
25
    use LoggerTrait;
26
27
    protected static $storeModes = [
28
        'file' => FileConfigStore::class,
29
        'post' => PostConfigStore::class,
30
//        'webdav' => WebdavConfigStore::class, // @todo
31
    ];
32
    private static $segment = 'SolrConfigureTask';
33
    protected $title = 'Configure Solr cores';
34
    protected $description = 'Create or reload a Solr Core by adding or reloading a configuration.';
35
36 26
    public function __construct()
37
    {
38 26
        parent::__construct();
39 26
    }
40
41
    /**
42
     * Implement this method in the task subclass to
43
     * execute via the TaskRunner
44
     *
45
     * @param HTTPRequest $request
46
     * @return bool|Exception
47
     * @throws ReflectionException
48
     * @throws ValidationException
49
     * @throws \GuzzleHttp\Exception\GuzzleException
50
     */
51 25
    public function run($request)
52
    {
53 25
        $this->extend('onBeforeSolrConfigureTask', $request);
54
55 25
        $indexes = (new SolrCoreService())->getValidIndexes();
56
57 25
        foreach ($indexes as $index) {
58
            try {
59 25
                $this->configureIndex($index);
60
            } catch (RequestException $error) {
61
                $exception = $error->getResponse()->getBody()->getContents();
62
                $solrLogger = new SolrLogger();
63
                $solrLogger->saveSolrLog('Config');
64
                $this->getLogger()->error($exception);
65
                $this->getLogger()->error(sprintf('Core loading failed for %s', $index));
66
                // Continue to the next index
67
                continue;
68
            }
69 25
            $this->extend('onAfterConfigureIndex', $index);
70
        }
71
72 25
        $this->extend('onAfterSolrConfigureTask');
73
74 25
        return true;
75
    }
76
77
    /**
78
     * Update the index on the given store
79
     *
80
     * @param string $index
81
     */
82 25
    protected function configureIndex($index): void
83
    {
84
        /** @var BaseIndex $instance */
85 25
        $instance = Injector::inst()->get($index, false);
86
87 25
        $index = $instance->getIndexName();
88
89
        // Then tell Solr to use those config files
90
        /** @var SolrCoreService $service */
91 25
        $service = Injector::inst()->get(SolrCoreService::class);
92
93
        // Assuming a core that doesn't exist doesn't have uptime, as per Solr docs
94
        // And it has a start time.
95
        // You'd have to be pretty darn fast to hit 0 uptime and 0 starttime for an existing core!
96 25
        $status = $service->coreStatus($index);
97 25
        $configStore = $this->createConfigForIndex($instance);
98
        // Default to create
99 25
        $method = 'coreCreate';
100
        // Switch to reload if the core is loaded
101 25
        if ($status && ($status->getUptime() && $status->getStartTime() !== null)) {
102 25
            $method = 'coreReload';
103
        }
104
        try {
105 25
            $service->$method($index, $configStore);
106 25
            $this->getLogger()->info(sprintf('Core %s successfully loaded', $index));
107
        } catch (\Exception $error) {
108
            $this->getLogger()->error($error);
109
            echo sprintf('Error in core %s', $index);
110
            throw new RuntimeException($error);
111
        }
112 25
    }
113
114
    /**
115
     * @param BaseIndex $instance
116
     * @return ConfigStore
117
     */
118 25
    protected function createConfigForIndex(BaseIndex $instance): ConfigStore
119
    {
120 25
        $storeConfig = SolrCoreService::config()->get('store');
121 25
        $configStore = $this->getStore($storeConfig);
122 25
        $instance->uploadConfig($configStore);
123
124 25
        return $configStore;
125
    }
126
127
    /**
128
     * @param $storeConfig
129
     * @return ConfigStore
130
     */
131 25
    protected function getStore($storeConfig): ConfigStore
132
    {
133 25
        $store = static::$storeModes[$storeConfig['mode']];
134 25
        $configStore = Injector::inst()->create($store, $storeConfig);
135
136
        // Allow changing the configStore if it needs to change to a different store
137 25
        $this->extend('onBeforeConfig', $configStore, $storeConfig);
138
139 25
        return $configStore;
140
    }
141
}
142