Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yii2
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PSDI Army
yii2
Commits
0d2f5028
Commit
0d2f5028
authored
Mar 29, 2013
by
Carsten Brandt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Finished Redis Connection class
parent
8e74add1
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
126 additions
and
104 deletions
+126
-104
Connection.php
framework/db/redis/Connection.php
+62
-79
config.php
tests/unit/data/config.php
+5
-0
ConnectionTest.php
tests/unit/framework/db/redis/ConnectionTest.php
+37
-11
RedisTestCase.php
tests/unit/framework/db/redis/RedisTestCase.php
+22
-14
No files found.
framework/db/redis/Connection.php
View file @
0d2f5028
...
@@ -10,14 +10,17 @@
...
@@ -10,14 +10,17 @@
namespace
yii\db\redis
;
namespace
yii\db\redis
;
use
\yii\base\Component
;
use
\yii\base\Component
;
use
yii\base\NotSupportedException
;
use
yii\base\InvalidConfigException
;
use
yii\base\InvalidConfigException
;
use
\yii\db\Exception
;
use
\yii\db\Exception
;
use
yii\util\StringHelper
;
/**
/**
*
*
*
*
*
*
* @method mixed set($key, $value) Set the string value of a key
* @method mixed get($key) Set the string value of a key
* TODO document methods
*
*
* @since 2.0
* @since 2.0
*/
*/
...
@@ -30,34 +33,18 @@ class Connection extends Component
...
@@ -30,34 +33,18 @@ class Connection extends Component
/**
/**
* @var string the Data Source Name, or DSN, contains the information required to connect to the database.
* @var string the Data Source Name, or DSN, contains the information required to connect to the database.
* DSN format: redis://[auth@][server][:port][/db]
* DSN format: redis://server:port[/db]
* @see charset
* Where db is a zero based integer which refers to the DB to use.
* If no DB is given, ID 0 is used.
*
* Example: redis://localhost:6379/2
*/
*/
public
$dsn
;
public
$dsn
;
/**
/**
* @var string the username for establishing DB connection. Defaults to empty string.
* @var string the password for establishing DB connection. Defaults to null meaning no AUTH command is send.
*/
* See http://redis.io/commands/auth
public
$username
=
''
;
/**
* @var string the password for establishing DB connection. Defaults to empty string.
*/
public
$password
=
''
;
/**
* @var boolean whether to enable profiling for the SQL statements being executed.
* Defaults to false. This should be mainly enabled and used during development
* to find out the bottleneck of SQL executions.
* @see getStats
*/
*/
public
$enableProfiling
=
false
;
public
$password
;
/**
* @var string the common prefix or suffix for table names. If a table name is given
* as `{{%TableName}}`, then the percentage character `%` will be replaced with this
* property value. For example, `{{%post}}` becomes `{{tbl_post}}` if this property is
* set as `"tbl_"`. Note that this property is only effective when [[enableAutoQuoting]]
* is true.
* @see enableAutoQuoting
*/
public
$keyPrefix
;
/**
/**
* @var array List of available redis commands http://redis.io/commands
* @var array List of available redis commands http://redis.io/commands
...
@@ -242,20 +229,25 @@ class Connection extends Component
...
@@ -242,20 +229,25 @@ class Connection extends Component
if
(
empty
(
$this
->
dsn
))
{
if
(
empty
(
$this
->
dsn
))
{
throw
new
InvalidConfigException
(
'Connection.dsn cannot be empty.'
);
throw
new
InvalidConfigException
(
'Connection.dsn cannot be empty.'
);
}
}
// TODO parse DSN
$dsn
=
explode
(
'/'
,
$this
->
dsn
);
$host
=
'localhost'
;
$host
=
$dsn
[
2
];
$port
=
6379
;
if
(
strpos
(
$host
,
':'
)
===
false
)
{
try
{
$host
.=
':6379'
;
\Yii
::
trace
(
'Opening DB connection: '
.
$this
->
dsn
,
__CLASS__
);
$this
->
_socket
=
stream_socket_client
(
$host
.
':'
.
$port
);
// TODO auth
// TODO select database
$this
->
initConnection
();
}
}
catch
(
\PDOException
$e
)
{
$db
=
isset
(
$dsn
[
3
])
?
$dsn
[
3
]
:
0
;
\Yii
::
error
(
"Failed to open DB connection (
{
$this
->
dsn
}
): "
.
$e
->
getMessage
(),
__CLASS__
);
$message
=
YII_DEBUG
?
'Failed to open DB connection: '
.
$e
->
getMessage
()
:
'Failed to open DB connection.'
;
\Yii
::
trace
(
'Opening DB connection: '
.
$this
->
dsn
,
__CLASS__
);
throw
new
Exception
(
$message
,
(
int
)
$e
->
getCode
(),
$e
->
errorInfo
);
$this
->
_socket
=
@
stream_socket_client
(
$host
,
$errorNumber
,
$errorDescription
);
if
(
$this
->
_socket
)
{
if
(
$this
->
password
!==
null
)
{
$this
->
executeCommand
(
'AUTH'
,
array
(
$this
->
password
));
}
$this
->
executeCommand
(
'SELECT'
,
array
(
$db
));
$this
->
initConnection
();
}
else
{
\Yii
::
error
(
"Failed to open DB connection (
{
$this
->
dsn
}
): "
.
$errorNumber
.
' - '
.
$errorDescription
,
__CLASS__
);
$message
=
YII_DEBUG
?
'Failed to open DB connection: '
.
$errorNumber
.
' - '
.
$errorDescription
:
'Failed to open DB connection.'
;
throw
new
Exception
(
$message
,
(
int
)
$errorNumber
,
$errorDescription
);
}
}
}
}
}
}
...
@@ -268,7 +260,7 @@ class Connection extends Component
...
@@ -268,7 +260,7 @@ class Connection extends Component
{
{
if
(
$this
->
_socket
!==
null
)
{
if
(
$this
->
_socket
!==
null
)
{
\Yii
::
trace
(
'Closing DB connection: '
.
$this
->
dsn
,
__CLASS__
);
\Yii
::
trace
(
'Closing DB connection: '
.
$this
->
dsn
,
__CLASS__
);
$this
->
__call
(
'CLOSE'
,
array
());
// TODO improve API
$this
->
executeCommand
(
'QUIT'
);
stream_socket_shutdown
(
$this
->
_socket
,
STREAM_SHUT_RDWR
);
stream_socket_shutdown
(
$this
->
_socket
,
STREAM_SHUT_RDWR
);
$this
->
_socket
=
null
;
$this
->
_socket
=
null
;
$this
->
_transaction
=
null
;
$this
->
_transaction
=
null
;
...
@@ -278,9 +270,7 @@ class Connection extends Component
...
@@ -278,9 +270,7 @@ class Connection extends Component
/**
/**
* Initializes the DB connection.
* Initializes the DB connection.
* This method is invoked right after the DB connection is established.
* This method is invoked right after the DB connection is established.
* The default implementation turns on `PDO::ATTR_EMULATE_PREPARES`
* The default implementation triggers an [[EVENT_AFTER_OPEN]] event.
* if [[emulatePrepare]] is true, and sets the database [[charset]] if it is not empty.
* It then triggers an [[EVENT_AFTER_OPEN]] event.
*/
*/
protected
function
initConnection
()
protected
function
initConnection
()
{
{
...
@@ -324,8 +314,6 @@ class Connection extends Component
...
@@ -324,8 +314,6 @@ class Connection extends Component
}
}
/**
/**
* http://redis.io/topics/protocol
* https://github.com/ptrofimov/tinyredisclient/blob/master/src/TinyRedisClient.php
*
*
* @param string $name
* @param string $name
* @param array $params
* @param array $params
...
@@ -333,23 +321,39 @@ class Connection extends Component
...
@@ -333,23 +321,39 @@ class Connection extends Component
*/
*/
public
function
__call
(
$name
,
$params
)
public
function
__call
(
$name
,
$params
)
{
{
// TODO set active to true?
$redisCommand
=
strtoupper
(
StringHelper
::
camel2words
(
$name
,
false
));
if
(
in_array
(
$name
,
$this
->
redisCommands
))
if
(
in_array
(
$redisCommand
,
$this
->
redisCommands
))
{
{
return
$this
->
executeCommand
(
$name
,
$params
);
array_unshift
(
$params
,
$name
);
}
else
{
$command
=
'*'
.
count
(
$params
)
.
"
\r\n
"
;
foreach
(
$params
as
$arg
)
{
$command
.=
'$'
.
strlen
(
$arg
)
.
"
\r\n
"
.
$arg
.
"
\r\n
"
;
}
\Yii
::
trace
(
"Executing Redis Command:
{
$command
}
"
,
__CLASS__
);
fwrite
(
$this
->
_socket
,
$command
);
return
$this
->
parseResponse
(
$command
);
}
else
{
return
parent
::
__call
(
$name
,
$params
);
return
parent
::
__call
(
$name
,
$params
);
}
}
}
}
/**
* Execute a redis command
* http://redis.io/commands
* http://redis.io/topics/protocol
*
* @param $name
* @param $params
* @return array|bool|null|string
*/
public
function
executeCommand
(
$name
,
$params
=
array
())
{
$this
->
open
();
array_unshift
(
$params
,
$name
);
$command
=
'*'
.
count
(
$params
)
.
"
\r\n
"
;
foreach
(
$params
as
$arg
)
{
$command
.=
'$'
.
strlen
(
$arg
)
.
"
\r\n
"
.
$arg
.
"
\r\n
"
;
}
\Yii
::
trace
(
"Executing Redis Command:
{
$name
}
"
,
__CLASS__
);
fwrite
(
$this
->
_socket
,
$command
);
return
$this
->
parseResponse
(
implode
(
' '
,
$params
));
}
private
function
parseResponse
(
$command
)
private
function
parseResponse
(
$command
)
{
{
if
((
$line
=
fgets
(
$this
->
_socket
))
===
false
)
{
if
((
$line
=
fgets
(
$this
->
_socket
))
===
false
)
{
...
@@ -383,28 +387,7 @@ class Connection extends Component
...
@@ -383,28 +387,7 @@ class Connection extends Component
}
}
return
$data
;
return
$data
;
default
:
default
:
throw
new
Exception
(
'Received illegal data from redis: '
.
substr
(
$line
,
0
,
-
2
)
.
"
\n
Redis command was: "
.
$command
);
throw
new
Exception
(
'Received illegal data from redis: '
.
$line
.
"
\n
Redis command was: "
.
$command
);
}
}
/**
* Returns the statistical results of SQL queries.
* The results returned include the number of SQL statements executed and
* the total time spent.
* In order to use this method, [[enableProfiling]] has to be set true.
* @return array the first element indicates the number of SQL statements executed,
* and the second element the total time spent in SQL execution.
* @see \yii\logging\Logger::getProfiling()
*/
public
function
getQuerySummary
()
{
$logger
=
\Yii
::
getLogger
();
$timings
=
$logger
->
getProfiling
(
array
(
'yii\db\redis\Connection::command'
));
$count
=
count
(
$timings
);
$time
=
0
;
foreach
(
$timings
as
$timing
)
{
$time
+=
$timing
[
1
];
}
}
return
array
(
$count
,
$time
);
}
}
}
}
tests/unit/data/config.php
View file @
0d2f5028
...
@@ -7,4 +7,9 @@ return array(
...
@@ -7,4 +7,9 @@ return array(
'password'
=>
''
,
'password'
=>
''
,
'fixture'
=>
__DIR__
.
'/mysql.sql'
,
'fixture'
=>
__DIR__
.
'/mysql.sql'
,
),
),
'redis'
=>
array
(
'dsn'
=>
'redis://localhost:6379/0'
,
'password'
=>
null
,
// 'fixture' => __DIR__ . '/mysql.sql',
),
);
);
tests/unit/framework/db/redis/ConnectionTest.php
View file @
0d2f5028
...
@@ -4,19 +4,44 @@ namespace yiiunit\framework\db\redis;
...
@@ -4,19 +4,44 @@ namespace yiiunit\framework\db\redis;
use
yii\db\redis\Connection
;
use
yii\db\redis\Connection
;
/**
*
*
* @author Carsten Brandt <mail@cebe.cc>
*/
class
ConnectionTest
extends
RedisTestCase
class
ConnectionTest
extends
RedisTestCase
{
{
public
function
testConstruct
()
/**
* Empty DSN should throw exception
* @expectedException \yii\base\InvalidConfigException
*/
public
function
testEmptyDSN
()
{
$db
=
new
Connection
();
$db
->
open
();
}
/**
* test connection to redis and selection of db
*/
public
function
testConnect
()
{
{
$db
=
new
Connection
();
$db
=
new
Connection
();
$db
->
dsn
=
'redis://localhost:6379'
;
$db
->
open
();
$this
->
assertTrue
(
$db
->
ping
());
$db
->
set
(
'YIITESTKEY'
,
'YIITESTVALUE'
);
$db
->
close
();
$db
=
new
Connection
();
$db
->
dsn
=
'redis://localhost:6379/0'
;
$db
->
open
();
$this
->
assertEquals
(
'YIITESTVALUE'
,
$db
->
get
(
'YIITESTKEY'
));
$db
->
close
();
$db
=
new
Connection
();
$db
->
dsn
=
'redis://localhost:6379/1'
;
$db
->
open
();
$this
->
assertNull
(
$db
->
get
(
'YIITESTKEY'
));
$db
->
close
();
}
}
public
function
storeGet
Data
()
public
function
keyValue
Data
()
{
{
return
array
(
return
array
(
array
(
123
),
array
(
123
),
...
@@ -24,18 +49,18 @@ class ConnectionTest extends RedisTestCase
...
@@ -24,18 +49,18 @@ class ConnectionTest extends RedisTestCase
array
(
0
),
array
(
0
),
array
(
'test'
),
array
(
'test'
),
array
(
"test
\r\n
test"
),
array
(
"test
\r\n
test"
),
array
(
json_encode
(
$this
)
),
array
(
''
),
);
);
}
}
/**
/**
* @dataProvider
storeGet
Data
* @dataProvider
keyValue
Data
*/
*/
public
function
testStoreGet
(
$data
)
public
function
testStoreGet
(
$data
)
{
{
$db
=
$this
->
getConnection
(
true
);
$db
=
$this
->
getConnection
(
true
);
$db
->
SET
(
'hi'
,
$data
);
$db
->
set
(
'hi'
,
$data
);
$this
->
assertEquals
(
$data
,
$db
->
GET
(
'hi'
));
$this
->
assertEquals
(
$data
,
$db
->
get
(
'hi'
));
}
}
}
}
\ No newline at end of file
tests/unit/framework/db/redis/RedisTestCase.php
View file @
0d2f5028
<?php
<?php
/**
*
*
* @author Carsten Brandt <mail@cebe.cc>
*/
namespace
yiiunit\framework\db\redis
;
namespace
yiiunit\framework\db\redis
;
use
yii\db\redis\Connection
;
use
yii\db\redis\Connection
;
use
yiiunit\TestCase
;
use
yiiunit\TestCase
;
/**
* RedisTestCase is the base class for all redis related test cases
*/
class
RedisTestCase
extends
TestCase
class
RedisTestCase
extends
TestCase
{
{
function
__construct
()
protected
function
setUp
()
{
{
// TODO check if a redis server is running
$params
=
$this
->
getParam
(
'redis'
);
//$this->markTestSkipped('No redis server running at port ...');
if
(
$params
===
null
||
!
isset
(
$params
[
'dsn'
]))
{
$this
->
markTestSkipped
(
'No redis server connection configured.'
);
}
$dsn
=
explode
(
'/'
,
$params
[
'dsn'
]);
$host
=
$dsn
[
2
];
if
(
strpos
(
$host
,
':'
)
===
false
)
{
$host
.=
':6379'
;
}
if
(
!@
stream_socket_client
(
$host
,
$errorNumber
,
$errorDescription
,
0.5
))
{
$this
->
markTestSkipped
(
'No redis server running at '
.
$params
[
'dsn'
]
.
' : '
.
$errorNumber
.
' - '
.
$errorDescription
);
}
parent
::
setUp
();
}
}
/**
/**
* @param bool $reset whether to clean up the test database
* @param bool $reset whether to clean up the test database
* @return Connection
* @return Connection
*/
*/
function
getConnection
(
$reset
=
true
)
public
function
getConnection
(
$reset
=
true
)
{
{
$params
=
$this
->
getParam
(
'redis'
);
$params
=
$this
->
getParam
(
'redis'
);
$db
=
new
\yii\db\redis\Connection
;
$db
=
new
\yii\db\redis\Connection
;
$db
->
dsn
=
$params
[
'dsn'
];
$db
->
dsn
=
$params
[
'dsn'
];
$db
->
username
=
$params
[
'username'
];
$db
->
password
=
$params
[
'password'
];
$db
->
password
=
$params
[
'password'
];
if
(
$reset
)
{
if
(
$reset
)
{
// TODO implement
$db
->
open
();
/* $db->open
();
$db
->
flushall
();
$lines = explode(';', file_get_contents($params['fixture']));
/*
$lines = explode(';', file_get_contents($params['fixture']));
foreach ($lines as $line) {
foreach ($lines as $line) {
if (trim($line) !== '') {
if (trim($line) !== '') {
$db->pdo->exec($line);
$db->pdo->exec($line);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment