Version not found. Please check the version and try again.
@owlmeans/redis 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +517 -0
- package/build/.gitkeep +0 -0
- package/build/consts.d.ts +2 -0
- package/build/consts.d.ts.map +1 -0
- package/build/consts.js +3 -0
- package/build/consts.js.map +1 -0
- package/build/index.d.ts +4 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +3 -0
- package/build/index.js.map +1 -0
- package/build/service.d.ts +9 -0
- package/build/service.d.ts.map +1 -0
- package/build/service.js +64 -0
- package/build/service.js.map +1 -0
- package/build/types.d.ts +6 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/build/utils/cluster.d.ts +5 -0
- package/build/utils/cluster.d.ts.map +1 -0
- package/build/utils/cluster.js +186 -0
- package/build/utils/cluster.js.map +1 -0
- package/build/utils/config.d.ts +9 -0
- package/build/utils/config.d.ts.map +1 -0
- package/build/utils/config.js +31 -0
- package/build/utils/config.js.map +1 -0
- package/build/utils/index.d.ts +4 -0
- package/build/utils/index.d.ts.map +1 -0
- package/build/utils/index.js +4 -0
- package/build/utils/index.js.map +1 -0
- package/build/utils/instance.d.ts +4 -0
- package/build/utils/instance.d.ts.map +1 -0
- package/build/utils/instance.js +13 -0
- package/build/utils/instance.js.map +1 -0
- package/package.json +40 -0
- package/src/consts.ts +3 -0
- package/src/index.ts +4 -0
- package/src/service.ts +94 -0
- package/src/types.ts +6 -0
- package/src/utils/cluster.ts +215 -0
- package/src/utils/config.ts +35 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/instance.ts +16 -0
- package/tsconfig.json +14 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../src/utils/cluster.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAIjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE5C,eAAO,MAAM,aAAa,WAAkB,QAAQ,CAAC,SAAS,CAAC,KAAG,OAAO,CAAC,OAAO,CAuLhF,CAAA"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { Cluster } from 'ioredis';
|
|
2
|
+
import { prepareClusterRedisOptions } from './config.js';
|
|
3
|
+
import { createClient } from './instance.js';
|
|
4
|
+
export const ensuerCluster = async (config) => {
|
|
5
|
+
if (!Array.isArray(config.host)) {
|
|
6
|
+
throw new SyntaxError('We may connect to redis cluster only knowing its nodes');
|
|
7
|
+
}
|
|
8
|
+
const setup = prepareClusterRedisOptions(config);
|
|
9
|
+
// 1. Create single clients for testing
|
|
10
|
+
const clients = await Promise.all(setup.nodes.map(async (node) => {
|
|
11
|
+
if (typeof node !== 'object') {
|
|
12
|
+
throw new SyntaxError('Cluster node must be an object after cluster options initialization');
|
|
13
|
+
}
|
|
14
|
+
if (node.host == null) {
|
|
15
|
+
throw new SyntaxError('Cluster node must have a host property after cluster options initialization');
|
|
16
|
+
}
|
|
17
|
+
const client = await createClient({ ...config, host: node.host });
|
|
18
|
+
return client;
|
|
19
|
+
}));
|
|
20
|
+
// 2. Test clients and ensure they are configured
|
|
21
|
+
try {
|
|
22
|
+
const masters = [];
|
|
23
|
+
const slaves = [];
|
|
24
|
+
const masterQty = config.meta?.masterNumber
|
|
25
|
+
?? Math.round(clients.length / (1 + (config.meta?.slaveNumber ?? 2)));
|
|
26
|
+
const slaveQty = config.meta?.slaveNumber ??
|
|
27
|
+
Math.round((clients.length - masterQty) / masterQty);
|
|
28
|
+
const requiredNodes = (slaveQty + 1) * masterQty;
|
|
29
|
+
if (requiredNodes !== clients.length) {
|
|
30
|
+
throw new SyntaxError(`Number of nodes in redis cluster does not match the configuration requirements: ${clients.length} / ${requiredNodes}`);
|
|
31
|
+
}
|
|
32
|
+
for (const client of clients) {
|
|
33
|
+
let nodesInfo = await client.cluster('NODES');
|
|
34
|
+
let nodes = parseClusterNodeInfo(nodesInfo);
|
|
35
|
+
// Remove nodes that we don't nkow
|
|
36
|
+
for (const node of nodes) {
|
|
37
|
+
// We do not remove ourselves
|
|
38
|
+
if (node.flags.includes('myself')) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (!config.host.includes(node.addr)) {
|
|
42
|
+
await client.cluster('FORGET', node.nodeId);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const otherNodes = nodes.filter(node => !node.flags.includes('myself'));
|
|
46
|
+
// Add nodes that are missing
|
|
47
|
+
for (const host of config.host) {
|
|
48
|
+
if (!otherNodes.some(node => node.addr === host)) {
|
|
49
|
+
await client.cluster('MEET', host, config.port ?? 6379);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
client.disconnect(true);
|
|
53
|
+
nodesInfo = await client.cluster('NODES');
|
|
54
|
+
nodes = parseClusterNodeInfo(nodesInfo);
|
|
55
|
+
const myself = nodes.find(node => node.flags.includes('myself'));
|
|
56
|
+
if (myself == null) {
|
|
57
|
+
throw new SyntaxError('Cluster node does not contain information about itself');
|
|
58
|
+
}
|
|
59
|
+
if (myself.flags.includes('master')) {
|
|
60
|
+
masters.push({ info: myself, node: client });
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
slaves.push({ info: myself, node: client });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
await Promise.all(clients.map(client => client.disconnect(true)));
|
|
67
|
+
const realMasters = masters.filter(master => master.info.slots != null);
|
|
68
|
+
const newcommers = masters.filter(master => master.info.slots == null);
|
|
69
|
+
const slotsChunk = Math.floor(16384 / masterQty);
|
|
70
|
+
const slotsSurplus = 16384 % masterQty;
|
|
71
|
+
const resetNode = async (node, flush = false) => {
|
|
72
|
+
flush && await node.node.flushall();
|
|
73
|
+
await node.node.cluster('RESET');
|
|
74
|
+
node.info.slots = null;
|
|
75
|
+
node.info.master = '-';
|
|
76
|
+
newcommers.push(node);
|
|
77
|
+
};
|
|
78
|
+
const configureMaster = async (node, idx) => {
|
|
79
|
+
const chunk = idx + 1 == masterQty ? slotsChunk + slotsSurplus : slotsChunk;
|
|
80
|
+
const firstSlot = idx * slotsChunk;
|
|
81
|
+
const lastSlot = firstSlot + chunk - 1;
|
|
82
|
+
await node.node.flushall();
|
|
83
|
+
await node.node.cluster('RESET');
|
|
84
|
+
await node.node.cluster('ADDSLOTSRANGE', firstSlot, lastSlot);
|
|
85
|
+
node.info.slots = [[firstSlot, lastSlot]];
|
|
86
|
+
const nodeSlaves = slaves.filter(slave => slave.info.master === node.info.nodeId);
|
|
87
|
+
while (nodeSlaves.length > slaveQty) {
|
|
88
|
+
const slave = nodeSlaves.pop();
|
|
89
|
+
if (slave == null) {
|
|
90
|
+
throw new SyntaxError('Not enough slaves to forget in redis cluster');
|
|
91
|
+
}
|
|
92
|
+
slaves.splice(slaves.indexOf(slave), 1);
|
|
93
|
+
await resetNode(slave);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
if (realMasters.length === 0) {
|
|
97
|
+
for (let i = 0; i < masterQty; ++i) {
|
|
98
|
+
const newcommer = newcommers.shift();
|
|
99
|
+
if (newcommer == null) {
|
|
100
|
+
throw new SyntaxError('(clean) Not enough nodes to add to redis cluster as master');
|
|
101
|
+
}
|
|
102
|
+
await configureMaster(newcommer, i);
|
|
103
|
+
realMasters.push(newcommer);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else if (realMasters.length !== masterQty) {
|
|
107
|
+
while (realMasters.length > masterQty) {
|
|
108
|
+
const renegade = realMasters.pop();
|
|
109
|
+
if (renegade == null) {
|
|
110
|
+
throw new SyntaxError('Not enough nodes to forget in redis cluster');
|
|
111
|
+
}
|
|
112
|
+
const renegadeSlaves = slaves.filter(slave => slave.info.master === renegade.info.nodeId);
|
|
113
|
+
for (const slave of renegadeSlaves) {
|
|
114
|
+
slaves.splice(slaves.indexOf(slave), 1);
|
|
115
|
+
await resetNode(slave);
|
|
116
|
+
}
|
|
117
|
+
await resetNode(renegade, true);
|
|
118
|
+
}
|
|
119
|
+
while (realMasters.length < masterQty) {
|
|
120
|
+
const newcommer = newcommers.shift();
|
|
121
|
+
if (newcommer == null) {
|
|
122
|
+
throw new SyntaxError('(dirty) Not enough nodes to add to redis cluster as master');
|
|
123
|
+
}
|
|
124
|
+
realMasters.push(newcommer);
|
|
125
|
+
}
|
|
126
|
+
for (let i = 0; i < masterQty; ++i) {
|
|
127
|
+
await configureMaster(realMasters[i], i);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (slaves.length !== slaveQty * masterQty) {
|
|
131
|
+
for (let master of realMasters) {
|
|
132
|
+
const masterSlaves = slaves.filter(slave => slave.info.master === master.info.nodeId);
|
|
133
|
+
while (masterSlaves.length > slaveQty) {
|
|
134
|
+
const slave = masterSlaves.pop();
|
|
135
|
+
if (slave == null) {
|
|
136
|
+
throw new SyntaxError('Not enough slaves to forget in redis cluster');
|
|
137
|
+
}
|
|
138
|
+
slaves.splice(slaves.indexOf(slave), 1);
|
|
139
|
+
await resetNode(slave);
|
|
140
|
+
}
|
|
141
|
+
while (masterSlaves.length < slaveQty) {
|
|
142
|
+
const newcommer = newcommers.shift();
|
|
143
|
+
if (newcommer == null) {
|
|
144
|
+
throw new SyntaxError('Not enough slaves to add to redis cluster');
|
|
145
|
+
}
|
|
146
|
+
newcommer.info.master = master.info.nodeId;
|
|
147
|
+
await newcommer.node.cluster('REPLICATE', master.info.nodeId);
|
|
148
|
+
masterSlaves.push(newcommer);
|
|
149
|
+
slaves.push(newcommer);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (newcommers.length !== 0) {
|
|
154
|
+
throw new SyntaxError('There are nodes that are not configured in redis cluster');
|
|
155
|
+
}
|
|
156
|
+
if (realMasters.length !== masterQty) {
|
|
157
|
+
throw new SyntaxError('Not enough master nodes in redis cluster after configuration');
|
|
158
|
+
}
|
|
159
|
+
if (slaves.length !== slaveQty * masterQty) {
|
|
160
|
+
throw new SyntaxError('Not enough slave nodes in redis cluster after configuration');
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch (e) {
|
|
164
|
+
console.error(e);
|
|
165
|
+
throw e;
|
|
166
|
+
}
|
|
167
|
+
// 3. Disconnect single clients
|
|
168
|
+
await Promise.all(clients.map(client => client.disconnect()));
|
|
169
|
+
// 4. Connect to cluster
|
|
170
|
+
return new Cluster(setup.nodes, setup.options);
|
|
171
|
+
};
|
|
172
|
+
const parseClusterNodeInfo = (clusterNodes) => {
|
|
173
|
+
const nodesInfo = clusterNodes.split('\n').filter(line => line.trim() !== '');
|
|
174
|
+
return nodesInfo.map(line => {
|
|
175
|
+
const [nodeId, addr, flags, master, , , , state, ...slots] = line.split(' ');
|
|
176
|
+
return {
|
|
177
|
+
nodeId,
|
|
178
|
+
addr: addr.trim().split(':')[0],
|
|
179
|
+
flags: flags.trim().split(','),
|
|
180
|
+
master,
|
|
181
|
+
state,
|
|
182
|
+
slots: slots != null && slots.length > 0 ? slots.map(slot => (slot.includes('-') ? slot.split('-', 2) : [slot, slot]).map(v => parseInt(v))) : null
|
|
183
|
+
};
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
//# sourceMappingURL=cluster.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster.js","sourceRoot":"","sources":["../../src/utils/cluster.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DbConfig } from '@owlmeans/resource';
|
|
2
|
+
import type { RedisOptions, ClusterNode, ClusterOptions } from 'ioredis';
|
|
3
|
+
import type { RedisMeta } from '../types.js';
|
|
4
|
+
export declare const prepareSingleRedisOptions: (config: DbConfig<RedisMeta>, host?: string) => RedisOptions;
|
|
5
|
+
export declare const prepareClusterRedisOptions: (config: DbConfig<RedisMeta>) => {
|
|
6
|
+
nodes: ClusterNode[];
|
|
7
|
+
options: ClusterOptions;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE5C,eAAO,MAAM,yBAAyB,WAAY,QAAQ,CAAC,SAAS,CAAC,SAAS,MAAM,KAAG,YAWtF,CAAA;AAED,eAAO,MAAM,0BAA0B,WAAY,QAAQ,CAAC,SAAS,CAAC,KAAG;IAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAiBvH,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export const prepareSingleRedisOptions = (config, host) => {
|
|
2
|
+
host = (host != null ? host : config.host);
|
|
3
|
+
if (typeof host !== 'string') {
|
|
4
|
+
throw new SyntaxError('Single redis options can be created only from config referencing single host');
|
|
5
|
+
}
|
|
6
|
+
return {
|
|
7
|
+
host: host,
|
|
8
|
+
port: config.port ?? 6379,
|
|
9
|
+
password: config.secret,
|
|
10
|
+
...config.meta
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export const prepareClusterRedisOptions = (config) => {
|
|
14
|
+
if (!Array.isArray(config.host)) {
|
|
15
|
+
throw new SyntaxError('Cluster redis options can be created only from config referencing multiple hosts');
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
nodes: config.host.map(host => ({ host, port: config.port })), options: {
|
|
19
|
+
dnsLookup: (address, callback) => {
|
|
20
|
+
callback(null, address);
|
|
21
|
+
},
|
|
22
|
+
slotsRefreshTimeout: 20000,
|
|
23
|
+
redisOptions: {
|
|
24
|
+
// tls: { rejectUnauthorized: false }, // @TODO check if it's working
|
|
25
|
+
password: config.secret,
|
|
26
|
+
...config.meta
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,MAA2B,EAAE,IAAa,EAAgB,EAAE;IACpG,IAAI,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAW,CAAA;IACpD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,WAAW,CAAC,8EAA8E,CAAC,CAAA;IACvG,CAAC;IACD,OAAO;QACL,IAAI,EAAE,IAAI;QACV,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI;QACzB,QAAQ,EAAE,MAAM,CAAC,MAAM;QACvB,GAAG,MAAM,CAAC,IAAI;KACf,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,MAA2B,EAAqD,EAAE;IAC3H,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,WAAW,CAAC,kFAAkF,CAAC,CAAA;IAC3G,CAAC;IACD,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE;YACtE,SAAS,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE;gBAC/B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YACzB,CAAC;YACD,mBAAmB,EAAE,KAAK;YAC1B,YAAY,EAAE;gBACZ,qEAAqE;gBACrE,QAAQ,EAAE,MAAM,CAAC,MAAM;gBACvB,GAAG,MAAM,CAAC,IAAI;aACf;SACF;KACF,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../../src/utils/instance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAK3D,eAAO,MAAM,YAAY,WAAkB,QAAQ,KAAG,OAAO,CAAC,WAAW,CASxE,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Redis } from 'ioredis';
|
|
2
|
+
import { prepareSingleRedisOptions } from './config.js';
|
|
3
|
+
import { ensuerCluster } from './cluster.js';
|
|
4
|
+
export const createClient = async (config) => {
|
|
5
|
+
if (Array.isArray(config.host) && config.host.length === 1) {
|
|
6
|
+
config.host = config.host[0];
|
|
7
|
+
}
|
|
8
|
+
if (typeof config.host === 'string') {
|
|
9
|
+
return new Redis(prepareSingleRedisOptions(config));
|
|
10
|
+
}
|
|
11
|
+
return await ensuerCluster(config);
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=instance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance.js","sourceRoot":"","sources":["../../src/utils/instance.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,KAAK,EAAC,MAAM,SAAS,CAAA;AAC7B,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAE5C,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAAE,MAAgB,EAAwB,EAAE;IAC3E,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3D,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC9B,CAAC;IACD,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO,IAAI,KAAK,CAAC,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAA;IACrD,CAAC;IAED,OAAO,MAAM,aAAa,CAAC,MAAM,CAAC,CAAA;AACpC,CAAC,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@owlmeans/redis",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "tsc -b",
|
|
7
|
+
"dev": "sleep 240 && nodemon -e ts,tsx,json --watch src --exec \"tsc -p ./tsconfig.json\"",
|
|
8
|
+
"watch": "tsc -b -w --preserveWatchOutput --pretty"
|
|
9
|
+
},
|
|
10
|
+
"main": "build/index.js",
|
|
11
|
+
"module": "build/index.js",
|
|
12
|
+
"types": "build/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./build/index.js",
|
|
16
|
+
"require": "./build/index.js",
|
|
17
|
+
"default": "./build/index.js",
|
|
18
|
+
"module": "./build/index.js",
|
|
19
|
+
"types": "./build/index.d.ts"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^22.7.8",
|
|
24
|
+
"nodemon": "^3.1.7",
|
|
25
|
+
"typescript": "^5.6.3"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@noble/hashes": "^1.5.0",
|
|
29
|
+
"@owlmeans/context": "^0.1.0",
|
|
30
|
+
"@owlmeans/redis-resource": "^0.1.0",
|
|
31
|
+
"@owlmeans/resource": "^0.1.0",
|
|
32
|
+
"@owlmeans/server-context": "^0.1.0",
|
|
33
|
+
"@scure/base": "^1.1.9",
|
|
34
|
+
"ioredis": "^5.4.1"
|
|
35
|
+
},
|
|
36
|
+
"private": false,
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
}
|
|
40
|
+
}
|
package/src/consts.ts
ADDED
package/src/index.ts
ADDED
package/src/service.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { RedisDbService, RedisClient, RedisDb } from '@owlmeans/redis-resource'
|
|
2
|
+
import { DEFAULT_ALIAS } from './consts.js'
|
|
3
|
+
import { createDbService } from '@owlmeans/resource'
|
|
4
|
+
import { assertContext, Layer } from '@owlmeans/context'
|
|
5
|
+
import type { BasicContext } from '@owlmeans/context'
|
|
6
|
+
import type { ServerContext, ServerConfig } from '@owlmeans/server-context'
|
|
7
|
+
import { createClient } from './utils/index.js'
|
|
8
|
+
|
|
9
|
+
type Config = ServerConfig
|
|
10
|
+
interface Context<C extends Config = Config> extends ServerContext<C> { }
|
|
11
|
+
|
|
12
|
+
export const makeRedisService = (alias: string = DEFAULT_ALIAS): RedisDbService => {
|
|
13
|
+
const location = `redis:${alias}`
|
|
14
|
+
|
|
15
|
+
const service: RedisDbService = createDbService<RedisDb, RedisClient, RedisDbService>(
|
|
16
|
+
alias, {
|
|
17
|
+
db: async configAlias => {
|
|
18
|
+
const client = await service.client(configAlias)
|
|
19
|
+
|
|
20
|
+
const name = await service.name(configAlias)
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @TODO we need to think how we can reuse the initail
|
|
24
|
+
* one instead of duplication for some cases
|
|
25
|
+
*/
|
|
26
|
+
return { client: client.duplicate(), prefix: name }
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
initialize: async configAlias => {
|
|
30
|
+
configAlias = service.ensureConfigAlias(configAlias)
|
|
31
|
+
const config = service.config(configAlias)
|
|
32
|
+
|
|
33
|
+
if (service.clients[configAlias] != null) {
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (service.layers == null) {
|
|
38
|
+
service.layers = [Layer.Global]
|
|
39
|
+
}
|
|
40
|
+
if (config.serviceSensitive && service.layers.includes(Layer.Service)) {
|
|
41
|
+
service.layers.push(Layer.Service)
|
|
42
|
+
}
|
|
43
|
+
if (config.entitySensitive && service.layers.includes(Layer.Entity)) {
|
|
44
|
+
service.layers.push(Layer.Entity)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let client = await createClient(config)
|
|
48
|
+
|
|
49
|
+
// we need to check all hosts for replication consistancy
|
|
50
|
+
|
|
51
|
+
if (service.clients[configAlias] != null) {
|
|
52
|
+
throw new SyntaxError(`Cannot replace existing redis client: ${configAlias} - ${service.alias}`)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
process.on('SIGTERM', () => {
|
|
56
|
+
client.quit()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
service.clients[configAlias] = client
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
reinitializeContext: <T>(context: BasicContext<ServerConfig>) => {
|
|
63
|
+
const _service = makeRedisService(alias)
|
|
64
|
+
|
|
65
|
+
_service.ctx = context
|
|
66
|
+
|
|
67
|
+
_service.layers = service.layers
|
|
68
|
+
|
|
69
|
+
return _service as T
|
|
70
|
+
}
|
|
71
|
+
}, service => async () => {
|
|
72
|
+
const context = assertContext<Config, Context>(service.ctx as Context, location)
|
|
73
|
+
|
|
74
|
+
// Try to initialize all connections
|
|
75
|
+
await context.cfg.dbs?.filter(dbConfig => dbConfig.service === alias).reduce(async (prev, dbConfig) => {
|
|
76
|
+
await prev
|
|
77
|
+
await service.config(dbConfig.alias)
|
|
78
|
+
}, Promise.resolve())
|
|
79
|
+
|
|
80
|
+
service.initialized = true
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
return service
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export const appendRedis = <C extends Config, T extends Context<C> = Context<C>>(
|
|
87
|
+
context: T, alias: string = DEFAULT_ALIAS
|
|
88
|
+
): T => {
|
|
89
|
+
const service = makeRedisService(alias)
|
|
90
|
+
|
|
91
|
+
context.registerService(service)
|
|
92
|
+
|
|
93
|
+
return context
|
|
94
|
+
}
|