-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0b5dd3a
Showing
4 changed files
with
239 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
<?php | ||
/** | ||
* Redis Counter implements fast atomic counters using Redis storage. | ||
* User: aschuurman | ||
* Date: 2016-01-16 | ||
* Time: 16:30 | ||
*/ | ||
|
||
namespace drsdre\redis; | ||
|
||
use Yii; | ||
use yii\base\Exception; | ||
use yii\base\InvalidConfigException; | ||
use yii\base\Component; | ||
use yii\redis\Connection; | ||
|
||
class Counter extends Component { | ||
|
||
/** | ||
* @var Connection|string|array the Redis [[Connection]] object or the application component ID of the Redis [[Connection]]. | ||
* This can also be an array that is used to create a redis [[Connection]] instance in case you do not want do configure | ||
* redis connection as an application component. | ||
* After the Cache object is created, if you want to change this property, you should only assign it | ||
* with a Redis [[Connection]] object. | ||
*/ | ||
public $redis = 'redis'; | ||
|
||
/** | ||
* Initializes the redis Counter component. | ||
* This method will initialize the [[redis]] property to make sure it refers to a valid redis connection. | ||
* @throws InvalidConfigException if [[redis]] is invalid. | ||
*/ | ||
public function init() | ||
{ | ||
parent::init(); | ||
if (is_string($this->redis)) { | ||
$this->redis = Yii::$app->get($this->redis); | ||
} elseif (is_array($this->redis)) { | ||
if (!isset($this->redis['class'])) { | ||
$this->redis['class'] = Connection::className(); | ||
} | ||
$this->redis = Yii::createObject($this->redis); | ||
} | ||
if (!$this->redis instanceof Connection) { | ||
throw new InvalidConfigException("Counter::redis must be either a Redis connection instance or the application component ID of a Redis connection."); | ||
} | ||
} | ||
|
||
/** | ||
* Checks whether a specified key exists in the counter store. | ||
* This can be faster than getting the value from the counter store if the data is big. | ||
* @param string $key a key identifying the counter. | ||
* @return boolean true if a value exists in counter store, false if the value is not in the counter store or expired. | ||
*/ | ||
public function exists($key) | ||
{ | ||
return (bool) $this->redis->executeCommand('EXISTS', [$key]); | ||
} | ||
|
||
/** | ||
* Gets a counter identified by key | ||
* | ||
* @param string $key a key identifying the counter. | ||
* @return boolean whether the value is successfully stored | ||
*/ | ||
public function get($key) | ||
{ | ||
return $this->redis->executeCommand('GET', [$key]); | ||
} | ||
|
||
/** | ||
* Sets a counter identified by key with amount | ||
* | ||
* @param string $key a key identifying the counter. | ||
* @param integer $amount the value to incremented with | ||
* @param integer $expire the number of seconds in which the stored value will expire. 0 means never expire. | ||
* @return boolean whether the value is successfully stored | ||
* @throws Exception | ||
*/ | ||
public function set($key, $amount = 0, $expire = 0) | ||
{ | ||
if (!is_int($amount)) { | ||
throw new Exception('Counter amount can only be an integer value'); | ||
} | ||
if ($expire == 0) { | ||
return (bool) $this->redis->executeCommand('SET', [$key, $amount, 'NX']); | ||
} else { | ||
$expire = (int) ($expire * 1000); | ||
|
||
return (bool) $this->redis->executeCommand('SET', [$key, $amount, 'PX', $expire, 'NX']); | ||
} | ||
} | ||
|
||
/** | ||
* Deletes a value with the specified key from the counter store | ||
* @param string $key a key identifying counter. | ||
* @return boolean if no error happens during deletion | ||
*/ | ||
public function delete($key) | ||
{ | ||
return (bool) $this->redis->executeCommand('DEL', [$key]); | ||
} | ||
|
||
/** | ||
* Increment a counter identified by key with optional amount | ||
* | ||
* @param string $key a key identifying the counter. | ||
* @param integer $amount the value to increment with | ||
* @return boolean whether the counter is successfully stored | ||
* @throws Exception | ||
*/ | ||
public function incr($key, $amount = 1) | ||
{ | ||
if (!is_int($amount)) { | ||
throw new Exception('Counter amount can only be an integer value'); | ||
} | ||
return (bool) $this->redis->executeCommand('INCRBY', [$key, $amount]); | ||
} | ||
|
||
/** | ||
* Decrement a counter identified by key with optional amount | ||
* | ||
* @param string $key a key identifying the counter. | ||
* @param integer $amount the value to decrement with | ||
* @return boolean whether the counter is successfully stored | ||
* @throws Exception | ||
*/ | ||
public function decr($key, $amount = 1) | ||
{ | ||
if (!is_int($amount)) { | ||
throw new Exception('Counter amount can only be an integer value'); | ||
} | ||
return (bool) $this->redis->executeCommand('DECRBY', [$key, $amount]); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2015 AFS | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
Yii2 Redis Counter | ||
================== | ||
Redis Counter implements fast atomic counters using Redis storage. | ||
|
||
|
||
Installation | ||
------------ | ||
|
||
The preferred way to install this extension is through [composer](http://getcomposer.org/download/). | ||
|
||
Either run | ||
|
||
``` | ||
php composer.phar require --prefer-dist drsdre/yii2-redis-counter "*" | ||
``` | ||
|
||
or add | ||
|
||
``` | ||
"drsdre/yii2-redis-counter": "*" | ||
``` | ||
|
||
to the require section of your `composer.json` file. | ||
|
||
|
||
Usage | ||
----- | ||
|
||
You need to setup the client as application component: | ||
|
||
```php | ||
'components' => [ | ||
'redisCounter' => [ | ||
'class' => 'drsdre\redis\Counter', | ||
], | ||
... | ||
] | ||
``` | ||
|
||
Optional the parameter 'redis' can be added to specify a specific Redis connection. | ||
|
||
Usage | ||
----- | ||
|
||
Once the extension is installed, use it in your code like : | ||
|
||
```php | ||
// Create a hourly counter | ||
$counter_key = 'hourly_statistics'; | ||
|
||
// Check if counter is setup | ||
if (Yii::$app->redisCounter->exists($counter_key)) { | ||
// Atomic increment counter with 1 | ||
Yii::$app->redisCounter->incr($counter_key); | ||
} else { | ||
// Create counter set value to 1 and let it exist for 1 hour | ||
Yii::$app->redisCounter->set($counter_key, 1, 60*60); | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"name": "drsdre/yii2-redis-counter", | ||
"description": "Redis Counter implements fast atomic counters using Redis storage.", | ||
"type": "yii2-extension", | ||
"keywords": ["yii2","extension","redis","counter","atomic"], | ||
"license": "MIT", | ||
"authors": [ | ||
{ | ||
"name": "A.F.Schuurman", | ||
"email": "[email protected]" | ||
} | ||
], | ||
"require": { | ||
"yiisoft/yii2": "*", | ||
"yiisoft/yii2-bootstrap": "*", | ||
"yiisoft/yii2-redis": "~2.0.0" | ||
}, | ||
"autoload": { | ||
"psr-4": { | ||
"drsdre\\redis": "" | ||
} | ||
} | ||
} |