Skip to content

Instantly share code, notes, and snippets.

@tazzytazzy
Created December 27, 2023 21:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tazzytazzy/40deb7788166f9bbd1d42e762385432e to your computer and use it in GitHub Desktop.
Save tazzytazzy/40deb7788166f9bbd1d42e762385432e to your computer and use it in GitHub Desktop.
// For mediawiki 1.41.0 - includes/libs/redis/RedisConnectionPool.php
/**
* Get a connection to a redis server. Based on code in RedisBagOStuff.php.
*
* @param string $server A hostname/port combination or the absolute path of a UNIX socket.
* If a hostname is specified but no port, port 6379 will be used.
* @param LoggerInterface|null $logger PSR-3 logger instance. [optional]
* @return RedisConnRef|Redis|false Returns false on failure
* @throws InvalidArgumentException
*/
public function getConnection( $server, LoggerInterface $logger = null ) {
// See: https://www.mediawiki.org/wiki/Talk:Redis
global $wgRedisDatabase;
if (is_null($wgRedisDatabase)) {
$wgRedisDatabase = 0;
}
// The above @return also documents 'Redis' for convenience with IDEs.
// RedisConnRef uses PHP magic methods, which wouldn't be recognised.
$logger = $logger ?: $this->logger;
// Check the listing "dead" servers which have had a connection errors.
// Servers are marked dead for a limited period of time, to
// avoid excessive overhead from repeated connection timeouts.
if ( isset( $this->downServers[$server] ) ) {
$now = time();
if ( $now > $this->downServers[$server] ) {
// Dead time expired
unset( $this->downServers[$server] );
} else {
// Server is dead
$logger->debug(
'Server "{redis_server}" is marked down for another ' .
( $this->downServers[$server] - $now ) . ' seconds',
[ 'redis_server' => $server ]
);
return false;
}
}
// Check if a connection is already free for use
if ( isset( $this->connections[$server] ) ) {
foreach ( $this->connections[$server] as &$connection ) {
if ( $connection['free'] ) {
$connection['free'] = false;
--$this->idlePoolSize;
return new RedisConnRef(
$this, $server, $connection['conn'], $logger
);
}
}
}
if ( !$server ) {
throw new InvalidArgumentException(
__CLASS__ . ": invalid configured server \"$server\"" );
} elseif ( substr( $server, 0, 1 ) === '/' ) {
// UNIX domain socket
// These are required by the redis extension to start with a slash, but
// we still need to set the port to a special value to make it work.
$host = $server;
$port = 0;
} else {
// TCP connection
if ( preg_match( '/^\[(.+)\]:(\d+)$/', $server, $m ) ) {
// (ip, port)
[ $host, $port ] = [ $m[1], (int)$m[2] ];
} elseif ( preg_match( '/^((?:[\w]+\:\/\/)?[^:]+):(\d+)$/', $server, $m ) ) {
// (ip, uri or path, port)
[ $host, $port ] = [ $m[1], (int)$m[2] ];
if (
substr( $host, 0, 6 ) === 'tls://'
&& version_compare( phpversion( 'redis' ), '5.0.0' ) < 0
) {
throw new RuntimeException(
'A newer version of the Redis client library is required to use TLS. ' .
'See https://www.mediawiki.org/wiki/Redis#Setup' );
}
} else {
// (ip or path, port)
[ $host, $port ] = [ $server, 6379 ];
}
}
$conn = new Redis();
try {
if ( $this->persistent ) {
$result = $conn->pconnect( $host, $port, $this->connectTimeout, $this->id );
} else {
$result = $conn->connect( $host, $port, $this->connectTimeout );
}
if ( !$result ) {
$logger->error(
'Could not connect to server "{redis_server}"',
[ 'redis_server' => $server ]
);
// Mark server down for some time to avoid further timeouts
$this->downServers[$server] = time() + self::SERVER_DOWN_TTL;
return false;
}
if ( ( $this->password !== null ) && !$conn->auth( $this->password ) ) {
$logger->error(
'Authentication error connecting to "{redis_server}"',
[ 'redis_server' => $server ]
);
}
} catch ( RedisException $e ) {
$this->downServers[$server] = time() + self::SERVER_DOWN_TTL;
$logger->error(
'Redis exception connecting to "{redis_server}"',
[
'redis_server' => $server,
'exception' => $e,
]
);
return false;
}
$conn->select($wgRedisDatabase);
$conn->setOption( Redis::OPT_READ_TIMEOUT, $this->readTimeout );
$conn->setOption( Redis::OPT_SERIALIZER, $this->serializer );
$this->connections[$server][] = [ 'conn' => $conn, 'free' => false ];
return new RedisConnRef( $this, $server, $conn, $logger );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment