Skip to content

Commit 2fcfef4

Browse files
authored
fix(backend): use node-redis instead of ioredis for sharedb-redis-pubsub (#38)
* fix(backend): use node-redis instead of ioredis for sharedb-redis-pubsub * chore: use yarn from alpha branch * chore(sharedb-access,sharedb-schema): remove dev deps for now since tests are not working anyways and they lead to non-deduped instances of sharedb
1 parent a883c9d commit 2fcfef4

12 files changed

Lines changed: 137 additions & 123 deletions

File tree

packages/backend/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export interface DbExports {
4040
export function createBackend (options?: BackendOptions): any // Replace 'any' with Backend class type
4141

4242
// Exports instances and constructors for Redis and database connections
43+
export function getRedis (options?: any): Redis
4344
export const redis: RedisExports['redis']
4445
export const redlock: RedisExports['redlock']
4546
export const Redlock: RedisExports['Redlock']

packages/backend/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export default function createBackend ({
4444

4545
const backend = new ShareDB({
4646
db,
47-
pubsub,
47+
...(pubsub ? { pubsub } : {}),
4848
extraDbs
4949
})
5050

packages/backend/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@
2222
"ioredis": "^5.3.2",
2323
"ioredis-mock": "^8.9.0",
2424
"mongodb": "^6.0.0",
25+
"redis": "^5.0.0",
2526
"redlock": "^3.0.0",
26-
"sharedb": "^5.0.0",
27+
"sharedb": "5.2.2",
2728
"sharedb-hooks": "~4.0.0",
2829
"sharedb-mongo": "^4.1.2",
2930
"sharedb-redis-pubsub": "^5.1.0",
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import RedisMock from 'ioredis-mock'
44

55
export { Redis, RedisMock }
66

7-
export function getRedis ({ enable = true, opts, url, keyPrefix, ...additionalOptions }) {
7+
export function getIoRedis ({ enable = true, opts, url, keyPrefix, ...additionalOptions }) {
88
if (enable) {
99
if (typeof opts === 'string') {
1010
opts = JSON.parse(opts)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { readFileSync } from 'fs'
2+
import { createClient, createSentinel } from 'redis'
3+
4+
export function getNodeRedis ({ opts, url }) {
5+
const parsedOpts = typeof opts === 'string' ? JSON.parse(opts) : opts
6+
7+
let client
8+
9+
if (parsedOpts?.sentinels) {
10+
client = createSentinel(_getSentinelOptions(parsedOpts))
11+
} else if (url) {
12+
client = createClient({ url })
13+
}
14+
15+
if (!client) {
16+
throw new Error('[@teamplay/backend] REDIS_URL or REDIS_OPTS is required when Redis pubsub is enabled')
17+
}
18+
19+
client.on('error', error => {
20+
console.error('[@teamplay/backend] Redis pubsub client error:', error)
21+
})
22+
23+
return client
24+
}
25+
26+
function _getSentinelOptions (opts) {
27+
const tls = _getTlsOptions(opts)
28+
const socket = tls ? { tls: true, ...tls } : undefined
29+
const sentinelRootNodes = opts.sentinels.map(sentinel => ({
30+
host: sentinel.host || sentinel.hostname || sentinel.ip || sentinel.address,
31+
port: Number(sentinel.port || opts.sentinel_port || 26379)
32+
}))
33+
34+
return {
35+
name: opts.name || 'mymaster',
36+
sentinelRootNodes,
37+
nodeClientOptions: {
38+
socket,
39+
username: opts.username,
40+
password: opts.password,
41+
database: opts.db || 0
42+
},
43+
sentinelClientOptions: {
44+
socket,
45+
username: opts.sentinelUsername,
46+
password: opts.sentinelPassword
47+
}
48+
}
49+
}
50+
51+
function _getTlsOptions (opts) {
52+
if (!opts?.key) return
53+
54+
return {
55+
key: readFileSync(opts.key),
56+
cert: readFileSync(opts.cert),
57+
ca: readFileSync(opts.ca)
58+
}
59+
}

packages/backend/redis/index.js

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,34 @@
11
import Redlock from 'redlock'
22
import redisPubSub from 'sharedb-redis-pubsub'
3-
import { getRedis, Redis, RedisMock } from './getRedis.js'
3+
import { getIoRedis, Redis, RedisMock } from './getIoRedis.js'
4+
import { getNodeRedis } from './getNodeRedis.js'
45

56
const ENABLE_REDIS = !process.env.NO_REDIS
7+
const ENABLE_REDIS_PUBSUB = ENABLE_REDIS && !!(process.env.REDIS_URL || process.env.REDIS_OPTS)
68

79
const RedisClient = ENABLE_REDIS ? Redis : RedisMock
8-
export { RedisClient as Redis, getRedis, getRedisOptions, generatePrefix }
10+
export {
11+
RedisClient as Redis,
12+
getRedisOptions,
13+
generatePrefix
14+
}
15+
export const getRedis = getIoRedis
916
export const prefix = generatePrefix({
1017
mongoUrl: process.env.MONGO_URL,
1118
baseUrl: process.env.BASE_URL
1219
})
13-
export const redis = getRedis(getRedisOptions())
14-
export const redisObserver = getRedis(getRedisOptions())
20+
export const redis = getIoRedis(getRedisOptions())
1521

16-
export const pubsub = redisPubSub({
17-
client: redis,
18-
observer: redisObserver,
19-
prefix
20-
})
22+
// Teamplay exposes ioredis for the rest of the backend ecosystem
23+
// (BullMQ, Redlock, mocks), but sharedb-redis-pubsub@5 expects node-redis.
24+
// We therefore create separate node-redis clients only for ShareDB pubsub.
25+
export const pubsub = ENABLE_REDIS_PUBSUB
26+
? redisPubSub({
27+
client: getNodeRedis(getRedisOptions({ addPrefix: false })),
28+
observer: getNodeRedis(getRedisOptions({ addPrefix: false })),
29+
prefix
30+
})
31+
: undefined
2132

2233
export const redlock = getRedlock(redis)
2334

packages/sharedb-access/package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
"lodash": "^4.17.20"
2323
},
2424
"devDependencies": {
25-
"mocha": "^11.7.5",
26-
"racer": "1.0.1",
27-
"sharedb": "^5.0.0"
25+
"mocha": "^11.7.5"
2826
}
2927
}

packages/sharedb-access/test/db.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// TODO: Update tests to work with new teamplay api
12
import promisifyRacer from '@startupjs/orm/lib/promisifyRacer.js'
23
import racer from 'racer'
34
import sharedb from 'sharedb'

packages/sharedb-schema/package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
"z-schema": "^4.2.3"
2020
},
2121
"devDependencies": {
22-
"mocha": "^11.7.5",
23-
"racer": "1.0.1",
24-
"sharedb": "^5.0.0"
22+
"mocha": "^11.7.5"
2523
}
2624
}

packages/sharedb-schema/test/model.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// TODO: Update tests to work with new teamplay api
12
import promisifyRacer from '@startupjs/orm/lib/promisifyRacer.js'
23
import racer from 'racer'
34
import sharedb from 'sharedb'

0 commit comments

Comments
 (0)