Skip to content

Commit ab6dbe6

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 ab6dbe6

6 files changed

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

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)