Completed
Push — compat-sf4 ( 2c998b...98be8a )
by Kevin
08:51
created

IndexManager::delete()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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