redis-smq
Version:
A high-performance, reliable, and scalable message queue for Node.js.
93 lines • 4.51 kB
JavaScript
import { async } from 'redis-smq-common';
import { BrowserStorageAbstract } from './browser-storage-abstract.js';
import { withSharedPoolConnection } from '../../../common/redis/redis-connection-pool/with-shared-pool-connection.js';
export class BrowserStorageSet extends BrowserStorageAbstract {
count(redisKey, cb) {
this.logger.debug(`Counting items in ${redisKey}`);
withSharedPoolConnection((client, cb) => {
this.logger.debug(`Executing SCARD on ${redisKey}`);
client.scard(redisKey, (err, reply) => {
if (err) {
this.logger.error(`SCARD failed for ${redisKey}: ${err.message}`);
return cb(err);
}
this.logger.debug(`${redisKey} contains ${reply} items`);
cb(null, reply);
});
}, cb);
}
fetchItems(redisKey, pageParams, cb) {
const { page, pageSize } = pageParams;
this.logger.debug(`Fetching items from ${redisKey} (page ${page}, size ${pageSize})`);
withSharedPoolConnection((client, cb) => {
const scanToPage = (cursor, currentPage, cb) => {
this.logger.debug(`SSCAN ${redisKey} with cursor ${cursor}, targeting page ${page}, currently at ${currentPage}`);
async.withCallback((cb) => client.sscan(redisKey, cursor, { COUNT: pageSize }, cb), (reply, cb) => {
if (currentPage == page) {
this.logger.debug(`Reached target page ${page}, items: ${reply.items.length}`);
return cb(null, reply);
}
if (reply.cursor === '0') {
this.logger.debug(`End of set reached at page ${currentPage}, target was ${page}`);
return cb(null, { cursor, items: [] });
}
this.logger.debug(`Moving to next page, cursor: ${reply.cursor}`);
currentPage = currentPage + 1;
scanToPage(reply.cursor, currentPage, cb);
}, cb);
};
scanToPage('0', 1, (err, reply) => {
if (err) {
this.logger.error(`Error fetching items from ${redisKey}: ${err.message}`);
return cb(err);
}
const { items = [] } = reply ?? {};
const itemCount = items.length;
if (itemCount === 0) {
this.logger.debug(`No items found in ${redisKey} for page ${page}`);
}
else {
this.logger.debug(`Retrieved ${itemCount} items from ${redisKey}`);
}
cb(null, items);
});
}, cb);
}
fetchAllItems(redisKey, cb) {
this.logger.debug(`Fetching all items from ${redisKey}`);
withSharedPoolConnection((client, cb) => {
const items = new Set();
let scanCount = 0;
const fullScan = (cursor, cb) => {
scanCount++;
this.logger.debug(`SSCAN ${redisKey} iteration ${scanCount}, cursor: ${cursor}`);
async.withCallback((cb) => client.sscan(redisKey, cursor, {}, cb), (reply, cb) => {
const newItems = reply.items.length;
this.logger.debug(`Adding ${newItems} items from scan iteration ${scanCount}`);
reply.items.forEach((i) => items.add(i));
if (reply.cursor === '0') {
this.logger.debug(`Scan complete after ${scanCount} iterations`);
return cb();
}
fullScan(reply.cursor, cb);
}, cb);
};
this.logger.debug(`Starting SSCAN with initial cursor=0`);
fullScan('0', (err) => {
if (err) {
this.logger.error(`Error fetching all items from ${redisKey}: ${err.message}`);
return cb(err);
}
const itemCount = items.size;
if (itemCount === 0) {
this.logger.debug(`${redisKey} is empty`);
}
else {
this.logger.debug(`Retrieved ${itemCount} total items from ${redisKey}`);
}
cb(null, [...items.values()]);
});
}, cb);
}
}
//# sourceMappingURL=browser-storage-set.js.map