Version 4.3.0

This commit is contained in:
Neo committed 2025-12-19 05:47:12 -08:00
1 parent 96997ddd8e
commit fe1acf984a
1349 files changed
+116159 -67711

No files matched your search

+71 -156
View File
@@ -22,6 +22,23 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _Redis extends \IPS\Data\Cache
{
/**
* Constructor
*
* @return void
*/
public function __construct( $configuration )
{
try
{
\IPS\Redis::i();
}
catch( \RedisException $e )
{
throw new \IPS\Data\Cache\Exception;
}
}
/**
* Server supports this method?
*
@@ -60,89 +77,28 @@ class _Redis extends \IPS\Data\Cache
}
/**
* @brief Connection resource
* Redis key
*/
protected static $links = array();
protected $_redisKey;
/**
* @brief Connection key
*/
protected $connectionKey = NULL;
/**
* @brief Connection timeout - keep low or you negate the benefits of caching
*/
protected $timeout = 2;
/**
* Constructor
* Get random string used in the keys to identify this site compared to other sites
*
* @param array $configuration Configuration
* @return void
* @param string $key
* @return string|FALSE Value from the _datastore; FALSE if key doesn't exist
*/
public function __construct( $configuration )
protected function _getRedisKey()
{
/* Figure out our connection key, as you could theoretically attempt to connect to more than one Redis server */
$this->connectionKey = md5( $configuration['server'] . ':' . $configuration['port'] );
/* If we've already attempted to establish this link, just return now */
if( isset( static::$links[ $this->connectionKey ] ) )
if ( !$this->_redisKey )
{
return;
}
/* Connect to server */
try
{
static::$links[ $this->connectionKey ] = new \Redis;
if( static::$links[ $this->connectionKey ]->connect( $configuration['server'], $configuration['port'], $this->timeout ) === FALSE )
if ( !( $this->_redisKey = \IPS\Redis::i()->get( 'redisKey' ) ) )
{
$this->resetConnection();
throw new \RedisException;
$this->_redisKey = md5( mt_rand() );
\IPS\Redis::i()->setex( 'redisKey', 604800, $this->_redisKey );
}
else
{
if( $configuration['password'] )
{
if( static::$links[ $this->connectionKey ]->auth( $configuration['password'] ) === FALSE )
{
$this->resetConnection();
throw new \RedisException;
}
}
}
if( static::$links[ $this->connectionKey ] !== NULL )
{
static::$links[ $this->connectionKey ]->setOption( \Redis::OPT_SERIALIZER, \Redis::SERIALIZER_PHP );
}
/* If connection times out, connect can return TRUE and we won't know until our next attempt to talk to the server,
so we should ping now to verify we were able to connect successfully */
static::$links[ $this->connectionKey ]->ping();
register_shutdown_function( function( $object ){
try
{
if( isset( static::$links[ $object->connectionKey ] ) AND static::$links[ $object->connectionKey ] )
{
static::$links[ $object->connectionKey ]->close();
unset( static::$links[ $object->connectionKey ] );
}
}
catch( \RedisException $e ){}
}, $this );
\IPS\Log::debug( "Connected to Redis", 'cache' );
}
catch( \RedisException $e )
{
$this->resetConnection( $e );
\IPS\Log::debug( "Connection to Redis failed", 'cache' );
}
return $this->_redisKey;
}
/**
@@ -153,32 +109,23 @@ class _Redis extends \IPS\Data\Cache
*/
protected function get( $key )
{
if( isset( $this->cache[ $key ] ) )
if( array_key_exists( $key, $this->cache ) )
{
\IPS\Log::debug( "Get {$key} from Redis (already loaded)", 'cache' );
return $this->cache[ $key ];
}
if ( static::$links[ $this->connectionKey ] )
try
{
\IPS\Log::debug( "Get {$key} from Redis", 'cache' );
$this->cache[ $key ] = \IPS\Redis::i()->get( $this->_getRedisKey() . '_' . $key );
try
{
$this->cache[ $key ] = static::$links[ $this->connectionKey ]->get( \IPS\SUITE_UNIQUE_KEY . '_' . $key );
return $this->cache[ $key ];
}
catch( \RedisException $e )
{
$this->resetConnection( $e );
return FALSE;
}
return $this->cache[ $key ];
}
catch( \RedisException $e )
{
\IPS\Redis::i()->resetConnection( $e );
/* No connection */
return FALSE;
return FALSE;
}
}
/**
@@ -191,32 +138,24 @@ class _Redis extends \IPS\Data\Cache
*/
protected function set( $key, $value, \IPS\DateTime $expire = NULL )
{
if ( static::$links[ $this->connectionKey ] )
try
{
\IPS\Log::debug( "Set {$key} in Redis", 'cache' );
try
if ( $expire )
{
if ( $expire )
{
return (bool) static::$links[ $this->connectionKey ]->setex( \IPS\SUITE_UNIQUE_KEY . '_' . $key, $expire->getTimestamp() - time(), $value );
}
else
{
/* Set for 24 hours */
return (bool) static::$links[ $this->connectionKey ]->setex( \IPS\SUITE_UNIQUE_KEY . '_' . $key, 86400, $value );
}
return (bool) \IPS\Redis::i()->setex( $this->_getRedisKey() . '_' . $key, $expire->getTimestamp() - time(), $value );
}
catch( \RedisException $e )
else
{
$this->resetConnection( $e );
return FALSE;
/* Set for 24 hours */
return (bool) \IPS\Redis::i()->setex( $this->_getRedisKey() . '_' . $key, 86400, $value );
}
}
catch( \RedisException $e )
{
\IPS\Redis::i()->resetConnection( $e );
/* No connection */
return FALSE;
return FALSE;
}
}
/**
@@ -227,14 +166,11 @@ class _Redis extends \IPS\Data\Cache
*/
protected function exists( $key )
{
if( isset( $this->cache[ $key ] ) )
if( array_key_exists( $key, $this->cache ) )
{
\IPS\Log::debug( "Check exists {$key} from Redis (already loaded)", 'cache' );
return ( $this->cache[ $key ] === FALSE ) ? FALSE : TRUE;
}
\IPS\Log::debug( "Check exists {$key} from Redis", 'cache' );
/* We do a get instead of an exists() check because it will cause the cache value to be fetched and cached inline, saving another call to the server */
return ( $this->get( $key ) === FALSE ) ? FALSE : TRUE;
}
@@ -246,39 +182,16 @@ class _Redis extends \IPS\Data\Cache
* @return bool
*/
protected function delete( $key )
{
if ( static::$links[ $this->connectionKey ] )
{
try
{
\IPS\Log::debug( "Delete {$key} from Redis", 'cache' );
try
{
return (bool) static::$links[ $this->connectionKey ]->delete( \IPS\SUITE_UNIQUE_KEY . '_' . $key );
}
catch( \RedisException $e )
{
$this->resetConnection( $e );
}
return (bool) \IPS\Redis::i()->delete( $this->_getRedisKey() . '_' . $key );
}
/* No connection */
return FALSE;
}
/**
* Reset connection
*
* @param \RedisException|NULL If this was called as a result of an exception, log that to the debug log
* @return void
*/
protected function resetConnection( \RedisException $e = NULL )
{
if ( $e !== NULL )
catch( \RedisException $e )
{
\IPS\Log::debug( $e, 'redis_exception' );
\IPS\Redis::i()->resetConnection( $e );
return FALSE;
}
static::$links[ $this->connectionKey ] = NULL;
throw new \IPS\Data\Cache\Exception;
}
/**
@@ -289,17 +202,19 @@ class _Redis extends \IPS\Data\Cache
public function clearAll()
{
parent::clearAll();
if ( static::$links[ $this->connectionKey ] )
{
try
{
static::$links[ $this->connectionKey ]->flushDb();
}
catch( \RedisException $e )
{
$this->resetConnection( $e );
}
}
$this->_redisKey = md5( mt_rand() );
\IPS\Redis::i()->setex( 'redisKey', 604800, $this->_redisKey );
}
/**
* Log a page hit
*
* @param \IPS\Http\Url|NULL $url URL to log (or null)
* @return void
*/
public function logPageHit( $url=NULL )
{
return \IPS\Redis::i()->logPageHit( $url );
}
}