mm_redis 2.1.7 → 2.3.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/example/index.js +40 -0
- package/index.js +12 -4112
- package/lib/redis.js +4085 -0
- package/lib/tools/index.js +16 -0
- package/lib/tools/push_queue/index.js +115 -0
- package/lib/tools/queue/index.js +395 -0
- package/lib/tools/redis/index.js +57 -0
- package/lib/tools/redis_lock/index.js +210 -0
- package/package.json +49 -39
- package/test.js +14 -1
- package/tool/push_queue/index.js +7 -0
- package/tool/push_queue/tool.json +56 -0
- package/tool/queue/index.js +7 -0
- package/tool/queue/tool.json +129 -0
- package/tool/redis/index.js +7 -0
- package/tool/redis/tool.json +133 -0
- package/tool/redis_lock/index.js +7 -0
- package/tool/redis_lock/tool.json +91 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redis 分布式锁管理器
|
|
3
|
+
* 基于 Redis SET NX + TTL,使用 WATCH/MULTI/EXEC 实现原子释放和续期
|
|
4
|
+
* 防止锁过期后被误删:每次获取锁生成唯一 uuid,释放时验证 uuid 匹配
|
|
5
|
+
* 依赖: redis (v4+,与 mm_redis 共用同一个底层库)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 生成唯一锁标识
|
|
10
|
+
* @returns {string} 唯一锁值
|
|
11
|
+
*/
|
|
12
|
+
function _genLockValue() {
|
|
13
|
+
return Date.now().toString(36) + '-' + Math.random().toString(36).substr(2, 9);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 获取 Redis 客户端(复用 mm_redis 连接池,不可用时自建独立连接)
|
|
18
|
+
* @param {object} opts 配置选项
|
|
19
|
+
* @returns {object} { client, release } 或 null
|
|
20
|
+
*/
|
|
21
|
+
async function _getClient(opts) {
|
|
22
|
+
var redis_admin = null;
|
|
23
|
+
try {
|
|
24
|
+
var { redisAdmin } = require('mm_redis');
|
|
25
|
+
if (redisAdmin) {
|
|
26
|
+
redis_admin = redisAdmin('os', opts);
|
|
27
|
+
}
|
|
28
|
+
} catch (e) {
|
|
29
|
+
// mm_redis 不可用时使用传入的 opts
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// 优先复用 mm_redis 连接池,保证配置一致且不新建独立连接
|
|
33
|
+
if (redis_admin && typeof redis_admin._getConnection === 'function') {
|
|
34
|
+
var conn = await redis_admin._getConnection();
|
|
35
|
+
return {
|
|
36
|
+
client: conn,
|
|
37
|
+
release: function () {
|
|
38
|
+
try {
|
|
39
|
+
redis_admin._releaseConnection(conn);
|
|
40
|
+
} catch (e) {
|
|
41
|
+
void e;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 回退: mm_redis 不可用,自建独立连接
|
|
48
|
+
var redis_mod = require('redis');
|
|
49
|
+
if (!redis_mod || !redis_mod.createClient) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
var createClient = redis_mod.createClient;
|
|
53
|
+
var client = createClient({
|
|
54
|
+
socket: {
|
|
55
|
+
host: opts.host || 'localhost',
|
|
56
|
+
port: opts.port || 6379,
|
|
57
|
+
connectTimeout: 5000
|
|
58
|
+
},
|
|
59
|
+
password: opts.password || '',
|
|
60
|
+
database: opts.db || 0
|
|
61
|
+
});
|
|
62
|
+
await client.connect();
|
|
63
|
+
return {
|
|
64
|
+
client: client,
|
|
65
|
+
release: function () {
|
|
66
|
+
try {
|
|
67
|
+
client.quit();
|
|
68
|
+
} catch (e) {
|
|
69
|
+
void e;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 获取分布式锁
|
|
77
|
+
* @param {object} client Redis 客户端
|
|
78
|
+
* @param {string} lock_key 锁键名
|
|
79
|
+
* @param {number} ttl 锁过期时间(秒)
|
|
80
|
+
* @returns {object} 获取结果
|
|
81
|
+
*/
|
|
82
|
+
async function _acquire(client, lock_key, ttl) {
|
|
83
|
+
var lock_value = _genLockValue();
|
|
84
|
+
var ttl_sec = ttl || 30;
|
|
85
|
+
var result = await client.set(lock_key, lock_value, { EX: ttl_sec, NX: true });
|
|
86
|
+
if (result === 'OK') {
|
|
87
|
+
return { acquired: true, lock_key: lock_key, lock_value: lock_value, ttl: ttl_sec };
|
|
88
|
+
}
|
|
89
|
+
return { acquired: false, lock_key: lock_key, msg: '锁已被占用' };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* 释放分布式锁(WATCH/MULTI/EXEC 原子操作)
|
|
94
|
+
* 原理: WATCH 监控键 → 验证持有者 → MULTI 事务删除 → EXEC 提交
|
|
95
|
+
* 如果 EXEC 返回 null 说明 WATCH 期间键被修改(锁已被他人持有或过期后重新获取),放弃删除
|
|
96
|
+
* @param {object} client Redis 客户端
|
|
97
|
+
* @param {string} lock_key 锁键名
|
|
98
|
+
* @param {string} lock_value 锁值(需与获取时一致)
|
|
99
|
+
* @returns {object} 释放结果
|
|
100
|
+
*/
|
|
101
|
+
async function _release(client, lock_key, lock_value) {
|
|
102
|
+
if (!lock_value) {
|
|
103
|
+
return { released: false, msg: '缺少 lock_value,无法安全释放锁' };
|
|
104
|
+
}
|
|
105
|
+
await client.watch(lock_key);
|
|
106
|
+
var current = await client.get(lock_key);
|
|
107
|
+
if (current !== lock_value) {
|
|
108
|
+
await client.unwatch();
|
|
109
|
+
return { released: false, lock_key: lock_key, msg: '锁已被他人持有或已过期' };
|
|
110
|
+
}
|
|
111
|
+
var exec_result = await client.multi().del(lock_key).exec();
|
|
112
|
+
if (exec_result === null) {
|
|
113
|
+
return { released: false, lock_key: lock_key, msg: '锁在释放过程中被修改,放弃删除' };
|
|
114
|
+
}
|
|
115
|
+
return { released: true, lock_key: lock_key };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* 锁续期(WATCH/MULTI/EXEC 原子操作)
|
|
120
|
+
* 原理: 同释放,将 DEL 替换为 EXPIRE
|
|
121
|
+
* @param {object} client Redis 客户端
|
|
122
|
+
* @param {string} lock_key 锁键名
|
|
123
|
+
* @param {string} lock_value 锁值(需与获取时一致)
|
|
124
|
+
* @param {number} ttl 续期时间(秒)
|
|
125
|
+
* @returns {object} 续期结果
|
|
126
|
+
*/
|
|
127
|
+
async function _renew(client, lock_key, lock_value, ttl) {
|
|
128
|
+
if (!lock_value) {
|
|
129
|
+
return { renewed: false, msg: '缺少 lock_value,无法续期' };
|
|
130
|
+
}
|
|
131
|
+
var ttl_sec = ttl || 30;
|
|
132
|
+
await client.watch(lock_key);
|
|
133
|
+
var current = await client.get(lock_key);
|
|
134
|
+
if (current !== lock_value) {
|
|
135
|
+
await client.unwatch();
|
|
136
|
+
return { renewed: false, lock_key: lock_key, msg: '锁已被他人持有或已过期' };
|
|
137
|
+
}
|
|
138
|
+
var exec_result = await client.multi().expire(lock_key, ttl_sec).exec();
|
|
139
|
+
if (exec_result === null) {
|
|
140
|
+
return { renewed: false, lock_key: lock_key, msg: '锁在续期过程中被修改' };
|
|
141
|
+
}
|
|
142
|
+
return { renewed: true, lock_key: lock_key, ttl: ttl_sec };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* 主函数
|
|
147
|
+
* @param {object} ctx 上下文
|
|
148
|
+
* @param {object} params 参数
|
|
149
|
+
* @returns {object} 执行结果
|
|
150
|
+
*/
|
|
151
|
+
async function main(params, ctx, options) {
|
|
152
|
+
var opts = (this && typeof this.getOptions === 'function') ? this.getOptions() : {};
|
|
153
|
+
|
|
154
|
+
var holder;
|
|
155
|
+
try {
|
|
156
|
+
holder = await _getClient(opts);
|
|
157
|
+
} catch (e) {
|
|
158
|
+
ctx.output = {
|
|
159
|
+
error: {
|
|
160
|
+
code: 'LOCK_CONNECT_FAIL',
|
|
161
|
+
message: 'Redis 连接失败: ' + e.message
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
return ctx.output;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (!holder || !holder.client) {
|
|
168
|
+
ctx.output = {
|
|
169
|
+
error: {
|
|
170
|
+
code: 'LOCK_MISSING_DEP',
|
|
171
|
+
message: '分布式锁需要 redis 库,请手动执行: npm install redis'
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
return ctx.output;
|
|
175
|
+
}
|
|
176
|
+
var client = holder.client;
|
|
177
|
+
|
|
178
|
+
var action = params.action || '';
|
|
179
|
+
var lock_key = params.lock_key || '';
|
|
180
|
+
|
|
181
|
+
if (!lock_key) {
|
|
182
|
+
ctx.output = { error: { code: 'LOCK_NO_KEY', message: '锁键名 lock_key 不能为空' } };
|
|
183
|
+
await holder.release();
|
|
184
|
+
return ctx.output;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
switch (action) {
|
|
189
|
+
case 'acquire':
|
|
190
|
+
ctx.output = await _acquire(client, lock_key, params.ttl);
|
|
191
|
+
break;
|
|
192
|
+
case 'release':
|
|
193
|
+
ctx.output = await _release(client, lock_key, params.lock_value);
|
|
194
|
+
break;
|
|
195
|
+
case 'renew':
|
|
196
|
+
ctx.output = await _renew(client, lock_key, params.lock_value, params.ttl);
|
|
197
|
+
break;
|
|
198
|
+
default:
|
|
199
|
+
ctx.output = {
|
|
200
|
+
error: { code: 'LOCK_UNKNOWN_ACTION', message: '不支持的操作: ' + action + ',支持: acquire/release/renew' }
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
} finally {
|
|
204
|
+
await holder.release();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return ctx.output;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
module.exports = { main };
|
package/package.json
CHANGED
|
@@ -1,41 +1,51 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
2
|
+
"name": "mm_redis",
|
|
3
|
+
"version": "2.3.0",
|
|
4
|
+
"description": "高效的Redis客户端封装库,提供连接池管理、数据类型操作、错误处理和批量操作优化",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "node test.js",
|
|
8
|
+
"dev": "nodemon test.js"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://gitee.com/qiuwenwu91/mm_redis.git"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"mm_mod",
|
|
16
|
+
"mm_adapter",
|
|
17
|
+
"mm_redis",
|
|
18
|
+
"redis",
|
|
19
|
+
"cache",
|
|
20
|
+
"client",
|
|
21
|
+
"connection-pool",
|
|
22
|
+
"pipeline",
|
|
23
|
+
"hash",
|
|
24
|
+
"set",
|
|
25
|
+
"sorted-set",
|
|
26
|
+
"list",
|
|
27
|
+
"redis-client",
|
|
28
|
+
"nodejs"
|
|
29
|
+
],
|
|
30
|
+
"layer": "infrastructure",
|
|
31
|
+
"group": "cache",
|
|
32
|
+
"author": "qww",
|
|
33
|
+
"license": "ISC",
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://gitee.com/qiuwenwu91/mm_redis/issues"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://www.npmjs.com/package/mm_redis",
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"mm_admin": "^1.1.0",
|
|
40
|
+
"mm_eslint": "^1.0.0",
|
|
41
|
+
"mm_helper": "^1.0.0",
|
|
42
|
+
"mm_mod": "^1.0.1",
|
|
43
|
+
"redis": "^6.2.1"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=14.0.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"mm_eslint": "^1.7.7"
|
|
50
|
+
}
|
|
41
51
|
}
|
package/test.js
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
|
+
// 独立运行时补充全局 $ 对象(mm_os 宿主环境已提供,npm 包测试需自备)
|
|
2
|
+
if (!global.$) {
|
|
3
|
+
global.$ = {
|
|
4
|
+
log: {
|
|
5
|
+
debug: console.debug ? console.debug.bind(console) : console.log.bind(console),
|
|
6
|
+
info: console.info ? console.info.bind(console) : console.log.bind(console),
|
|
7
|
+
warn: console.warn ? console.warn.bind(console) : console.log.bind(console),
|
|
8
|
+
error: console.error ? console.error.bind(console) : console.log.bind(console),
|
|
9
|
+
success: console.log.bind(console)
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
1
14
|
const { redisAdmin } = require('./index.js');
|
|
2
15
|
|
|
3
16
|
async function test() {
|
|
4
17
|
try {
|
|
5
18
|
var bl, num, arr = [];
|
|
6
19
|
var config = './config.json'.loadJson(__dirname);
|
|
7
|
-
var rs = redisAdmin('
|
|
20
|
+
var rs = redisAdmin('os', config);
|
|
8
21
|
await rs.open();
|
|
9
22
|
|
|
10
23
|
// 清理之前的测试数据
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "push_queue",
|
|
3
|
+
"handler": "sender",
|
|
4
|
+
"title": "队列发信器",
|
|
5
|
+
"description": "将消息写入 Redis 消息队列(lPush)。适用场景:需要异步解耦、削峰填谷或与消费端对接时。工作流提示:queue_name 必填队列名称,data 填消息数据(会 JSON 序列化),返回 sent 与 message 确认入队结果。",
|
|
6
|
+
"type": "gateway",
|
|
7
|
+
"params": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"properties": {
|
|
10
|
+
"queue_name": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "队列名称"
|
|
13
|
+
},
|
|
14
|
+
"data": {
|
|
15
|
+
"description": "消息数据"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"required": [
|
|
19
|
+
"queue_name",
|
|
20
|
+
"data"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"returns": {
|
|
24
|
+
"description": "返回队列发信结果,正常时包含队列名称与消息数据,异常时包含错误码与错误信息",
|
|
25
|
+
"type": "object",
|
|
26
|
+
"properties": {
|
|
27
|
+
"sent": {
|
|
28
|
+
"type": "boolean",
|
|
29
|
+
"description": "是否入队成功"
|
|
30
|
+
},
|
|
31
|
+
"tip": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"description": "提示信息"
|
|
34
|
+
},
|
|
35
|
+
"message": {
|
|
36
|
+
"description": "消息数据"
|
|
37
|
+
},
|
|
38
|
+
"error": {
|
|
39
|
+
"type": "object",
|
|
40
|
+
"description": "错误信息,仅调用出错时返回",
|
|
41
|
+
"properties": {
|
|
42
|
+
"code": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"description": "错误码"
|
|
45
|
+
},
|
|
46
|
+
"message": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"description": "错误描述"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"options": {},
|
|
55
|
+
"group": "transport"
|
|
56
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "queue",
|
|
3
|
+
"handler": "manager",
|
|
4
|
+
"title": "消息队列管理器",
|
|
5
|
+
"description": "消息队列发布、消费、确认、重试、死信。适用场景:异步解耦、可靠传递。工作流提示:action 与 queue_name 必填,publish/delay 配 message,消费后 _raw 做 ack/retry,死信 dlq 配 dlq_action,结果在 obj/list、ID 在 message_id。",
|
|
6
|
+
"type": "data",
|
|
7
|
+
"params": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"properties": {
|
|
10
|
+
"action": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "操作类型: publish/consume/batch_consume/ack/retry/dlq/delay/delay_poll/status",
|
|
13
|
+
"enum": [
|
|
14
|
+
"publish",
|
|
15
|
+
"consume",
|
|
16
|
+
"batch_consume",
|
|
17
|
+
"ack",
|
|
18
|
+
"retry",
|
|
19
|
+
"dlq",
|
|
20
|
+
"delay",
|
|
21
|
+
"delay_poll",
|
|
22
|
+
"status"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"queue_name": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"description": "队列名称"
|
|
28
|
+
},
|
|
29
|
+
"message": {
|
|
30
|
+
"description": "消息内容(publish/delay时必填)"
|
|
31
|
+
},
|
|
32
|
+
"count": {
|
|
33
|
+
"type": "number",
|
|
34
|
+
"description": "批量消费数量(batch_consume时使用,默认10)"
|
|
35
|
+
},
|
|
36
|
+
"_raw": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"description": "消费时返回的原始消息字符串(ack/retry时必填)"
|
|
39
|
+
},
|
|
40
|
+
"max_retries": {
|
|
41
|
+
"type": "number",
|
|
42
|
+
"description": "最大重试次数(retry时使用,默认3)"
|
|
43
|
+
},
|
|
44
|
+
"dlq_action": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"description": "死信操作: view/replay/clear (dlq时使用)",
|
|
47
|
+
"enum": [
|
|
48
|
+
"view",
|
|
49
|
+
"replay",
|
|
50
|
+
"clear"
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
"delay_seconds": {
|
|
54
|
+
"type": "number",
|
|
55
|
+
"description": "延迟秒数(delay时使用,必须>0)"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"required": [
|
|
59
|
+
"action",
|
|
60
|
+
"queue_name"
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
"returns": {
|
|
64
|
+
"description": "管理操作结果,读操作返回 obj/list,写操作返回 msg/message_id/queue,异常时返回 error",
|
|
65
|
+
"type": "object",
|
|
66
|
+
"properties": {
|
|
67
|
+
"obj": {
|
|
68
|
+
"description": "消费的消息内容或状态"
|
|
69
|
+
},
|
|
70
|
+
"list": {
|
|
71
|
+
"type": "array",
|
|
72
|
+
"description": "批量消费的消息列表"
|
|
73
|
+
},
|
|
74
|
+
"msg": {
|
|
75
|
+
"type": "string",
|
|
76
|
+
"description": "操作结果描述"
|
|
77
|
+
},
|
|
78
|
+
"message_id": {
|
|
79
|
+
"type": "string",
|
|
80
|
+
"description": "消息ID"
|
|
81
|
+
},
|
|
82
|
+
"queue": {
|
|
83
|
+
"type": "string",
|
|
84
|
+
"description": "队列名称"
|
|
85
|
+
},
|
|
86
|
+
"count": {
|
|
87
|
+
"type": "number",
|
|
88
|
+
"description": "操作影响的消息数量"
|
|
89
|
+
},
|
|
90
|
+
"retry_count": {
|
|
91
|
+
"type": "number",
|
|
92
|
+
"description": "当前重试次数"
|
|
93
|
+
},
|
|
94
|
+
"delay_seconds": {
|
|
95
|
+
"type": "number",
|
|
96
|
+
"description": "延迟秒数"
|
|
97
|
+
},
|
|
98
|
+
"exec_at": {
|
|
99
|
+
"type": "string",
|
|
100
|
+
"description": "延迟消息执行时间"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"options": {
|
|
105
|
+
"driver": {
|
|
106
|
+
"type": "string",
|
|
107
|
+
"description": "队列驱动: redis",
|
|
108
|
+
"default": "redis"
|
|
109
|
+
},
|
|
110
|
+
"host": {
|
|
111
|
+
"type": "string",
|
|
112
|
+
"description": "队列服务主机",
|
|
113
|
+
"default": "localhost"
|
|
114
|
+
},
|
|
115
|
+
"port": {
|
|
116
|
+
"type": "number",
|
|
117
|
+
"description": "队列服务端口"
|
|
118
|
+
},
|
|
119
|
+
"password": {
|
|
120
|
+
"type": "string",
|
|
121
|
+
"description": "队列服务密码"
|
|
122
|
+
},
|
|
123
|
+
"db": {
|
|
124
|
+
"type": "number",
|
|
125
|
+
"description": "Redis 数据库编号"
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
"group": "system"
|
|
129
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "redis",
|
|
3
|
+
"handler": "manager",
|
|
4
|
+
"title": "Redis管理器",
|
|
5
|
+
"description": "管理 Redis 缓存,覆盖键值、哈希、列表、集合、有序集合、发布订阅。适用场景:缓存数据、计数器、分布式协作或消息订阅时。工作流提示:action 与 key 必填,字符串配 value/ttl,哈希配 field/body,集合/有序集合/pub/sub 有专属 action,返回随操作而定。",
|
|
6
|
+
"type": "data",
|
|
7
|
+
"params": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"properties": {
|
|
10
|
+
"action": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "操作类型",
|
|
13
|
+
"enum": [
|
|
14
|
+
"get",
|
|
15
|
+
"set",
|
|
16
|
+
"del",
|
|
17
|
+
"has",
|
|
18
|
+
"exists",
|
|
19
|
+
"add",
|
|
20
|
+
"getset",
|
|
21
|
+
"expire",
|
|
22
|
+
"pexpire",
|
|
23
|
+
"persist",
|
|
24
|
+
"ttl",
|
|
25
|
+
"incr",
|
|
26
|
+
"decr",
|
|
27
|
+
"incrby",
|
|
28
|
+
"decrby",
|
|
29
|
+
"incrbyfloat",
|
|
30
|
+
"keys",
|
|
31
|
+
"clear",
|
|
32
|
+
"clearExpire",
|
|
33
|
+
"dbsize",
|
|
34
|
+
"flushdb",
|
|
35
|
+
"isConnected",
|
|
36
|
+
"mget",
|
|
37
|
+
"mset",
|
|
38
|
+
"msetObj",
|
|
39
|
+
"strlen",
|
|
40
|
+
"append",
|
|
41
|
+
"setrange",
|
|
42
|
+
"hget",
|
|
43
|
+
"hset",
|
|
44
|
+
"hgetall",
|
|
45
|
+
"hkeys",
|
|
46
|
+
"hvals",
|
|
47
|
+
"hlen",
|
|
48
|
+
"hdel",
|
|
49
|
+
"hmset",
|
|
50
|
+
"hmget",
|
|
51
|
+
"hexists",
|
|
52
|
+
"hsetObj",
|
|
53
|
+
"setForList",
|
|
54
|
+
"addForList",
|
|
55
|
+
"getForList",
|
|
56
|
+
"clearForList",
|
|
57
|
+
"hasForList",
|
|
58
|
+
"sadd",
|
|
59
|
+
"srem",
|
|
60
|
+
"sismember",
|
|
61
|
+
"smembers",
|
|
62
|
+
"scard",
|
|
63
|
+
"sinter",
|
|
64
|
+
"sunion",
|
|
65
|
+
"sdiff",
|
|
66
|
+
"zadd",
|
|
67
|
+
"zrem",
|
|
68
|
+
"zscore",
|
|
69
|
+
"zrank",
|
|
70
|
+
"zrevrank",
|
|
71
|
+
"zincrby",
|
|
72
|
+
"zcard",
|
|
73
|
+
"zcount",
|
|
74
|
+
"zrevrange",
|
|
75
|
+
"publish",
|
|
76
|
+
"unsubscribe"
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
"key": {
|
|
80
|
+
"type": "string",
|
|
81
|
+
"description": "缓存键"
|
|
82
|
+
},
|
|
83
|
+
"value": {
|
|
84
|
+
"description": "缓存值/增量值/成员等"
|
|
85
|
+
},
|
|
86
|
+
"ttl": {
|
|
87
|
+
"type": "number",
|
|
88
|
+
"description": "过期时间(秒)",
|
|
89
|
+
"min": 0,
|
|
90
|
+
"max": 31536000
|
|
91
|
+
},
|
|
92
|
+
"field": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"description": "哈希字段名/有序集合成员名(哈希和有序集合操作)"
|
|
95
|
+
},
|
|
96
|
+
"body": {
|
|
97
|
+
"type": "object",
|
|
98
|
+
"description": "批量数据对象(hsetObj/msetObj 操作)"
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"required": [
|
|
102
|
+
"action",
|
|
103
|
+
"key"
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
"returns": {
|
|
107
|
+
"description": "管理操作结果,返回值类型根据操作而定",
|
|
108
|
+
"type": "object"
|
|
109
|
+
},
|
|
110
|
+
"options": {
|
|
111
|
+
"host": {
|
|
112
|
+
"type": "string",
|
|
113
|
+
"description": "Redis主机地址",
|
|
114
|
+
"default": "127.0.0.1"
|
|
115
|
+
},
|
|
116
|
+
"port": {
|
|
117
|
+
"type": "number",
|
|
118
|
+
"description": "Redis端口",
|
|
119
|
+
"default": 6379
|
|
120
|
+
},
|
|
121
|
+
"password": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"description": "Redis密码",
|
|
124
|
+
"default": "asd159357"
|
|
125
|
+
},
|
|
126
|
+
"db": {
|
|
127
|
+
"type": "number",
|
|
128
|
+
"description": "数据库编号",
|
|
129
|
+
"default": 0
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
"group": "storage"
|
|
133
|
+
}
|