Passed
Push — hans/logtests ( 76c086...71695d )
by Simon
06:24 queued 02:27
created

SolrConfigureTask::logException()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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