Completed
Push — master ( 6f372c...9253a3 )
by Sebastian
06:48
created

Redis   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 192
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Test Coverage

Coverage 96.43%

Importance

Changes 2
Bugs 1 Features 1
Metric Value
wmc 14
c 2
b 1
f 1
lcom 1
cbo 10
dl 0
loc 192
ccs 54
cts 56
cp 0.9643
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A setup() 0 14 2
A backup() 0 21 2
A getExecutable() 0 12 2
A getRedisLastSave() 0 6 1
A getLastBackupTime() 0 10 2
A isDumpCreatedYet() 0 12 3
A copyDumpToTargetDir() 0 9 2
1
<?php
2
namespace phpbu\App\Backup\Source;
3
4
use phpbu\App\Backup\Cli;
5
use phpbu\App\Backup\Source;
6
use phpbu\App\Backup\Target;
7
use phpbu\App\Cli\Executable;
8
use phpbu\App\Exception;
9
use phpbu\App\Result;
10
use phpbu\App\Util;
11
12
/**
13
 * Tar source class.
14
 *
15
 * @package    phpbu
16
 * @subpackage Backup
17
 * @author     Sebastian Feldmann <[email protected]>
18
 * @copyright  Sebastian Feldmann <[email protected]>
19
 * @license    https://opensource.org/licenses/MIT The MIT License (MIT)
20
 * @link       http://phpbu.de/
21
 * @since      Class available since Release 2.1.12
22
 */
