Skip to content

Instantly share code, notes, and snippets.

@spion
Last active February 18, 2016 11:26
Show Gist options
  • Save spion/8517936 to your computer and use it in GitHub Desktop.
Save spion/8517936 to your computer and use it in GitHub Desktop.
Shank shiz without crashing
// A generic library that can be used to
// acquire resources which may get into
// an unusable state if something throws
// while they're being used.
var Promise = require('bluebird');
// Acquires an acquirable resource, then passes it to
// the function fn, returning its returned result.
// If fn throws, the resource is disposed and will be
// recreated the next time its acquired
function acquire(res, fn) {
return res._get()
.then(fn)
.catch(function(e) {
var p = res._get();
return p.bind(res)
.then(res._disposer)
.finally(res._nullify)
.finally(function() {
throw e;
});
});
}
// Creates a resource which may be acquired. Pass
// a factory function (lambda) that takes no arguments.
// If the resource contains file handles, also pass
// a dispose function that gets rid of them.
acquire.create = function create(fn, dispose) {
return new Acquirable(fn, dispose);
}
function nothing() {}
function Acquirable(fn, dispose) {
this._factory = fn;
this._disposer = dispose || nothing;
this._instance = null;
}
Acquirable.prototype._get = function Acquirable$_get() {
if (this._instance == null) {
this._instance = Promise.try(this._factory);
}
return this._instance;
}
Acquirable.prototype._nullify = function Acquirable$_nullify() {
this._instance = null;
}
module.exports = acquire;
// Using acquire.js we can safely use the shiz
// library even though its throws cause the
// shiz object to get into an bad state
var shizer = require('./shiz');
var acquire = require('./acquire');
var shiz = acquire.create(function() { return shizer(); });
function doSomeShiz(n) {
return acquire(shiz, function(shiz) {
shiz.expect(n);
for (var i = 0; i < n; i++) {
shiz();
}
});
}
setInterval(function() {
doSomeShiz(10);
}, 1000);
// Some bug in the code causes it to crash sometimes.
// Gee, that sure is annoying! Server restarts in a
// clean state, and spams the error log until we go
// in and fix it.
// <spion> The only refactoring I did to this function
// is to make the state non-global. Most modules
// export a (factory) function anyway so usually that
// wont be a problem
module.exports = function shiz() {
// this is some internal state etc.
var theShiz = 0;
var expectShiz = 0;
console.log("Making new shiz");
function expect(n) {
expectShiz = n;
theShiz = 0;
}
function verify() {
console.log('did %d of shiz, expected %d', theShiz, expectShiz);
console.log('cleanup shiz');
theShiz = 0;
}
function shiz() {
theShiz++;
// oops
// such error
// many throw uncawt lul
if (Math.random() > 0.5)
throw new Error('shank shiz');
if (theShiz === expectShiz)
verify();
if (theShiz > expectShiz)
throw new Error('uh o so error such unexpect');
}
shiz.verify = verify;
shiz.expect = expect;
return shiz;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment