Completed
Pull Request — master (#13)
by X
12:07
created

Couchbase::supportRateStrategy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 1
c 1
b 0
f 1
nc 1
nop 0
dl 0
loc 3
ccs 1
cts 1
cp 1
crap 1
rs 10
1
<?php
2
/**
3
 * Couchbase Adapter for ackintosh/ganesha
4
 */
5
namespace GaneshaPlugin\Adapter;
6
7
use RuntimeException;
8
9
use Ackintosh\Ganesha;
10
use Ackintosh\Ganesha\Exception\StorageException;
11
use Ackintosh\Ganesha\Configuration;
12
use Ackintosh\Ganesha\Storage\AdapterInterface;
13
use Ackintosh\Ganesha\Storage\Adapter\TumblingTimeWindowInterface;
14
use Couchbase\Bucket;
15
use Couchbase\Exception as CBException;
16
17
/**
18
 * Adapter class using Couchbase
19
 */
20
class Couchbase implements AdapterInterface, TumblingTimeWindowInterface
21
{
22
    /**
23
     * @var \Couchbase\Bucket $bucket Couchbase bucket to manage data
24
     */
25
    private $bucket;
26
27
    /**
28
     * @var \Ackintosh\Ganesha\Configuration $configuration circuit breaker configuration
29
     */
30
    private $configuration;
31
32
    /**
33
     * constructor
34
     *
35 1
     * @param \Couchbase\Bucket $bucket Couchbase bucket to manage data
36
     */
37 1
    public function __construct(Bucket $bucket)
38
    {
39
        $this->bucket = $bucket;
40
    }
41
42
    /**
43
     * return wwhether the adapter supports counting strategy
44
     *
45
     * @rrturn bool
46 1
     */
47
    public function supportCountStrategy()
48 1
    {
49
        return true;
50
    }
51
52
    /**
53
     * return whether the adapter supports rating strategy
54
     *
55
     * @return bool
56
     */
57
    public function supportRateStrategy()
58 3
    {
59
        return true;
60 3
    }
61
62
    /**
63
     * set circuit breaker configuration
64
     *
65
     * @param \Ackintosh\Ganesha\Configuration $configuration circuit breaker configuration
66
     * @return void
67
     */
68
    public function setConfiguration(Configuration $configuration)
69
    {
70
        $this->configuration = $configuration;
71 2
    }
72
73 2
    /**
74
     * load success / failure / rejection count
75
     *
76
     * @param  string $service name of the service
77
     * @return int
78
     * @throws \Ackintosh\Ganesha\Exception\StorageException
79
     */
80
    public function load($service)
81
    {
82
        return $this->get($service, 0);
83 2
    }
84
85 2
    /**
86
     * save success / failure / rejection count
87
     *
88
     * @param  string $service name of the service
89
     * @param  int    $count   success / failure / rejection count of the service
90
     * @return void
91
     * @throws \Ackintosh\Ganesha\Exception\StorageException
92
     */
93
    public function save($service, $count)
94
    {
95
        $this->upsert($service, $count);
96
    }
97 2
98
    /**
99 2
     * increment success / failure / rejection count
100
     *
101
     * @param  string $service name of the service
102
     * @return void
103
     * @throws \Ackintosh\Ganesha\Exception\StorageException
104
     */
105
    public function increment($service)
106
    {
107
        $this->counter($service, 1);
108
    }
109
110 2
    /**
111
     * decrement failure count
112 2
     *
113
     * If the operation would decrease the value below 0, the new value must be 0.
114
     *
115
     * @param  string $service name of the service
116
     * @return void
117
     * @throws \Ackintosh\Ganesha\Exception\StorageException
118
     */
119
    public function decrement($service)
120
    {
121
        $this->counter($service, -1);
122 3
    }
123
124 3
    /**
125
     * sets last failure time
126
     *
127
     * @param  string $service         name of the service
128
     * @param  int    $lastFailureTime last failure time (unix time)
129
     * @return void
130
     * @throws \Ackintosh\Ganesha\Exception\StorageException
131
     */
132
    public function saveLastFailureTime($service, $lastFailureTime)
133
    {
134
        $this->upsert($service, $lastFailureTime);
135 2
    }
136
137 2
    /**
138
     * returns last failure time
139
     *
140
     * @param string $service name of the service
141
     * @return int | null
142
     * @throws \Ackintosh\Ganesha\Exception\StorageException
143
     */
144
    public function loadLastFailureTime($service)
145
    {
146
        return $this->get($service, null);
147 3
    }
148
149 3
    /**
150
     * sets status
151
     *
152
     * @param  string $service name of the service
153
     * @param  int    $status  status of the service
154
     * @return void
155
     * @throws \Ackintosh\Ganesha\Exception\StorageException
156
     */
157
    public function saveStatus($service, $status)
158 1
    {
159
        $this->upsert($service, $status);
160 1
    }
161
162
    /**
163
     * returns status
164
     *
165
     * @param  string $service name of the service
166
     * @return int
167
     * @throws \Ackintosh\Ganesha\Exception\StorageException
168
     */
169 10
    public function loadStatus($service)
170
    {
171 10
        return $this->get($service, Ganesha::STATUS_CALMED_DOWN);
172 10
    }
173 10
174
    /**
175 10
     * resets all counts
176
     *
177 10
     * @return void
178
     * @throws \Ackintosh\Ganesha\Exception\StorageException
179
     */
180
    public function reset()
181
    {
182
        throw new RuntimeException('not implemented');
183
    }
184
185
    /**
186
     * return option parameters for Couchbase operation
187
     *
188 11
     * @param array $additional additional option
189
     * @return array
190
     */
191 11
    private function getOptions(array $additional = [])
192 6
    {
193 6
        $expiry = isset($this->configuration['timeWindow']) ?
194 3
                $this->configuration['timeWindow'] * 2 : // current + previous
195
                0;
196 3
        $initial = [
197
            'expiry' => $expiry,
198 5
        ];
199
        return array_merge($initial, $additional);
200
    }
201
202
    /**
203
     * get data from couchbase bucket
204
     *
205
     * @param string $key     key of the document
206
     * @param mixed  $default default value for missing document
207
     * @return mixed
208
     * @throws \Ackintosh\Ganesha\Exception\StorageException
209 7
     */
210
    private function get($key, $default)
211
    {
212 7
        try {
213 3
            $doc = $this->bucket->get($key, []);
214 3
        } catch (CBException $e) {
215
            if ($e->getCode() === COUCHBASE_KEY_ENOENT) {
216
                return $default;
217
            }
218
            throw new StorageException($e->getMessage(), $e->getCode(), $e);
219
        }
220
        return $doc->value;
221
    }
222
223
    /**
224
     * update or insert value for given key
225
     *
226 4
     * @param string $key   id of the document
227
     * @param mixed  $value value of the document
228
     * @return void
229 4
     * @throws \Ackintosh\Ganesha\Exception\StorageException
230 2
     */
231 2
    private function upsert($key, $value)
232
    {
233
        try {
234
            $this->bucket->upsert($key, $value, $this->getOptions());
235
        } catch (CBException $e) {
236
            throw new StorageException($e->getMessage(), $e->getCode(), $e);
237
        }
238
    }
239
240
    /**
241
     * increment / decrement counter for given key
242
     *
243
     * @param string $key   key of the counter
244
     * @param int    $delta increment / decrement delta
245
     * @return void
246
     * @throws \Ackintosh\Ganesha\Exception\StorageException
247
     */
248
    private function counter($key, $delta)
249
    {
250
        try {
251
            $this->bucket->counter($key, $delta, $this->getOptions(['initial' => 0]));
252
        } catch (\Couchbase\Exception $e) {
253
            throw new StorageException($e->getMessage(), $e->getCode(), $e);
254
        }
255
    }
256
}
257