bonsaif 1.10.33 → 1.10.34

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.
Files changed (2) hide show
  1. package/lib/hookup/redis.js +140 -29
  2. package/package.json +1 -1
@@ -14,41 +14,103 @@ const scan=async(options,db, cursor, pattern, count)=>{ // SCAN cursor [MATCH p
14
14
  const redisConn = await exec.redisConn(options);
15
15
  const start = Date.now();
16
16
 
17
- cursor = cursor!=null ? cursor : '0';
17
+ cursor = cursor!=null ? String(cursor) : '0';
18
18
  pattern = pattern!=null ? pattern : '*';
19
- count = count!=null ? count : 100;
19
+ count = count!=null ? parseInt(count) : 100;
20
20
 
21
21
  return new Promise((resolve, reject)=>{
22
22
  try{
23
- redisConn.select(db,function() { /* ... */ });
24
-
25
- // SCAN necesita los argumentos expandidos, no como array
26
- redisConn.scan(cursor, 'MATCH', pattern, 'COUNT', count, function (err, res) {
27
- if (err) {
28
- reject(err);
23
+ // Esperar a que se seleccione la DB antes de ejecutar SCAN
24
+ redisConn.select(db, function(selectErr) {
25
+ if (selectErr) {
26
+ const end = Date.now();
27
+ const time = end - start;
28
+ resolve({"scan":"error", "cursor":"0", "keys":[], "count":0, "iterations":0, "err":selectErr, "time":utl.milisegundosASegundos(time)});
29
+ try{ exec.redisClose(redisConn); }catch(e){}
29
30
  return;
30
31
  }
31
32
 
32
- const end = Date.now();
33
- const time = end - start;
33
+ // Iterar automáticamente hasta obtener todas las keys
34
+ let allKeys = [];
35
+ let currentCursor = cursor;
36
+ let iterations = 0;
37
+ const maxIterations = 10000; // Protección contra loops infinitos
34
38
 
35
- // res[0] es el nuevo cursor, res[1] es el array de keys
36
- resolve({
37
- "cursor": res[0],
38
- "keys": res[1],
39
- "count": res[1].length,
40
- "time": utl.milisegundosASegundos(time)
41
- });
39
+ const scanIteration = () => {
40
+ iterations++;
41
+
42
+ if (iterations > maxIterations) {
43
+ const end = Date.now();
44
+ const time = end - start;
45
+ resolve({"scan":"max_iterations", "cursor":currentCursor, "keys":allKeys, "count":allKeys.length, "iterations":iterations, "err":"SCAN: max iterations exceeded", "time":utl.milisegundosASegundos(time)});
46
+ try{ exec.redisClose(redisConn); }catch(e){}
47
+ return;
48
+ }
49
+
50
+ redisConn.scan(currentCursor, 'MATCH', pattern, 'COUNT', count, function (err, res) {
51
+ if (err) {
52
+ const end = Date.now();
53
+ const time = end - start;
54
+ resolve({"scan":"error", "cursor":currentCursor, "keys":allKeys, "count":allKeys.length, "iterations":iterations, "err":err, "time":utl.milisegundosASegundos(time)});
55
+ try{ exec.redisClose(redisConn); }catch(e){}
56
+ return;
57
+ }
58
+
59
+ const newCursor = res[0];
60
+ const keys = res[1] || [];
61
+
62
+ // Acumular keys
63
+ allKeys = allKeys.concat(keys);
64
+
65
+ utl.log(`${tag} SCAN iteration=${iterations} cursor=${currentCursor}->${newCursor} keys=${keys.length} total=${allKeys.length}`);
66
+
67
+ // Si el cursor es "0", terminamos
68
+ if (newCursor === '0') {
69
+ const end = Date.now();
70
+ const time = end - start;
71
+
72
+ const result = {
73
+ "scan": "ok",
74
+ "cursor": newCursor,
75
+ "keys": allKeys,
76
+ "count": allKeys.length,
77
+ "iterations": iterations,
78
+ "err": null,
79
+ "time": utl.milisegundosASegundos(time)
80
+ };
81
+
82
+ utl.log(`${tag} SCAN COMPLETE: returning ${allKeys.length} keys in ${iterations} iterations`);
83
+
84
+ resolve(result);
85
+
86
+ try{
87
+ exec.redisClose(redisConn);
88
+ utl.log(`${tag} SCAN connection closed successfully`);
89
+ }catch(e){
90
+ utl.log(`${tag} err.scan close: ${e}`);
91
+ }
92
+ } else {
93
+ // Continuar iterando
94
+ currentCursor = newCursor;
95
+ scanIteration();
96
+ }
97
+ });
98
+ };
42
99
 
43
- try{
44
- exec.redisClose(redisConn);
45
- }catch(e){
46
- utl.log('err.scan '+e);
47
- }
48
- });
100
+ // Iniciar iteración
101
+ scanIteration();
102
+ });
49
103
  }catch(e){
50
- utl.log('err scan: '+e);
51
- reject(e);
104
+ utl.log(`${tag} err scan: ${e}`);
105
+ const end = Date.now();
106
+ const time = end - start;
107
+ // Cerrar conexión en caso de error
108
+ try{
109
+ exec.redisClose(redisConn);
110
+ }catch(closeErr){
111
+ utl.log(`${tag} err closing connection after error: ${closeErr}`);
112
+ }
113
+ resolve({"scan":"error", "cursor":"0", "keys":[], "count":0, "iterations":0, "err":e, "time":utl.milisegundosASegundos(time)});
52
114
  }
53
115
  })
54
116
  }
@@ -108,6 +170,31 @@ const get=async( options, db, key )=>{
108
170
  })