23
class Redis extends Cli implements Source
24
{
25
    /**
26
     * Path to executable.
27
     *
28
     * @var string
29
     */
30
    private $pathToRedisCli;
31
32
    /**
33
     * Show stdErr
34
     *
35
     * @var boolean
36
     */
37
    private $showStdErr;
38
39
    /**
40
     * Time to wait for the dump to finish
41
     *
42
     * @var integer
43
     */
44
    private $timeout;
45
46
    /**
47
     * Host to backup
48
     *
49
     * @var string
50
     */
51
    private $host;
52
53
    /**
54
     * Port to connect to
55
     *
56
     * @var int
57
     */
58
    private $port;
59
60
    /**
61
     * Password for authentication
62
     *
63
     * @var string
64
     */
65
    private $password;
66
67
    /**
68
     * Path to the redis rdb directory, for Debian it's /var/lib/redis/{PORT}/dump.rdb
69
     *
70
     * @var string
71
     */
72
    private $pathToRedisData;
73
74
    /**
75
     * Setup.
76
     *
77
     * @see    \phpbu\App\Backup\Source
78
     * @param  array $conf
79
     * @throws \phpbu\App\Exception
80
     */
81
    public function setup(array $conf = array())
82
    {
83
        $this->pathToRedisCli  = Util\Arr::getValue($conf, 'pathToRedisCli');
84
        $this->showStdErr      = Util\Str::toBoolean(Util\Arr::getValue($conf, 'showStdErr', ''), false);
85
        $this->pathToRedisData = Util\Arr::getValue($conf, 'pathToRedisData');
86
        $this->timeout         = Util\Arr::getValue($conf, 'timeout', 45);
87
        $this->host            = Util\Arr::getValue($conf, 'host');
88 5
        $this->port            = Util\Arr::getValue($conf, 'port');
89
        $this->password        = Util\Arr::getValue($conf, 'password');
90 5
91 5
        if (empty($this->pathToRedisData)) {
92 5
            throw new Exception('pathToRedisData option is mandatory');
93 5
        }
94 5
    }
95 5
96 5
    /**
97
     * Execute the backup.
98 5
     *
99 1
     * @see    \phpbu\App\Backup\Source
100
     * @param  \phpbu\App\Backup\Target $target
101 4
     * @param  \phpbu\App\Result        $result
102
     * @return \phpbu\App\Backup\Source\Status
103
     * @throws \phpbu\App\Exception
104
     */
105
    public function backup(Target $target, Result $result)
106
    {
107
        // set uncompressed default MIME type
108
        $target->setMimeType('application/octet-stream');
109
110
        $redisSave = $this->getExecutable($target);
111
        $redisLast = $this->getRedisLastSave($redisSave);
0 ignored issues
show
Documentation introduced by
$redisSave is of type object<phpbu\App\Cli\Executable>, but the function expects a object<phpbu\App\Backup\Source\RedisCli>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
112 3
113
        $lastBackupTimestamp = $this->getLastBackupTime($redisLast);
114
115 3
        $saveResult = $redisSave->run();
116
        $result->debug($saveResult->getCmd());
117 3
        if (!$saveResult->wasSuccessful()) {
118 3
            throw new Exception('redis-cli BGSAVE failed');
119 3
        }
120
        $this->isDumpCreatedYet($lastBackupTimestamp, $redisLast);
121 3
122
        $pathToDump = $this->copyDumpToTargetDir($target);
123 3
124 3
        return Status::create()->uncompressed()->dataPath($pathToDump);
125 3
    }
126 1
127
    /**
128 2
     * Setup the Executable to run the 'tar' command.
129
     *
130 1
     * @param  \phpbu\App\Backup\Target
131
     * @return \phpbu\App\Cli\Executable
132 1
     */
133
    public function getExecutable(Target $target)
134
    {
135
        if (null == $this->executable) {
136
            $this->executable = new Executable\RedisCli($this->pathToRedisCli);
137
            $this->executable->backup()
138
                             ->useHost($this->host)
139
                             ->usePort($this->port)
140
                             ->usePassword($this->password)
141 4
                             ->showStdErr($this->showStdErr);
142
        }
143 4
        return $this->executable;
144 1
    }
145 1
146 1
    /**
147 1
     * Creates a RedisLastSave command from a RedisSave command.
148 1
     *
149 1
     * @param  \phpbu\App\Backup\Source\RedisCli $redis
150 1
     * @return \phpbu\App\Backup\Source\RedisCli
151 4
     */
152
    public function getRedisLastSave(RedisCli $redis)
153
    {
154
        $redisLast = clone($redis);
155
        $redisLast->lastBackupTime();
156
        return $redisLast;
157
    }
158
159
    /**
160
     * Return last successful save timestamp.
161 3
     *
162
     * @param  \phpbu\App\Cli\Executable\RedisCli $redis
163 3
     * @return int
164 3
     * @throws \phpbu\App\Exception
165 3
     */
166 3
    private function getLastBackupTime(Executable\RedisCli $redis)
167
    {
168
        $result  = $redis->run();
169 3
        $output  = $result->getOutputAsString();
170
        $matches = [];
171
        if (!preg_match('#\(integer\) ([0-9]+)#i', $output, $matches)) {
172
            throw new Exception('invalid redis-cli LASTSAVE output');
173
        }
174
        return $matches[1];
175
    }
176
177
    /**
178
     * Check the dump date and return true if BGSAVE is finished.
179
     *
180 2
     * @param  int $lastTimestamp
181
     * @param  \phpbu\App\Cli\Executable\RedisCli $redis
182 2
     * @return bool
183 2
     * @throws \phpbu\App\Exception
184 1
     */
185 1
    private function isDumpCreatedYet($lastTimestamp, $redis)
186
    {
187 1
        $i = 0;
188 1
        while ($this->getLastBackupTime($redis) <= $lastTimestamp) {
189 1
            if ($i > $this->timeout) {
190 1
                throw new Exception('redis-cli BGSAVE is taking to long, increase timeout');
191
            }
192
            $i++;
193
            sleep(1);
194
        }
195
        return true;
196
    }
197
198
    /**
199
     * Copy the redis RDB file to its backup location.
200 1
     *
201
     * @param  \phpbu\App\Backup\Target $target
202 1
     * @return string
203
     * @throws \phpbu\App\Exception
204
     */
205 1
    private function copyDumpToTargetDir(Target $target)
206 1
    {
207 1
        if (!file_exists($this->pathToRedisData)) {
208
            throw new Exception('Redis data not found at: \'' . $this->pathToRedisCli . '\'');
209
        }
210
        $targetFile = $target->getPathnamePlain();
211
        copy($this->pathToRedisData, $targetFile);
212
        return $targetFile;
213
    }
214
}
215