IndexManager::getCurrentIndex()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 10
ccs 6
cts 6
cp 1
rs 9.4286
cc 3
eloc 5
nc 3
nop 0
crap 3
1
<?php
2
3
namespace Zenstruck\ElasticaBundle\Elastica;
4
5
use Elastica\Document;
6
use Elastica\Index;
7
use Elastica\Type;
8
use Psr\Log\LoggerInterface;
9
use Zenstruck\ElasticaBundle\Exception\RuntimeException;
10
11
/**
12
 * @author Kevin Bond <[email protected]>
13
 */
14
class IndexManager
15
{
16
    const DEFAULT_CHUNK_SIZE = 500;
17
18
    private $indexContext;
19
    private $logger;
20
21 6
    public function __construct(IndexContext $indexContext, LoggerInterface $logger = null)
22
    {
23 6
        $this->indexContext = $indexContext;
24 6
        $this->logger = $logger;
25 6
    }
26
27
    /**
28
     * Creates and indexes the elasticsearch index.
29
     *
30
     * @throws RuntimeException
31
     */
32 4
    public function create()
33
    {
34 4
        $indicies = $this->indexContext->getIndicies();
35
36 4
        foreach ($indicies as $index) {
37 4
            if ($index->exists()) {
38 1
                throw RuntimeException::indexExists($index);
39
            }
40 4
        }
41
42
        /** @var Index $index */
43 4
        $index = reset($indicies);
44
45 4
        $this->logInfo(sprintf('Creating index "%s".', $index->getName()));
46 4
        $this->doCreate($index);
47
48 4
        $aliasName = $this->indexContext->getAlias()->getName();
49 4
        $this->logInfo(sprintf('Adding alias "%s" for index "%s".', $aliasName, $index->getName()));
50 4
        $index->addAlias($aliasName);
51 4
    }
52
53
    /**
54
     * Reindex the elasticsearch index.
55
     *
56
     * @throws RuntimeException
57
     */
58 3
    public function reindex()
59
    {
60 3
        $oldIndex = $this->getCurrentIndex();
61 2
        $newIndex = $this->getFreshIndex();
62
63 1
        $this->logInfo(sprintf('Creating new index "%s".', $newIndex->getName()));
64 1
        $this->doCreate($newIndex);
65
66 1
        $aliasName = $this->indexContext->getAlias()->getName();
67 1
        $this->logInfo(sprintf('Swapping alias "%s" from index "%s" to index "%s".', $aliasName, $oldIndex->getName(), $newIndex->getName()));
68 1
        $newIndex->addAlias($aliasName);
69
70 1
        $this->logInfo(sprintf('Deleting old index "%s".', $oldIndex->getName()));
71 1
        $oldIndex->delete();
72 1
    }
73
74
    /**
75
     * Deletes the elasticsearch index.
76
     *
77
     * @throws RuntimeException
78
     */
79 1
    public function delete()
80
    {
81 1
        foreach ($this->indexContext->getIndicies() as $index) {
82 1
            $this->doDelete($index);
83 1
        }
84 1
    }
85
86 1
    private function doDelete(Index $index)
87
    {
88 1
        if ($index->exists()) {
89 1
            $this->logInfo(sprintf('Deleting index "%s".', $index->getName()));
90 1
            $index->delete();
91 1
        }
92 1
    }
93
94
    /**
95
     * @param string $message
96
     * @param array  $context
97
     */
98 4
    private function logInfo($message, array $context = array())
99
    {
100 4
        if (null === $this->logger) {
101 2
            return;
102
        }
103
104 3
        $this->logger->info($message, $context);
105 3
    }
106
107 4
    private function doCreate(Index $index)
108
    {
109 4
        $args = array();
110
111 4
        if (null !== $settings = $this->indexContext->getSettings()) {
112 4
            $args['settings'] = $settings;
113 4
        }
114
115 4
        $index->create($args);
116
117 4
        foreach ($this->indexContext->getTypeContexts() as $typeContext) {
118 4
            $type = new Type($index, $typeContext->getType()->getName());
119
120 4
            $this->logInfo(sprintf('Adding mapping for type "%s" on index "%s".', $type->getName(), $index->getName()));
121 4
            $type->setMapping($typeContext->getMapping());
122 4
            $this->addDocumentsToType($type, $typeContext->getDocuments());
123 4
        }
124 4
    }
125
126
    /**
127
     * @param Type       $type
128
     * @param Document[] $documents
129
     */
130 4
    private function addDocumentsToType(Type $type, array $documents)
131
    {
132 4
        $total = count($documents);
133 4
        $typeName = $type->getName();
134 4
        $indexName = $type->getIndex()->getName();
135 4
        $count = 0;
136
137 4
        $this->logInfo(sprintf('Adding %d documents to type "%s" on index "%s".', $total, $typeName, $indexName));
138
139 4
        foreach (array_chunk($documents, self::DEFAULT_CHUNK_SIZE) as $chunks) {
140 4
            $type->addDocuments($chunks);
141
142 4
            $count += count($chunks);
143 4
            $this->logInfo(sprintf('%s/%s documents added to type "%s" on index "%s".',
144 4
                $count,
145 4
                $total,
146 4
                $typeName,
147
                $indexName
148 4
            ));
149 4
        }
150 4
    }
151
152
    /**
153
     * @return Index
154
     */
155 2
    private function getFreshIndex()
156
    {
157 2
        foreach ($this->indexContext->getIndicies() as $index) {
158 2
            if (!$index->exists()) {
159 1
                return $index;
160
            }
161 2
        }
162
163 1
        throw new RuntimeException('No unused index in rotation. Run delete and create first.');
164
    }
165
166
    /**
167
     * @return Index
168
     */
169 3
    private function getCurrentIndex()
170
    {
171 3
        foreach ($this->indexContext->getIndicies() as $index) {
172 3
            if ($index->exists()) {
173 2
                return $index;
174
            }
175 1
        }
176
177 1
        throw new RuntimeException('No active index in rotation. Run create first.');
178
    }
179
}
180