109
171
  }
110
172
 
173
+ const type=async( options, db, key )=>{ // TYPE key
174
+ const exec = require("./exec");
175
+ const redisConn = await exec.redisConn(options);
176
+ const start = Date.now();
177
+
178
+ return new Promise((resolve, reject)=>{
179
+ try{
180
+ redisConn.select(db,function() { /* ... */ });
181
+ redisConn.type(key, function (err, res) {
182
+ const end = Date.now();
183
+ const time = end - start;
184
+
185
+ resolve({"type":key, "err":err, "res":res, "time":utl.milisegundosASegundos(time)});
186
+ try{
187
+ exec.redisClose(redisConn);
188
+ }catch(e){
189
+ utl.log('err.type '+e);
190
+ }
191
+ });
192
+ }catch(e){
193
+ utl.log('err type'+e);
194
+ }
195
+ })
196
+ }
197
+
111
198
 
112
199
  const incrby=async(options, db, key,value,expire, counter )=>{
113
200
  const exec = require("./exec");
@@ -784,6 +871,7 @@ const dbsize=async( options, db )=>{ // DBSIZE
784
871
  }
785
872
 
786
873
  const api=async(options, dbm, json)=>{
874
+ //utl.log('json recibido: '+JSON.stringify(json));
787
875
  const exec = require("./exec");
788
876
 
789
877
  const start = Date.now();
@@ -800,7 +888,7 @@ const api=async(options, dbm, json)=>{
800
888
  let lstop = json.stop!=null?json.stop*1:-1;
801
889
  let {field:id, val:vid} = getFirstField(filter);
802
890
 
803
- let ltdml = ['sinter','sunionstore','scard','hmget','hfind','upsert','set','get','scan','incrby','sadd','srem','smembers','hset','hgetall','del','incrbyfloat','expireat','setnx','hsetnx','hmset','expire','lrange','keys','dbsize'];
891
+ let ltdml = ['sinter','sunionstore','scard','hmget','hfind','upsert','set','get','type','scan','incrby','sadd','srem','smembers','hset','hgetall','del','incrbyfloat','expireat','setnx','hsetnx','hmset','expire','lrange','keys','dbsize'];
804
892
  for (let x of ltdml){
805
893
  if (utl.ObjectEmpty(json,x)){
806
894
  dml = x; break;
@@ -812,14 +900,36 @@ const api=async(options, dbm, json)=>{
812
900
  let keysArray = json.keys!=null ? json.keys : [];
813
901
  let fieldsArray = json.fields!=null ? json.fields : [];
814
902
  let destination = json.destination!=null ? json.destination : '';
815
- let cursor = json.cursor!=null ? json.cursor : '0';
816
- let pattern = json.pattern!=null ? json.pattern : key;
817
- let scan_count = json.count!=null ? json.count : 100;
903
+
904
+ // Parsear parámetros específicos para SCAN
905
+ let cursor = '0';
906
+ let pattern = '*';
907
+ let scan_count = 100;
908
+
909
+ if (dml === 'scan' && Array.isArray(key)) {
910
+ // Si scan viene como array: ["0", "COUNT", "100"] o ["0", "MATCH", "pattern", "COUNT", "100"]
911
+ cursor = key[0] || '0';
912
+ for (let i = 1; i < key.length; i++) {
913
+ if (key[i] === 'MATCH' && i + 1 < key.length) {
914
+ pattern = key[i + 1];
915
+ i++;
916
+ } else if (key[i] === 'COUNT' && i + 1 < key.length) {
917
+ scan_count = parseInt(key[i + 1]);
918
+ i++;
919
+ }
920
+ }
921
+ } else {
922
+ // Parámetros tradicionales
923
+ cursor = json.cursor!=null ? json.cursor : '0';
924
+ pattern = json.pattern!=null ? json.pattern : (typeof key === 'string' ? key : '*');
925
+ scan_count = json.count!=null ? json.count : 100;
926
+ }
818
927
 
819
928
  let r;
820
929
  switch (dml){
821
930
  case 'set': r = await set(options,dbm,key,value,expire); break;
822
931
  case 'get': r = await get(options,dbm,key); break;
932
+ case 'type': r = await type(options,dbm,key); break;
823
933
  case 'hfind': r = await hfind(options,dbm,key,filter,order,limit); break;
824
934
  case 'upsert': r = await upsert(options,dbm,key,value,id,vid,expire); break;
825
935
  case 'scan': r = await scan(options,dbm,cursor,pattern,scan_count); break;
@@ -934,6 +1044,7 @@ module.exports ={
934
1044
  scan,
935
1045
  set,
936
1046
  get,
1047
+ type,
937
1048
  incrby,
938
1049
  sadd,
939
1050
  srem,
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "name": "bonsaif",
16
16
  "description": "bonsaif is a library to connect to bonsaif apis",
17
- "version": "1.10.33",
17
+ "version": "1.10.34",
18
18
  "main": "index.js",
19
19
  "directories": {
20
20
  "lib": "lib"