Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2876099 create submodule to #33

Open
wants to merge 15 commits into
base: 8.x-1.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ If your Redis instance is remote, you can use this syntax:

Port is optional, default is 6379 (default Redis port).

Use persistent connections
--------------------------

This mode needs the following setting:

$settings['redis.connection']['persistent'] = TRUE;

Compression
-------------------------
Compressing the data stored in redis can massively reduce the nedeed storage.
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"name": "drupal/redis",
"type": "drupal-module",
"description": "Integration of Drupal with the Redis key-value store.",
"suggest": {
"predis/predis": "^1.1.1"
},
"license": "GPL-2.0",
"license": "GPL-2.0-or-later",
"autoload": {
"psr-4": {
"Drupal\\redis\\": "src"
Expand Down
41 changes: 41 additions & 0 deletions modules/redis_sessions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
CONTENTS OF THIS FILE
---------------------

* Introduction
* Requirements
* Installation
* Configuration


INTRODUCTION
------------

The Redis Sessions module creates an alternative to database storage for user
sessions. It uses a PHP Redis sessions manager and custom settings to
use Redis for sessions handling and storage.


REQUIREMENTS
------------

This module requires the following modules:

* Redis (https://drupal.org/project/redis)


INSTALLATION
------------

* Install as you would normally install a contributed Drupal module. See:
https://www.drupal.org/docs/8/extending-drupal-8/installing-modules
for further information.


CONFIGURATION
-------------

Either include the default example.services.yml from the module, which will
replace all supported backend services (check the file for the current list)
or copy the service definitions into a site specific services.yml.

$settings['container_yamls'][] = 'modules/redis/modules/redis_sessions/example.services.yml';
14 changes: 14 additions & 0 deletions modules/redis_sessions/example.services.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# This file contains example services overrides.
#
# Enable with this line in settings.php
# $settings['container_yamls'][] = 'modules/redis/modules/redis_sessions/example.services.yml';
#
# Or copy & paste the desired services into sites/default/services.yml.
#
# Note that the redis module must be enabled for this to work.

services:
# Replaces the default session handler storage with a redis implementation.
session_handler.storage:
class: SessionHandlerInterface
factory: ['@redis_sessions.session_handler.factory', get]
7 changes: 7 additions & 0 deletions modules/redis_sessions/redis_sessions.info.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: "Redis Sessions"
description: "A module to change PHP's session handling to use Redis."
package: "Performance"
type: module
core_version_requirement: ^8.8 || ^9
dependencies:
- redis:redis
4 changes: 4 additions & 0 deletions modules/redis_sessions/redis_sessions.services.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
services:
redis_sessions.session_handler.factory:
class: Drupal\redis_sessions\Session\SessionHandlerFactory
arguments: ['@redis.factory']
41 changes: 41 additions & 0 deletions modules/redis_sessions/src/Session/SessionHandlerFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Drupal\redis_sessions\Session;

use Drupal\redis\ClientFactory;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler;

/**
* Session handler handling.
*/
class SessionHandlerFactory {

/**
* The client factory.
*
* @var \Drupal\redis\ClientFactory
*/
protected $clientFactory;

/**
* Constructor.
*
* @param \Drupal\redis\ClientFactory $client_factory
* The client factory.
*/
public function __construct(ClientFactory $client_factory) {
$this->clientFactory = $client_factory;
}

/**
* Get actual session handler.
*
* @return \SessionHandlerInterface
* Return the redis session handler.
*/
public function get() {
$client = $this->clientFactory->getClient();
return new RedisSessionHandler($client);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Drupal\Tests\redis_sessions\Functional;

use Drupal\Component\Utility\OpCodeCache;
use Drupal\Core\Site\Settings;
use Drupal\Tests\redis\Functional\WebTest;

/**
* Tests complex processes like installing modules with redis backends.
*
* @group redis
* @group redis_sessions
*/
class RedisSessionWebTest extends WebTest {

/**
* {@inheritdoc}
*/
public static $modules = [
'redis_sessions',
];

/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();

// Set in-memory settings.
$settings = Settings::getAll();
$settings['container_yamls'][] = drupal_get_path('module', 'redis_sessions') . '/example.services.yml';
new Settings($settings);

// Write the containers_yaml update by hand, since writeSettings() doesn't
// support some of the definitions.
$filename = $this->siteDirectory . '/settings.php';
chmod($filename, 0666);
$contents = file_get_contents($filename);

// Add the container_yaml and cache definition.
$contents .= "\n\n" . '$settings["container_yamls"][] = "' . drupal_get_path('module', 'redis_sessions') . '/example.services.yml";';
file_put_contents($filename, $contents);
OpCodeCache::invalidate(DRUPAL_ROOT . '/' . $filename);

$this->rebuildContainer();
}

}
7 changes: 4 additions & 3 deletions redis.info.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Redis
description: Provide a module placeholder, for using as dependency for module that needs Redis.
package: Performance
name: "Redis"
description: "Provide a module placeholder, for using as dependency for module that needs Redis."
package: "Performance"
type: module
core_version_requirement: ^8.8 || ^9
configure: redis.admin_display
php: 7.1.0
2 changes: 1 addition & 1 deletion redis.install
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function redis_requirements($phase) {
'title' => "Redis",
'value' => t("Not connected."),
'severity' => REQUIREMENT_WARNING,
'description' => t("No Redis client connected, this module is useless thereof. Ensure that you enabled module using it or disable it."),
'description' => t("No Redis client connected, this module is therefore not used. Ensure that Redis is configured correctly, or disable this module."),
];
}

Expand Down
2 changes: 1 addition & 1 deletion src/Cache/CacheBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ protected function expandEntry(array $values, $allow_invalid) {
*
* @return array
*/
protected function createEntryHash($cid, $data, $expire = Cache::PERMANENT, array $tags) {
protected function createEntryHash($cid, $data, $expire, array $tags) {
// Always add a cache tag for the current bin, so that we can use that for
// invalidateAll().
$tags[] = $this->getTagForBin();
Expand Down
3 changes: 2 additions & 1 deletion src/Cache/RedisCacheTagsChecksum.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ protected function getTagInvalidationCounts(array $tags) {
// The mget command returns the values as an array with numeric keys,
// combine it with the tags array to get the expected return value and run
// it through intval() to convert to integers and FALSE to 0.
return array_map('intval', array_combine($tags, $this->client->mget($keys)));
$values = $this->client->mget($keys);
return $values ? array_map('intval', array_combine($tags, $values)) : [];
}

/**
Expand Down
9 changes: 7 additions & 2 deletions src/Client/PhpRedis.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class PhpRedis implements ClientInterface {
/**
* {@inheritdoc}
*/
public function getClient($host = NULL, $port = NULL, $base = NULL, $password = NULL) {
public function getClient($host = NULL, $port = NULL, $base = NULL, $password = NULL, $replicationHosts = [], $persistent = FALSE) {
$client = new \Redis();

// Sentinel mode, get the real master.
Expand All @@ -25,7 +25,12 @@ public function getClient($host = NULL, $port = NULL, $base = NULL, $password =
}
}

$client->connect($host, $port);
if ($persistent) {
$client->pconnect($host, $port);
}
else {
$client->connect($host, $port);
}

if (isset($password)) {
$client->auth($password);
Expand Down
17 changes: 10 additions & 7 deletions src/Client/Predis.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
*/
class Predis implements ClientInterface {

public function getClient($host = NULL, $port = NULL, $base = NULL, $password = NULL, $replicationHosts = NULL) {
public function getClient($host = NULL, $port = NULL, $base = NULL, $password = NULL, $replicationHosts = [], $persistent = FALSE) {
$connectionInfo = [
'password' => $password,
'host' => $host,
'port' => $port,
'database' => $base
'database' => $base,
'persistent' => $persistent
];

foreach ($connectionInfo as $key => $value) {
Expand All @@ -32,17 +33,19 @@ public function getClient($host = NULL, $port = NULL, $base = NULL, $password =
date_default_timezone_set(@date_default_timezone_get());

// If we are passed in an array of $replicationHosts, we should attempt a clustered client connection.
if ($replicationHosts !== NULL) {
if (!empty($replicationHosts)) {
$parameters = [];

foreach ($replicationHosts as $replicationHost) {
$param = 'tcp://' . $replicationHost['host'] . ':' . $replicationHost['port']
. '?persistent=' . (($persistent) ? 'true' : 'false');

// Configure master.
if ($replicationHost['role'] === 'primary') {
$parameters[] = 'tcp://' . $replicationHost['host'] . ':' . $replicationHost['port'] . '?alias=master';
}
else {
$parameters[] = 'tcp://' . $replicationHost['host'] . ':' . $replicationHost['port'];
$param .= '&alias=master';
}

$parameters[] = $param;
}

$options = ['replication' => true];
Expand Down
8 changes: 6 additions & 2 deletions src/ClientFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ public static function getClient() {
'port' => self::REDIS_DEFAULT_PORT,
'base' => self::REDIS_DEFAULT_BASE,
'password' => self::REDIS_DEFAULT_PASSWORD,
'persistent' => FALSE,
];

// If using replication, lets create the client appropriately.
Expand All @@ -165,14 +166,17 @@ public static function getClient() {
$settings['port'],
$settings['base'],
$settings['password'],
$settings['replication.host']);
$settings['replication.host'],
$settings['persistent']);
}
else {
self::$_client = self::getClientInterface()->getClient(
$settings['host'],
$settings['port'],
$settings['base'],
$settings['password']);
$settings['password'],
[], // There are no replication hosts.
$settings['persistent']);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/ClientInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface ClientInterface {
* @return mixed
* Real client depends from the library behind.
*/
public function getClient($host = NULL, $port = NULL, $base = NULL);
public function getClient($host = NULL, $port = NULL, $base = NULL, $password = NULL, $replicationHosts = [], $persistent = FALSE);

/**
* Get underlying library name used.
Expand Down
6 changes: 3 additions & 3 deletions src/Controller/ReportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public static function create(ContainerInterface $container) {
public function overview() {

$build['report'] = [
'#theme' => 'status_report',
'#type' => 'status_report',
'#requirements' => [],
];

Expand Down Expand Up @@ -171,9 +171,9 @@ public function overview() {

if ($memory_config['maxmemory']) {
$memory_value = $this->t('@used_memory / @max_memory (@used_percentage%), maxmemory policy: @policy', [
'@used_memory' => $info['used_memory_human'],
'@used_memory' => $info['used_memory_human'] ?? $info['Memory']['used_memory_human'],
'@max_memory' => format_size($memory_config['maxmemory']),
'@used_percentage' => (int) ($info['used_memory'] / $memory_config['maxmemory'] * 100),
'@used_percentage' => (int) ($info['used_memory'] ?? $info['Memory']['used_memory'] / $memory_config['maxmemory'] * 100),
'@policy' => $memory_config['maxmemory-policy'],
]);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/src/Kernel/RedisLockTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public function register(ContainerBuilder $container) {
/**
* {@inheritdoc}
*/
protected function setUp() {
protected function setUp(): void {
parent::setUp();
$this->lock = $this->container->get('lock');
}
Expand Down