New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

catbox

Package Overview
Dependencies
Maintainers
5
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

catbox - npm Package Compare versions

Comparing version 7.1.5 to 8.0.0

lib/pending.js

105

lib/client.js

@@ -33,11 +33,11 @@ 'use strict';

internals.Client.prototype.stop = function () {
internals.Client.prototype.start = function () {
this.connection.stop();
return internals.promised(this.connection, 'start');
};
internals.Client.prototype.start = function (callback) {
internals.Client.prototype.stop = function () {
this.connection.start(callback);
return this.connection.stop();
};

@@ -58,86 +58,70 @@

internals.Client.prototype.get = function (key, callback) {
internals.Client.prototype.get = async function (key, callback) {
if (!this.connection.isReady()) {
// Disconnected
return callback(Boom.internal('Disconnected'));
throw Boom.internal('Disconnected'); // Disconnected
}
if (!key) {
// Not found on null
return callback(null, null);
return null; // Not found on null
}
if (!internals.validateKey(key)) {
return callback(Boom.internal('Invalid key'));
throw Boom.internal('Invalid key');
}
this.connection.get(key, (err, result) => {
const result = await internals.promised(this.connection, 'get', key);
if (!result ||
result.item === undefined ||
result.item === null) {
if (err) {
// Connection error
return callback(err);
}
return null; // Not found
}
if (!result ||
result.item === undefined ||
result.item === null) {
const now = Date.now();
const expires = result.stored + result.ttl;
const ttl = expires - now;
if (ttl <= 0) {
return null; // Expired
}
// Not found
return callback(null, null);
}
const cached = {
item: result.item,
stored: result.stored,
ttl
};
const now = Date.now();
const expires = result.stored + result.ttl;
const ttl = expires - now;
if (ttl <= 0) {
// Expired
return callback(null, null);
}
// Valid
const cached = {
item: result.item,
stored: result.stored,
ttl
};
return callback(null, cached);
});
return cached; // Valid
};
internals.Client.prototype.set = function (key, value, ttl, callback) {
internals.Client.prototype.set = async function (key, value, ttl) {
if (!this.connection.isReady()) {
// Disconnected
return callback(Boom.internal('Disconnected'));
throw Boom.internal('Disconnected'); // Disconnected
}
if (!internals.validateKey(key)) {
return callback(Boom.internal('Invalid key'));
throw Boom.internal('Invalid key');
}
if (ttl <= 0) {
// Not cachable (or bad rules)
return callback();
return; // Not cachable (or bad rules)
}
this.connection.set(key, value, ttl, callback);
return await internals.promised(this.connection, 'set', key, value, ttl);
};
internals.Client.prototype.drop = function (key, callback) {
internals.Client.prototype.drop = async function (key) {
if (!this.connection.isReady()) {
// Disconnected
return callback(Boom.internal('Disconnected'));
throw Boom.internal('Disconnected'); // Disconnected
}
if (!internals.validateKey(key)) {
return callback(Boom.internal('Invalid key'));
throw Boom.internal('Invalid key');
}
this.connection.drop(key, callback); // Always drop, regardless of caching rules
return await internals.promised(this.connection, 'drop', key); // Always drop, regardless of caching rules
};

@@ -150,1 +134,20 @@

};
internals.promised = function (obj, method, ...args) {
const deferred = {};
const callbackPromise = new Promise((resolve, reject) => {
deferred.resolve = resolve;
deferred.reject = reject;
});
const result = obj[method](...args, (err, value) => {
return err ? deferred.reject(err) : deferred.resolve(value);
});
const isPromiseResult = !!(result && result.then);
return isPromiseResult ? result : callbackPromise;
};

@@ -9,3 +9,5 @@ 'use strict';

const Pending = require('./pending');
// Declare internals

@@ -18,45 +20,2 @@

internals.toBoundCallback = function (callback) {
return process.domain ? process.domain.bind(callback) : callback;
};
internals.PendingResponse = function (id, addCallback, onDidSend) {
this.id = id;
this.callbacks = [internals.toBoundCallback(addCallback)];
this.onDidSend = onDidSend;
this.timeoutTimer = null;
};
internals.PendingResponse.prototype.add = function (callback) {
this.callbacks.push(internals.toBoundCallback(callback)); // Explicitly bind callback to its process.domain (_finalize might get called from a different active process.domain)
};
internals.PendingResponse.prototype.send = function (err, value, cached, report) {
const length = this.callbacks.length;
for (let i = 0; i < length; ++i) {
Hoek.nextTick(this.callbacks[i])(err, value, cached, report);
}
clearTimeout(this.timeoutTimer);
this.callbacks = [];
return this.onDidSend(length, report);
};
internals.PendingResponse.prototype.setTimeout = function (fn, timeoutMs) {
clearTimeout(this.timeoutTimer);
this.timeoutTimer = setTimeout(fn, timeoutMs);
};
exports = module.exports = internals.Policy = function (options, cache, segment) {

@@ -67,3 +26,3 @@

this._cache = cache;
this._pendings = Object.create(null); // id -> PendingResponse
this._pendings = Object.create(null); // id -> Pending
this._pendingGenerateCall = Object.create(null); // id -> boolean

@@ -96,3 +55,3 @@ this.rules(options);

internals.Policy.prototype.get = function (key, callback) { // key: string or { id: 'id' }
internals.Policy.prototype.get = async function (key) { // key: string or { id: 'id' }

@@ -105,65 +64,69 @@ ++this.stats.gets;

if (this._pendings[id]) {
this._pendings[id].add(callback);
return;
return await this._pendings[id].join();
}
const pending = this._pendings[id] = new internals.PendingResponse(id, callback, (count, report) => {
const pending = new Pending(id);
this._pendings[id] = pending;
delete this._pendings[id];
this._get(pending, key); // Background processing
if (count > 0 && report.isStale !== undefined) {
this.stats.hits = this.stats.hits + count;
}
});
return await pending.promise;
};
// Lookup in cache
const timer = new Hoek.Timer();
this._get(id, (err, cached) => {
internals.Policy.prototype._get = async function (pending, key) {
if (err) {
++this.stats.errors;
}
// Prepare report
// Prepare report
const report = {};
const report = {
msec: timer.elapsed(),
error: err
};
// Lookup in cache
if (cached) {
report.stored = cached.stored;
report.ttl = cached.ttl;
const staleIn = typeof this.rule.staleIn === 'function' ? this.rule.staleIn(cached.stored, cached.ttl) : this.rule.staleIn;
cached.isStale = (staleIn ? (Date.now() - cached.stored) >= staleIn : false);
report.isStale = cached.isStale;
const timer = new Hoek.Bench();
let cached;
try {
cached = (this._cache ? await this._cache.get({ segment: this._segment, id: pending.id }) : null);
}
catch (err) {
report.error = err;
++this.stats.errors;
}
if (cached.isStale) {
++this.stats.stales;
}
report.msec = timer.elapsed();
if (cached) {
report.stored = cached.stored;
report.ttl = cached.ttl;
const staleIn = typeof this.rule.staleIn === 'function' ? this.rule.staleIn(cached.stored, cached.ttl) : this.rule.staleIn;
cached.isStale = (staleIn ? (Date.now() - cached.stored) >= staleIn : false);
report.isStale = cached.isStale;
if (cached.isStale) {
++this.stats.stales;
}
}
// No generate method
// No generate method
if (!this.rule.generateFunc ||
(err && !this.rule.generateOnReadError)) {
if (!this.rule.generateFunc ||
(report.error && !this.rule.generateOnReadError)) {
return pending.send(err, cached ? cached.item : null, cached, report);
}
this._send(pending, report.error, cached ? cached.item : null, cached, report);
return;
}
// Check if found and fresh
// Check if found and fresh
if (cached &&
!cached.isStale) {
if (cached &&
!cached.isStale) {
return pending.send(null, cached.item, cached, report);
}
this._send(pending, null, cached.item, cached, report);
return;
}
return this._generate(pending, key, cached, report);
});
await this._generate(pending, key, cached, report);
};
internals.Policy.prototype._generate = function (pending, key, cached, report) {
internals.Policy.prototype._generate = async function (pending, key, cached, report) {

@@ -182,3 +145,3 @@ if (cached) { // Must be stale

return pending.send(null, cached.item, cached, report);
return this._send(pending, null, cached.item, cached, report);
}, this.rule.staleTimeout);

@@ -192,3 +155,3 @@ }

return pending.send(Boom.serverUnavailable(), null, null, report);
return this._send(pending, Boom.serverUnavailable(), null, null, report);
}, this.rule.generateTimeout);

@@ -210,9 +173,3 @@ }

try {
this._callGenerateFunc(pending, key, cached, report);
}
catch (err) {
delete this._pendingGenerateCall[pending.id];
return pending.send(err, null, null, report);
}
await this._callGenerateFunc(pending, key, cached, report);
}

@@ -225,55 +182,62 @@ else {

internals.Policy.prototype._callGenerateFunc = function (pending, key, cached, report) {
internals.Policy.prototype._callGenerateFunc = async function (pending, key, cached, report) {
this.rule.generateFunc.call(null, key, (generateError, value, ttl) => {
let value;
const flags = {};
let generateError;
try {
value = await this.rule.generateFunc(key, flags);
}
catch (err) {
generateError = err;
}
pending = this._pendingGenerateCall[pending.id] || pending;
delete this._pendingGenerateCall[pending.id];
pending = this._pendingGenerateCall[pending.id] || pending;
delete this._pendingGenerateCall[pending.id];
const finalize = (err) => {
// Error (if dropOnError is not set to false) or not cached
const error = generateError || (this.rule.generateIgnoreWriteError ? null : err);
if (cached &&
error &&
!this.rule.dropOnError) {
let persistError;
try {
if ((generateError && this.rule.dropOnError) || flags.ttl === 0) { // null or undefined means use policy
await this.drop(pending.id); // Invalidate cache
}
else if (!generateError) {
await this.set(pending.id, value, flags.ttl); // Lazy save (replaces stale cache copy with late-coming fresh copy)
}
}
catch (err) {
persistError = err;
}
return pending.send(error, cached.item, cached, report);
}
const error = generateError || (this.rule.generateIgnoreWriteError ? null : persistError);
if (cached &&
error &&
!this.rule.dropOnError) {
return pending.send(error, value, null, report); // Ignored if stale value already returned
};
this._send(pending, error, cached.item, cached, report);
return;
}
// Error (if dropOnError is not set to false) or not cached
this._send(pending, error, value, null, report); // Ignored if stale value already returned
};
if ((generateError && this.rule.dropOnError) || ttl === 0) { // null or undefined means use policy
return this.drop(pending.id, finalize); // Invalidate cache
}
if (!generateError) {
return this.set(pending.id, value, ttl, finalize); // Lazy save (replaces stale cache copy with late-coming fresh copy)
}
internals.Policy.prototype._send = function (pending, err, value, cached, report) {
return finalize();
});
};
pending.send(err, value, cached, report);
delete this._pendings[pending.id];
internals.Policy.prototype._get = function (id, callback) {
if (!this._cache) {
return Hoek.nextTick(callback)(null, null);
if (report.isStale !== undefined) {
this.stats.hits = this.stats.hits + pending.count;
}
this._cache.get({ segment: this._segment, id }, callback);
};
internals.Policy.prototype.set = function (key, value, ttl, callback) {
internals.Policy.prototype.set = async function (key, value, ttl) {
callback = callback || Hoek.ignore;
++this.stats.sets;
if (!this._cache) {
return callback(null);
return;
}

@@ -283,30 +247,26 @@

const id = (key && typeof key === 'object') ? key.id : key;
this._cache.set({ segment: this._segment, id }, value, ttl, (err) => {
if (err) {
++this.stats.errors;
}
return callback(err);
});
try {
await this._cache.set({ segment: this._segment, id }, value, ttl);
}
catch (err) {
++this.stats.errors;
throw err;
}
};
internals.Policy.prototype.drop = function (key, callback) {
internals.Policy.prototype.drop = async function (key) {
callback = callback || Hoek.ignore;
if (!this._cache) {
return callback(null);
return;
}
const id = (key && typeof key === 'object') ? key.id : key;
this._cache.drop({ segment: this._segment, id }, (err) => {
if (err) {
++this.stats.errors;
}
return callback(err);
});
try {
return await this._cache.drop({ segment: this._segment, id });
}
catch (err) {
++this.stats.errors;
throw err;
}
};

@@ -358,4 +318,4 @@

expiresAt: '13:00',
generateFunc: function (id, next) { next(err, result, ttl); }
generateFunc: (id, flags) => { throw err; } / { return result; } / { flags.ttl = ttl; return result; }
generateTimeout: 500,

@@ -362,0 +322,0 @@ generateOnReadError: true,

{
"name": "catbox",
"description": "Multi-strategy object caching service",
"version": "7.1.5",
"version": "8.0.0",
"repository": "git://github.com/hapijs/catbox",

@@ -13,11 +13,11 @@ "main": "lib/index.js",

"engines": {
"node": ">=4.0.0"
"node": ">=8.0.0"
},
"dependencies": {
"boom": "5.x.x",
"hoek": "4.x.x",
"joi": "10.x.x"
"boom": "6.x.x",
"hoek": "5.x.x",
"joi": "11.x.x"
},
"devDependencies": {
"code": "4.x.x",
"code": "5.x.x",
"lab": "14.x.x"

@@ -24,0 +24,0 @@ },

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc