Skip to content

Commit d5594fc

Browse files
committed
feat: allow configuring a separate redis instance for use with notify_push
Signed-off-by: Robin Appelman <robin@icewind.nl>
1 parent e936bf3 commit d5594fc

6 files changed

Lines changed: 124 additions & 9 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ rand = { version = "0.8.5", features = ["small_rng"] }
2929
ahash = "0.8.11"
3030
flexi_logger = { version = "0.29.8", features = ["colors"] }
3131
tokio-stream = { version = "0.1.17", features = ["net"] }
32-
nextcloud-config-parser = "0.13.1"
32+
nextcloud-config-parser = "0.14.0"
3333
url = "2.5.4"
3434
clap = { version = "4.5.26", features = ["derive"] }
3535
sd-notify = { version = "0.4.3", optional = true }

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,17 @@ Note that Nextcloud loads all files matching `*.config.php` in the config direct
146146
file.
147147
You can enable this same behavior by passing the `--glob-config` option.
148148

149-
#####
149+
<details>
150+
<summary>Using a separate redis instance for the push server
151+
</summary>
152+
153+
You can optionally use a different redis instance for communications between the Nextcloud server and the push daemon.
154+
155+
This allows spreading moving the load away from the normal redis usage or use a redis setup more optimized for the specific usage (`PUBSUB` traffic instead of cache storage).
156+
157+
You can configure this by setting the `notify_push_redis` config option in the `config.php` of the Nextcloud server, this accepts the same options as the normal redis configurations.
158+
159+
</details>
150160

151161
<details>
152162
<summary>Connecting to redis over TLS

lib/AppInfo/Application.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
use OCA\NotifyPush\Listener;
1515
use OCA\NotifyPush\Queue\IQueue;
1616
use OCA\NotifyPush\Queue\NullQueue;
17+
use OCA\NotifyPush\Queue\PushRedisFactory;
18+
use OCA\NotifyPush\Queue\QueueFactory;
1719
use OCA\NotifyPush\Queue\RedisQueue;
1820
use OCP\Activity\IManager;
1921
use OCP\AppFramework\App;
@@ -41,10 +43,11 @@ public function register(IRegistrationContext $context): void {
4143
$context->registerCapability(Capabilities::class);
4244

4345
$context->registerService(IQueue::class, function (ContainerInterface $c) {
44-
/** @var RedisFactory $redisFactory */
45-
$redisFactory = $c->get(RedisFactory::class);
46-
if ($redisFactory->isAvailable()) {
47-
return new RedisQueue($redisFactory->getInstance());
46+
/** @var PushRedisFactory $factory */
47+
$factory = $c->get(PushRedisFactory::class);
48+
$redis = $factory->getRedis();
49+
if ($redis) {
50+
return new RedisQueue($redis);
4851
} else {
4952
return new NullQueue();
5053
}

lib/Queue/PushRedisFactory.php

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* SPDX-FileCopyrightText: 2025 Robin Appelman <robin@icewind.nl>
6+
* SPDX-License-Identifier: AGPL-3.0-or-later
7+
*/
8+
9+
namespace OCA\NotifyPush\Queue;
10+
11+
use OC\RedisFactory;
12+
use OCP\IConfig;
13+
14+
class PushRedisFactory {
15+
private $instance = null;
16+
private IConfig $config;
17+
private RedisFactory $redisFactory;
18+
19+
public function __construct(
20+
IConfig $config,
21+
RedisFactory $redisFactory,
22+
) {
23+
$this->config = $config;
24+
$this->redisFactory = $redisFactory;
25+
}
26+
27+
/**
28+
* @return \Redis|\RedisCluster|null
29+
* @throws \Exception
30+
*/
31+
public function getRedis() {
32+
if ($this->instance) {
33+
return $this->instance;
34+
}
35+
if ($this->config->getSystemValue('notify_push_redis', []) !== []) {
36+
return $this->getSeparateRedis();
37+
} elseif ($this->redisFactory->isAvailable()) {
38+
return $this->redisFactory->getInstance();
39+
} else {
40+
return null;
41+
}
42+
}
43+
44+
private function getSeparateRedis(): \Redis {
45+
$config = $this->config->getSystemValue('notify_push_redis', []);
46+
$timeout = $config['timeout'] ?? 0.0;
47+
$readTimeout = $config['read_timeout'] ?? 0.0;
48+
49+
$auth = null;
50+
if (isset($config['password']) && (string)$config['password'] !== '') {
51+
if (isset($config['user']) && (string)$config['user'] !== '') {
52+
$auth = [$config['user'], $config['password']];
53+
} else {
54+
$auth = $config['password'];
55+
}
56+
}
57+
58+
$persistent = $this->config->getSystemValue('notify_push_redis.persistent', true);
59+
60+
$redis = new \Redis();
61+
62+
$host = $config['host'] ?? '127.0.0.1';
63+
$port = $config['port'] ?? ($host[0] !== '/' ? 6379 : null);
64+
65+
// Support for older phpredis versions not supporting connectionParameters
66+
if (isset($config['ssl_context'])) {
67+
// Non-clustered redis requires connection parameters to be wrapped inside `stream`
68+
$connectionParameters = [
69+
'stream' => $config['ssl_context']
70+
];
71+
if ($persistent) {
72+
/**
73+
* even though the stubs and documentation don't want you to know this,
74+
* pconnect does have the same $connectionParameters argument connect has
75+
*
76+
* https://github.com/phpredis/phpredis/blob/0264de1824b03fb2d0ad515b4d4ec019cd2dae70/redis.c#L710-L730
77+
*
78+
* @psalm-suppress TooManyArguments
79+
*/
80+
$redis->pconnect($host, $port, $timeout, null, 0, $readTimeout, $connectionParameters);
81+
} else {
82+
$redis->connect($host, $port, $timeout, null, 0, $readTimeout, $connectionParameters);
83+
}
84+
} else {
85+
if ($persistent) {
86+
$redis->pconnect($host, $port, $timeout, null, 0, $readTimeout);
87+
} else {
88+
$redis->connect($host, $port, $timeout, null, 0, $readTimeout);
89+
}
90+
}
91+
92+
if ($auth !== null) {
93+
$redis->auth($auth);
94+
}
95+
96+
if (isset($config['dbindex'])) {
97+
$redis->select($config['dbindex']);
98+
}
99+
100+
return $redis;
101+
}
102+
}

src/config/nc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub(super) fn parse_config_file(
1818
database: Some(config.database.url().parse()?),
1919
database_prefix: Some(config.database_prefix),
2020
nextcloud_url: Some(config.nextcloud_url),
21-
redis: Some(config.redis),
21+
redis: Some(config.notify_push_redis.unwrap_or(config.redis)),
2222
..PartialConfig::default()
2323
})
2424
}

0 commit comments

Comments
 (0)