Commit 03427f58 authored by Erick Hitter's avatar Erick Hitter

First pass at Redis-powered system

* Port Redis PECL library connection from [Redis Object Cache](https://github.com/ericmann/Redis-Object-Cache/commit/b768b03f9dce21edd91806dc1ca741aa9523db7e)
* Replace meta functions with appropriate Redis calls
* Override default session manager
parent 048c03fe
<?php <?php
/** /**
* Meta-based user sessions token manager. * Redis-based user sessions token manager.
* *
* @since 4.0.0 * @since 0.1
*/ */
class WP_Redis_Session_Storage extends WP_Session_Tokens { class WP_Redis_User_Session_Storage extends WP_Session_Tokens {
/**
* Holds the Redis client.
*
* @var
*/
private $redis;
/**
* Track if Redis is available
*
* @var bool
*/
private $redis_connected = false;
/**
* Prefix used to namespace keys
*
* @var string
*/
public $prefix = 'wpruss';
/**
*
*/
public function __construct( $user_id ) {
global $blog_id, $table_prefix;
// General Redis settings
$redis = array(
'host' => '127.0.0.1',
'port' => 6379,
);
if ( defined( 'WP_REDIS_BACKEND_HOST' ) && WP_REDIS_BACKEND_HOST ) {
$redis['host'] = WP_REDIS_BACKEND_HOST;
}
if ( defined( 'WP_REDIS_BACKEND_PORT' ) && WP_REDIS_BACKEND_PORT ) {
$redis['port'] = WP_REDIS_BACKEND_PORT;
}
if ( defined( 'WP_REDIS_BACKEND_AUTH' ) && WP_REDIS_BACKEND_AUTH ) {
$redis['auth'] = WP_REDIS_BACKEND_AUTH;
}
if ( defined( 'WP_REDIS_BACKEND_DB' ) && WP_REDIS_BACKEND_DB ) {
$redis['database'] = WP_REDIS_BACKEND_DB;
}
if ( ( defined( 'WP_REDIS_SERIALIZER' ) ) ) {
$redis['serializer'] = WP_REDIS_SERIALIZER;
} else {
$redis['serializer'] = Redis::SERIALIZER_PHP;
}
// Use Redis PECL library.
try {
$this->redis = new Redis();
$this->redis->connect( $redis['host'], $redis['port'] );
$this->redis->setOption( Redis::OPT_SERIALIZER, $redis['serializer'] );
if ( isset( $redis['auth'] ) ) {
$this->redis->auth( $redis['auth'] );
}
if ( isset( $redis['database'] ) ) {
$this->redis->select( $redis['database'] );
}
$this->redis_connected = true;
} catch ( RedisException $e ) {
$this->redis_connected = false;
}
// Ensure Core's session constructor fires
parent::__construct( $user_id );
}
/** /**
* Get all sessions of a user. * Get all sessions of a user.
* *
* @since 4.0.0 * @since 0.1
* @access protected * @access protected
* *
* @return array Sessions of a user. * @return array Sessions of a user.
*/ */
protected function get_sessions() { protected function get_sessions() {
$sessions = get_user_meta( $this->user_id, 'session_tokens', true ); if ( ! $this->redis_connected ) {
return array();
}
$key = $this->get_key();
if ( ! $this->redis->exists( $key ) ) {
return array();
}
$sessions = $this->redis->get( $key );
if ( ! is_array( $sessions ) ) { if ( ! is_array( $sessions ) ) {
return array(); return array();
} }
...@@ -43,7 +125,7 @@ class WP_Redis_Session_Storage extends WP_Session_Tokens { ...@@ -43,7 +125,7 @@ class WP_Redis_Session_Storage extends WP_Session_Tokens {
/** /**
* Retrieve a session by its verifier (token hash). * Retrieve a session by its verifier (token hash).
* *
* @since 4.0.0 * @since 0.1
* @access protected * @access protected
* *
* @param string $verifier Verifier of the session to retrieve. * @param string $verifier Verifier of the session to retrieve.
...@@ -62,7 +144,7 @@ class WP_Redis_Session_Storage extends WP_Session_Tokens { ...@@ -62,7 +144,7 @@ class WP_Redis_Session_Storage extends WP_Session_Tokens {
/** /**
* Update a session by its verifier. * Update a session by its verifier.
* *
* @since 4.0.0 * @since 0.1
* @access protected * @access protected
* *
* @param string $verifier Verifier of the session to update. * @param string $verifier Verifier of the session to update.
...@@ -81,29 +163,35 @@ class WP_Redis_Session_Storage extends WP_Session_Tokens { ...@@ -81,29 +163,35 @@ class WP_Redis_Session_Storage extends WP_Session_Tokens {
} }
/** /**
* Update a user's sessions in the usermeta table. * Update a user's sessions in Redis.
* *
* @since 4.0.0 * @since 0.1
* @access protected * @access protected
* *
* @param array $sessions Sessions. * @param array $sessions Sessions.
*/ */
protected function update_sessions( $sessions ) { protected function update_sessions( $sessions ) {
if ( ! $this->redis_connected ) {
return;
}
if ( ! has_filter( 'attach_session_information' ) ) { if ( ! has_filter( 'attach_session_information' ) ) {
$sessions = wp_list_pluck( $sessions, 'expiration' ); $sessions = wp_list_pluck( $sessions, 'expiration' );
} }
$key = $this->key();
if ( $sessions ) { if ( $sessions ) {
update_user_meta( $this->user_id, 'session_tokens', $sessions ); $this->redis->set( $key, $sessions ) );
} else { } elseif ( $this->redis->exists( $key ) ) {
delete_user_meta( $this->user_id, 'session_tokens' ); $this->redis->del( $key );
} }
} }
/** /**
* Destroy all session tokens for a user, except a single session passed. * Destroy all session tokens for a user, except a single session passed.
* *
* @since 4.0.0 * @since 0.1
* @access protected * @access protected
* *
* @param string $verifier Verifier of the session to keep. * @param string $verifier Verifier of the session to keep.
...@@ -116,7 +204,7 @@ class WP_Redis_Session_Storage extends WP_Session_Tokens { ...@@ -116,7 +204,7 @@ class WP_Redis_Session_Storage extends WP_Session_Tokens {
/** /**
* Destroy all session tokens for a user. * Destroy all session tokens for a user.
* *
* @since 4.0.0 * @since 0.1
* @access protected * @access protected
*/ */
protected function destroy_all_sessions() { protected function destroy_all_sessions() {
...@@ -126,11 +214,25 @@ class WP_Redis_Session_Storage extends WP_Session_Tokens { ...@@ -126,11 +214,25 @@ class WP_Redis_Session_Storage extends WP_Session_Tokens {
/** /**
* Destroy all session tokens for all users. * Destroy all session tokens for all users.
* *
* @since 4.0.0 * @since 0.1
* @access public * @access public
* @static * @static
*/ */
public static function drop_sessions() { public static function drop_sessions() {
delete_metadata( 'user', false, 'session_tokens', false, true ); return false;
}
/**
*
*/
protected function get_key() {
return $this->prefix . ':' . $this->user_id;
} }
} }
/**
*
*/
add_filter( 'session_token_manager', function ( $manager ) {
return 'WP_Redis_User_Session_Storage';
} );
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment