Comparing version 0.4.0 to 0.5.0
@@ -5,2 +5,22 @@ # Change Log | ||
<a name="0.5.0"></a> | ||
# [0.5.0](https://github.com/bucharest-gold/opossum/compare/v0.3.0...v0.5.0) (2016-12-22) | ||
### Bug Fixes | ||
* ensure fallback event emits after function call ([df40ea7](https://github.com/bucharest-gold/opossum/commit/df40ea7)) | ||
* ensure pending close flag is reset ([5a1b70b](https://github.com/bucharest-gold/opossum/commit/5a1b70b)) | ||
* ensure that promise is rejected on fallback ([d4496d8](https://github.com/bucharest-gold/opossum/commit/d4496d8)) | ||
* fix (again) browser load of circuitBreaker ([58a80fb](https://github.com/bucharest-gold/opossum/commit/58a80fb)) | ||
* fix export of module in browser environment ([5a0594c](https://github.com/bucharest-gold/opossum/commit/5a0594c)) | ||
### Features | ||
* allow for a CircuitBreaker as a fallback ([85cbc34](https://github.com/bucharest-gold/opossum/commit/85cbc34)) | ||
* Full featured browser capabilities ([2cc08f0](https://github.com/bucharest-gold/opossum/commit/2cc08f0)) | ||
<a name="0.4.0"></a> | ||
@@ -7,0 +27,0 @@ # [0.4.0](https://github.com/bucharest-gold/opossum/compare/v0.3.0...v0.4.0) (2016-12-20) |
@@ -1,2 +0,2 @@ | ||
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f;}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e);},l,l.exports,e,t,n,r);}return n[o].exports;}for(var i=typeof require=="function"&&require,o=0;o<r.length;o++)s(r[o]);return s;})({1:[function(c,d,h){(function(j){'use strict';const k=c('./lib/circuit'),q=c('fidelity'),w={timeout:10000,maxFailures:10,resetTimeout:30000,Promise:q},z=typeof j==='object'&&j&&j.Object===Object&&j,A=z||Function('return this')();function circuitBreaker(B,C){return new k(B,Object.assign({},w,C));}circuitBreaker.promisify=c('./lib/promisify');function exportModule(D){if(typeof d==='object'&&d.exports){d.exports=h=D;}A[D.name]=D;}exportModule(circuitBreaker);}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{});},{"./lib/circuit":2,"./lib/promisify":3,"fidelity":6}],2:[function(E,F,G){'use strict';const H=E('events'),I=E('./status'),J=Symbol('state'),K=Symbol('open'),L=Symbol('closed'),M=Symbol('half-open'),N=Symbol('pending-close'),O=Symbol('fallback'),P=Symbol('num-failures'),Q=Symbol('status');class CircuitBreaker extends H{constructor(R,S){super();if(typeof R!=='function')this.action=()=>R;else this.action=R;this.options=S;this.Promise=S.Promise;this[Q]=new I(this);this[J]=L;this[O]=null;this[N]=!1;this[P]=0;function _startTimer(T){return()=>{const U=setTimeout(()=>{T[J]=M;T.emit('halfOpen',T.options.resetTimeout);},T.options.resetTimeout);if(typeof U.unref==='function'){U.unref();}};}this.on('open',_startTimer(this));this.on('success',()=>this.close());}close(){this[P]=0;this[N]=!1;if(this[J]!==L){this[J]=L;this.emit('close');}}open(){this[N]=!1;if(this[J]!==K){this[J]=K;this.emit('open');}}get closed(){return this[J]===L;}get opened(){return this[J]===K;}get halfOpen(){return this[J]===M;}get status(){return this[Q];}fallback(V){this[O]=V;return this;}fire(){const W=Array.prototype.slice.call(arguments);this.emit('fire',W);if(this.opened||this.halfOpen&&this[N]){this.emit('reject',new Error('Breaker is open'));return failFast(this,'Breaker is open',W);}this[N]=this.halfOpen;let X,Y=!1;try{return new this.Promise((Z,a1)=>{const b1=setTimeout(()=>{Y=!0;const c1=new Error(`Timed out after ${this.options.timeout}ms`);this.emit('timeout',c1);failFast(this,c1,W);a1(c1);},this.options.timeout);Promise.resolve(this.action.apply(this.action,W)).then(d1=>{if(!Y){this.emit('success',d1);Z(d1);clearTimeout(b1);}}).catch(e1=>{failFast(this,e1,W);a1(e1);clearTimeout(b1);});});}catch(error){clearTimeout(X);return failFast(this,error,W);}}}function failFast(f1,g1,h1){f1.emit('failure',g1);f1[P]+=1;if(f1[P]>=f1.options.maxFailures){f1.open();}if(f1[O]){return new f1.Promise((i1,j1)=>{const k1=f1[O].apply(f1[O],h1);f1.emit('fallback',k1);i1(k1);});}return f1.Promise.reject.apply(null,[g1]);}F.exports=G=CircuitBreaker;},{"./status":4,"events":5}],3:[function(l1,m1,n1){'use strict';const o1=l1('fidelity');m1.exports=n1=function promisify(p1){return function promisifiedFunction(){return new o1((q1,r1)=>{const cb=(s1,t1)=>{if(s1)r1(s1);q1(t1);},u1=Array.prototype.slice.call(arguments);u1.push(cb);p1.apply(p1,u1);});};};},{"fidelity":6}],4:[function(v1,w1,x1){'use strict';const y1=Symbol('circuit-breaker');class Status{constructor(z1){this.failures=0;this.fallbacks=0;this.successes=0;this.rejects=0;this.fires=0;this.timeouts=0;this[y1]=z1;z1.on('success',()=>this.successes++);z1.on('failure',()=>this.failures++);z1.on('fallback',()=>this.fallbacks++);z1.on('timeout',()=>this.timeouts++);z1.on('fire',()=>this.fires++);z1.on('reject',()=>this.rejects++);}}w1.exports=x1=Status;},{}],5:[function(A1,B1,C1){function EventEmitter(){this._events=this._events||{};this._maxListeners=this._maxListeners||void 0;}B1.exports=EventEmitter;EventEmitter.EventEmitter=EventEmitter;EventEmitter.prototype._events=void 0;EventEmitter.prototype._maxListeners=void 0;EventEmitter.defaultMaxListeners=10;EventEmitter.prototype.setMaxListeners=function(n){if(!isNumber(n)||n<0||isNaN(n))throw TypeError('n must be a positive number');this._maxListeners=n;return this;};EventEmitter.prototype.emit=function(D1){var er,F1,G1,H1,i,I1;if(!this._events)this._events={};if(D1==='error'){if(!this._events.error||isObject(this._events.error)&&!this._events.error.length){er=arguments[1];if(er instanceof Error){throw er;}else{var J1=new Error('Uncaught, unspecified "error" event. ('+er+')');J1.context=er;throw J1;}}}F1=this._events[D1];if(isUndefined(F1))return!1;if(isFunction(F1)){switch(arguments.length){case 1:F1.call(this);break;case 2:F1.call(this,arguments[1]);break;case 3:F1.call(this,arguments[1],arguments[2]);break;default:H1=Array.prototype.slice.call(arguments,1);F1.apply(this,H1);}}else if(isObject(F1)){H1=Array.prototype.slice.call(arguments,1);I1=F1.slice();G1=I1.length;for(i=0;i<G1;i++)I1[i].apply(this,H1);}return!0;};EventEmitter.prototype.addListener=function(K1,L1){var m;if(!isFunction(L1))throw TypeError('listener must be a function');if(!this._events)this._events={};if(this._events.newListener)this.emit('newListener',K1,isFunction(L1.listener)?L1.listener:L1);if(!this._events[K1])this._events[K1]=L1;else if(isObject(this._events[K1]))this._events[K1].push(L1);else this._events[K1]=[this._events[K1],L1];if(isObject(this._events[K1])&&!this._events[K1].warned){if(!isUndefined(this._maxListeners)){m=this._maxListeners;}else{m=EventEmitter.defaultMaxListeners;}if(m&&m>0&&this._events[K1].length>m){this._events[K1].warned=!0;console.error('(node) warning: possible EventEmitter memory '+'leak detected. %d listeners added. '+'Use emitter.setMaxListeners() to increase limit.',this._events[K1].length);if(typeof console.trace==='function'){console.trace();}}}return this;};EventEmitter.prototype.on=EventEmitter.prototype.addListener;EventEmitter.prototype.once=function(M1,N1){if(!isFunction(N1))throw TypeError('listener must be a function');var O1=!1;function g(){this.removeListener(M1,g);if(!O1){O1=!0;N1.apply(this,arguments);}}g.listener=N1;this.on(M1,g);return this;};EventEmitter.prototype.removeListener=function(P1,Q1){var R1,S1,T1,i;if(!isFunction(Q1))throw TypeError('listener must be a function');if(!this._events||!this._events[P1])return this;R1=this._events[P1];T1=R1.length;S1=-1;if(R1===Q1||isFunction(R1.listener)&&R1.listener===Q1){delete this._events[P1];if(this._events.removeListener)this.emit('removeListener',P1,Q1);}else if(isObject(R1)){for(i=T1;i-->0;){if(R1[i]===Q1||R1[i].listener&&R1[i].listener===Q1){S1=i;break;}}if(S1<0)return this;if(R1.length===1){R1.length=0;delete this._events[P1];}else{R1.splice(S1,1);}if(this._events.removeListener)this.emit('removeListener',P1,Q1);}return this;};EventEmitter.prototype.removeAllListeners=function(U1){var V1,W1;if(!this._events)return this;if(!this._events.removeListener){if(arguments.length===0)this._events={};else if(this._events[U1])delete this._events[U1];return this;}if(arguments.length===0){for(V1 in this._events){if(V1==='removeListener')continue;this.removeAllListeners(V1);}this.removeAllListeners('removeListener');this._events={};return this;}W1=this._events[U1];if(isFunction(W1)){this.removeListener(U1,W1);}else if(W1){while(W1.length)this.removeListener(U1,W1[W1.length-1]);}delete this._events[U1];return this;};EventEmitter.prototype.listeners=function(X1){var Y1;if(!this._events||!this._events[X1])Y1=[];else if(isFunction(this._events[X1]))Y1=[this._events[X1]];else Y1=this._events[X1].slice();return Y1;};EventEmitter.prototype.listenerCount=function(Z1){if(this._events){var a2=this._events[Z1];if(isFunction(a2))return 1;else if(a2)return a2.length;}return 0;};EventEmitter.listenerCount=function(b2,c2){return b2.listenerCount(c2);};function isFunction(d2){return typeof d2==='function';}function isNumber(e2){return typeof e2==='number';}function isObject(f2){return typeof f2==='object'&&f2!==null;}function isUndefined(g2){return g2===void 0;}},{}],6:[function(h2,i2,j2){(function(k2){(function(){'use strict';var l2=typeof k2==='object'&&k2&&k2.Object===Object&&k2,m2=l2||Function('return this')();const n2=0,o2=1,p2=2,q2=Symbol('handlers'),r2=Symbol('queue'),s2=Symbol('state'),t2=Symbol('value');class FidelityPromise{constructor(fn){this[r2]=[];this[q2]=new Handlers();this[s2]=n2;this[t2]=void 0;const v2=typeof fn;if(v2==='function'){tryFunction(fn,this);}else if(v2!=='undefined'){resolvePromise(this,fn);}}get state(){return this[s2];}get value(){return this[t2];}then(w2,x2){const y2=new FidelityPromise();if(typeof w2==='function'){y2[q2].fulfill=w2;}if(typeof x2==='function'){y2[q2].reject=x2;}this[r2].push(y2);process(this);return y2;}catch(z2){return this.then(null,z2);}static promise(fn){console.error('Fidelity.promise() is deprecated. Use `new Fidelity.Promise()`.');return new FidelityPromise(fn);}static deferred(){let B2,C2;const p=new FidelityPromise((D2,E2)=>{B2=D2;C2=E2;});return{promise:p,resolve:F2=>B2(F2),reject:G2=>C2(G2)};}static resolve(H2){if(H2&&H2.then)return H2;switch(H2){case null:return U2;case!0:return S2;case!1:return T2;case 0:return V2;case'':return W2;}const p=new FidelityPromise();p[s2]=o2;p[t2]=H2;return p;}static reject(I2){const p=new FidelityPromise();p[s2]=p2;p[t2]=I2;return p;}static all(){const J2=[],K2=Array.from(arguments).reduce((a,b)=>a.concat(b),[]),L2=K2.reduce((M2,p)=>M2.then(()=>p).then(r=>J2.push(r)),Promise.resolve(null));return L2.then(_=>J2);}static race(){const N2=Array.from(arguments).reduce((a,b)=>a.concat(b),[]);return new FidelityPromise((O2,P2)=>{N2.forEach(p=>p.then(O2).catch(P2));});}}FidelityPromise.PENDING=n2;FidelityPromise.FULFILLED=o2;FidelityPromise.REJECTED=p2;class Handlers{constructor(){this.fulfill=null;this.reject=null;}}const Q2=(()=>{if(m2.process&&typeof m2.process.nextTick==='function'){return m2.process.nextTick;}else if(typeof m2.setImmediate==='function'){return m2.setImmediate;}else if(typeof m2.setTimeout==='function'){return(f,p)=>m2.setTimeout(f,0,p);}else{console.error('No nextTick. How we gonna do this?');return(f,p)=>f.call(this,p);}})();function exportModule(R2){if(typeof i2==='object'&&i2.exports){i2.exports=R2;}else{m2[R2.name]=R2;}}const S2=new FidelityPromise(!0),T2=new FidelityPromise(!1),U2=new FidelityPromise(null),V2=new FidelityPromise(0),W2=new FidelityPromise('');function tryFunction(fn,Y2){try{fn(v=>resolvePromise(Y2,v),r=>transition(Y2,p2,r));}catch(e){transition(Y2,p2,e);}}function resolvePromise(p,x){if(x===p){transition(p,p2,new TypeError('The promise and its value are the same.'));return;}const Z2=typeof x;if(x&&(Z2==='function'||Z2==='object')){let a3=!1;try{const b3=x.then;if(b3&&typeof b3==='function'){b3.call(x,y=>{if(!a3){resolvePromise(p,y);a3=!0;}},r=>{if(!a3){transition(p,p2,r);a3=!0;}});}else{transition(p,o2,x);a3=!0;}}catch(e){if(!a3){transition(p,p2,e);a3=!0;}}}else{transition(p,o2,x);}}function process(p){if(p[s2]===n2)return;Q2(processNextTick,p);return p;}function processNextTick(p){let c3,qp;while(p[r2].length){qp=p[r2].shift();if(p[s2]===o2){c3=qp[q2].fulfill||(v=>v);}else if(p[s2]===p2){c3=qp[q2].reject||(r=>{throw r;});}try{resolvePromise(qp,c3(p[t2]));}catch(e){transition(qp,p2,e);continue;}}}function transition(p,e3,f3){if(p[s2]===e3||p[s2]!==n2)return;p[s2]=e3;p[t2]=f3;return process(p);}exportModule(FidelityPromise);}).call(this);}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{});},{}]},{},[1,2,3,4]); | ||
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f;}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e);},l,l.exports,e,t,n,r);}return n[o].exports;}for(var i=typeof require=="function"&&require,o=0;o<r.length;o++)s(r[o]);return s;})({1:[function(c,d,h){(function(j){'use strict';const k=c('./lib/circuit'),q=c('fidelity'),w={timeout:10000,maxFailures:10,resetTimeout:30000,Promise:q},z=typeof j==='object'&&j&&j.Object===Object&&j,A=z||Function('return this')();function circuitBreaker(B,C){return new k(B,Object.assign({},w,C));}circuitBreaker.promisify=c('./lib/promisify');function exportModule(D){if(typeof d==='object'&&d.exports){d.exports=h=D;}A[D.name]=D;}exportModule(circuitBreaker);}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{});},{"./lib/circuit":2,"./lib/promisify":3,"fidelity":6}],2:[function(E,F,G){'use strict';const H=E('events'),I=E('./status'),J=Symbol('state'),K=Symbol('open'),L=Symbol('closed'),M=Symbol('half-open'),N=Symbol('pending-close'),O=Symbol('fallback'),P=Symbol('num-failures'),Q=Symbol('status');class CircuitBreaker extends H{constructor(R,S){super();this.options=S;this.Promise=S.Promise;this[Q]=new I(this);this[J]=L;this[O]=null;this[N]=!1;this[P]=0;if(typeof R!=='function')this.action=()=>this.Promise.resolve(R);else this.action=R;function _startTimer(T){return()=>{const U=setTimeout(()=>{T[J]=M;T.emit('halfOpen',T.options.resetTimeout);},T.options.resetTimeout);if(typeof U.unref==='function'){U.unref();}};}this.on('open',_startTimer(this));this.on('success',()=>this.close());}close(){this[P]=0;this[N]=!1;if(this[J]!==L){this[J]=L;this.emit('close');}}open(){this[N]=!1;if(this[J]!==K){this[J]=K;this.emit('open');}}get closed(){return this[J]===L;}get opened(){return this[J]===K;}get halfOpen(){return this[J]===M;}get status(){return this[Q];}fallback(V){let W=V;if(V instanceof CircuitBreaker){W=function(){return V.fire.apply(V,arguments);};}this[O]=W;return this;}fire(){const X=Array.prototype.slice.call(arguments);this.emit('fire',X);if(this.opened||this.halfOpen&&this[N]){this.emit('reject',new Error('Breaker is open'));return fail(this,'Breaker is open',X);}this[N]=this.halfOpen;let Y,Z=!1;try{return new this.Promise((a1,b1)=>{Y=setTimeout(()=>{Z=!0;const c1=new Error(`Timed out after ${this.options.timeout}ms`);this.emit('timeout',c1);fail(this,c1,X);b1(c1);},this.options.timeout);const d1=this.action.apply(this.action,X),e1=typeof d1.then==='function'?d1:this.Promise.resolve(d1);e1.then(f1=>{if(!Z){this.emit('success',f1);a1(f1);clearTimeout(Y);}}).catch(g1=>{fail(this,g1,X);b1(g1);clearTimeout(Y);});});}catch(error){clearTimeout(Y);return fail(this,error,X);}}}function fail(h1,i1,j1){h1.emit('failure',i1);h1[P]+=1;if(h1[P]>=h1.options.maxFailures){h1.open();}if(h1[O]){return new h1.Promise((k1,l1)=>{const m1=h1[O].apply(h1[O],j1);h1.emit('fallback',m1);k1(m1);});}return h1.Promise.reject.apply(null,[i1]);}F.exports=G=CircuitBreaker;},{"./status":4,"events":5}],3:[function(n1,o1,p1){'use strict';const q1=n1('fidelity');o1.exports=p1=function promisify(r1){return function promisifiedFunction(){return new q1((s1,t1)=>{const cb=(u1,v1)=>{if(u1)t1(u1);s1(v1);},w1=Array.prototype.slice.call(arguments);w1.push(cb);r1.apply(r1,w1);});};};},{"fidelity":6}],4:[function(x1,y1,z1){'use strict';const A1=Symbol('circuit-breaker');class Status{constructor(B1){this.failures=0;this.fallbacks=0;this.successes=0;this.rejects=0;this.fires=0;this.timeouts=0;this[A1]=B1;B1.on('success',()=>this.successes++);B1.on('failure',()=>this.failures++);B1.on('fallback',()=>this.fallbacks++);B1.on('timeout',()=>this.timeouts++);B1.on('fire',()=>this.fires++);B1.on('reject',()=>this.rejects++);}}y1.exports=z1=Status;},{}],5:[function(C1,D1,E1){function EventEmitter(){this._events=this._events||{};this._maxListeners=this._maxListeners||void 0;}D1.exports=EventEmitter;EventEmitter.EventEmitter=EventEmitter;EventEmitter.prototype._events=void 0;EventEmitter.prototype._maxListeners=void 0;EventEmitter.defaultMaxListeners=10;EventEmitter.prototype.setMaxListeners=function(n){if(!isNumber(n)||n<0||isNaN(n))throw TypeError('n must be a positive number');this._maxListeners=n;return this;};EventEmitter.prototype.emit=function(F1){var er,H1,I1,J1,i,K1;if(!this._events)this._events={};if(F1==='error'){if(!this._events.error||isObject(this._events.error)&&!this._events.error.length){er=arguments[1];if(er instanceof Error){throw er;}else{var L1=new Error('Uncaught, unspecified "error" event. ('+er+')');L1.context=er;throw L1;}}}H1=this._events[F1];if(isUndefined(H1))return!1;if(isFunction(H1)){switch(arguments.length){case 1:H1.call(this);break;case 2:H1.call(this,arguments[1]);break;case 3:H1.call(this,arguments[1],arguments[2]);break;default:J1=Array.prototype.slice.call(arguments,1);H1.apply(this,J1);}}else if(isObject(H1)){J1=Array.prototype.slice.call(arguments,1);K1=H1.slice();I1=K1.length;for(i=0;i<I1;i++)K1[i].apply(this,J1);}return!0;};EventEmitter.prototype.addListener=function(M1,N1){var m;if(!isFunction(N1))throw TypeError('listener must be a function');if(!this._events)this._events={};if(this._events.newListener)this.emit('newListener',M1,isFunction(N1.listener)?N1.listener:N1);if(!this._events[M1])this._events[M1]=N1;else if(isObject(this._events[M1]))this._events[M1].push(N1);else this._events[M1]=[this._events[M1],N1];if(isObject(this._events[M1])&&!this._events[M1].warned){if(!isUndefined(this._maxListeners)){m=this._maxListeners;}else{m=EventEmitter.defaultMaxListeners;}if(m&&m>0&&this._events[M1].length>m){this._events[M1].warned=!0;console.error('(node) warning: possible EventEmitter memory '+'leak detected. %d listeners added. '+'Use emitter.setMaxListeners() to increase limit.',this._events[M1].length);if(typeof console.trace==='function'){console.trace();}}}return this;};EventEmitter.prototype.on=EventEmitter.prototype.addListener;EventEmitter.prototype.once=function(O1,P1){if(!isFunction(P1))throw TypeError('listener must be a function');var Q1=!1;function g(){this.removeListener(O1,g);if(!Q1){Q1=!0;P1.apply(this,arguments);}}g.listener=P1;this.on(O1,g);return this;};EventEmitter.prototype.removeListener=function(R1,S1){var T1,U1,V1,i;if(!isFunction(S1))throw TypeError('listener must be a function');if(!this._events||!this._events[R1])return this;T1=this._events[R1];V1=T1.length;U1=-1;if(T1===S1||isFunction(T1.listener)&&T1.listener===S1){delete this._events[R1];if(this._events.removeListener)this.emit('removeListener',R1,S1);}else if(isObject(T1)){for(i=V1;i-->0;){if(T1[i]===S1||T1[i].listener&&T1[i].listener===S1){U1=i;break;}}if(U1<0)return this;if(T1.length===1){T1.length=0;delete this._events[R1];}else{T1.splice(U1,1);}if(this._events.removeListener)this.emit('removeListener',R1,S1);}return this;};EventEmitter.prototype.removeAllListeners=function(W1){var X1,Y1;if(!this._events)return this;if(!this._events.removeListener){if(arguments.length===0)this._events={};else if(this._events[W1])delete this._events[W1];return this;}if(arguments.length===0){for(X1 in this._events){if(X1==='removeListener')continue;this.removeAllListeners(X1);}this.removeAllListeners('removeListener');this._events={};return this;}Y1=this._events[W1];if(isFunction(Y1)){this.removeListener(W1,Y1);}else if(Y1){while(Y1.length)this.removeListener(W1,Y1[Y1.length-1]);}delete this._events[W1];return this;};EventEmitter.prototype.listeners=function(Z1){var a2;if(!this._events||!this._events[Z1])a2=[];else if(isFunction(this._events[Z1]))a2=[this._events[Z1]];else a2=this._events[Z1].slice();return a2;};EventEmitter.prototype.listenerCount=function(b2){if(this._events){var c2=this._events[b2];if(isFunction(c2))return 1;else if(c2)return c2.length;}return 0;};EventEmitter.listenerCount=function(d2,e2){return d2.listenerCount(e2);};function isFunction(f2){return typeof f2==='function';}function isNumber(g2){return typeof g2==='number';}function isObject(h2){return typeof h2==='object'&&h2!==null;}function isUndefined(i2){return i2===void 0;}},{}],6:[function(j2,k2,l2){(function(m2){(function(){'use strict';var n2=typeof m2==='object'&&m2&&m2.Object===Object&&m2,o2=n2||Function('return this')();const p2=0,q2=1,r2=2,s2=Symbol('handlers'),t2=Symbol('queue'),u2=Symbol('state'),v2=Symbol('value');class FidelityPromise{constructor(fn){this[t2]=[];this[s2]=new Handlers();this[u2]=p2;this[v2]=void 0;const x2=typeof fn;if(x2==='function'){tryFunction(fn,this);}else if(x2!=='undefined'){resolvePromise(this,fn);}}get state(){return this[u2];}get value(){return this[v2];}then(y2,z2){const A2=new FidelityPromise();if(typeof y2==='function'){A2[s2].fulfill=y2;}if(typeof z2==='function'){A2[s2].reject=z2;}this[t2].push(A2);process(this);return A2;}catch(B2){return this.then(null,B2);}static promise(fn){console.error('Fidelity.promise() is deprecated. Use `new Fidelity.Promise()`.');return new FidelityPromise(fn);}static deferred(){let D2,E2;const p=new FidelityPromise((F2,G2)=>{D2=F2;E2=G2;});return{promise:p,resolve:H2=>D2(H2),reject:I2=>E2(I2)};}static resolve(J2){if(J2&&J2.then)return J2;switch(J2){case null:return W2;case!0:return U2;case!1:return V2;case 0:return X2;case'':return Y2;}const p=new FidelityPromise();p[u2]=q2;p[v2]=J2;return p;}static reject(K2){const p=new FidelityPromise();p[u2]=r2;p[v2]=K2;return p;}static all(){const L2=[],M2=Array.from(arguments).reduce((a,b)=>a.concat(b),[]),N2=M2.reduce((O2,p)=>O2.then(()=>p).then(r=>L2.push(r)),Promise.resolve(null));return N2.then(_=>L2);}static race(){const P2=Array.from(arguments).reduce((a,b)=>a.concat(b),[]);return new FidelityPromise((Q2,R2)=>{P2.forEach(p=>p.then(Q2).catch(R2));});}}FidelityPromise.PENDING=p2;FidelityPromise.FULFILLED=q2;FidelityPromise.REJECTED=r2;class Handlers{constructor(){this.fulfill=null;this.reject=null;}}const S2=(()=>{if(o2.process&&typeof o2.process.nextTick==='function'){return o2.process.nextTick;}else if(typeof o2.setImmediate==='function'){return o2.setImmediate;}else if(typeof o2.setTimeout==='function'){return(f,p)=>o2.setTimeout(f,0,p);}else{console.error('No nextTick. How we gonna do this?');return(f,p)=>f.call(this,p);}})();function exportModule(T2){if(typeof k2==='object'&&k2.exports){k2.exports=T2;}else{o2[T2.name]=T2;}}const U2=new FidelityPromise(!0),V2=new FidelityPromise(!1),W2=new FidelityPromise(null),X2=new FidelityPromise(0),Y2=new FidelityPromise('');function tryFunction(fn,a3){try{fn(v=>resolvePromise(a3,v),r=>transition(a3,r2,r));}catch(e){transition(a3,r2,e);}}function resolvePromise(p,x){if(x===p){transition(p,r2,new TypeError('The promise and its value are the same.'));return;}const b3=typeof x;if(x&&(b3==='function'||b3==='object')){let c3=!1;try{const d3=x.then;if(d3&&typeof d3==='function'){d3.call(x,y=>{if(!c3){resolvePromise(p,y);c3=!0;}},r=>{if(!c3){transition(p,r2,r);c3=!0;}});}else{transition(p,q2,x);c3=!0;}}catch(e){if(!c3){transition(p,r2,e);c3=!0;}}}else{transition(p,q2,x);}}function process(p){if(p[u2]===p2)return;S2(processNextTick,p);return p;}function processNextTick(p){let e3,qp;while(p[t2].length){qp=p[t2].shift();if(p[u2]===q2){e3=qp[s2].fulfill||(v=>v);}else if(p[u2]===r2){e3=qp[s2].reject||(r=>{throw r;});}try{resolvePromise(qp,e3(p[v2]));}catch(e){transition(qp,r2,e);continue;}}}function transition(p,g3,h3){if(p[u2]===g3||p[u2]!==p2)return;p[u2]=g3;p[v2]=h3;return process(p);}exportModule(FidelityPromise);}).call(this);}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{});},{}]},{},[1,2,3,4]); | ||
@@ -15,7 +15,7 @@ (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
/** Detect free variable `global` from Node.js. */ | ||
// Detect free variable `global` from Node.js. | ||
const freeGlobal = typeof global === 'object' && global && global.Object === Object && global; | ||
/* eslint no-new-func: 0 */ | ||
/** Used as a reference to the global object. */ | ||
// Used as a reference to the global object. | ||
const root = freeGlobal || Function('return this')(); | ||
@@ -92,11 +92,2 @@ | ||
* Constructs a {@link CircuitBreaker}. | ||
* @fires 'fire' When the action is executed | ||
* @fires 'reject' When the breaker is open but fire() has been called | ||
* @fires 'timeout' When the breaker action has timed out | ||
* @fires 'success' when the breaker action completes successfully | ||
* @fires 'failure' when the breaker action fails | ||
* @fires 'open' when the breaker enters the 'open' state | ||
* @fires 'close' when the breaker enters the 'closed' state | ||
* @fires 'halfOpen' when the breaker enters the 'halfOpen' state | ||
* @fires 'fallback' when a fallback function has executed | ||
* @param action {function} The action to fire for this {@link CircuitBreaker} instance | ||
@@ -112,2 +103,3 @@ * @param options {Object} Options for the {@link CircuitBreaker}. | ||
* the breaker to `halfOpen` state, and trying the action again. | ||
* @fires CircuitBreaker#halfOpen | ||
*/ | ||
@@ -117,4 +109,2 @@ class CircuitBreaker extends EventEmitter { | ||
super(); | ||
if (typeof action !== 'function') this.action = () => action; | ||
else this.action = action; | ||
this.options = options; | ||
@@ -128,2 +118,11 @@ this.Promise = options.Promise; | ||
if (typeof action !== 'function') this.action = () => this.Promise.resolve(action); | ||
else this.action = action; | ||
/** | ||
* Emitted after options.resetTimeout has elapsed, allowing for | ||
* a single attempt to call the service again. If that attempt is | ||
* successful, the circuit will be closed. Otherwise it remains open. | ||
* @event CircuitBreaker#halfOpen | ||
*/ | ||
function _startTimer (circuit) { | ||
@@ -147,2 +146,3 @@ return () => { | ||
* Closes the breaker, allowing the action to execute again | ||
* @fires CircuitBreaker#close | ||
*/ | ||
@@ -154,2 +154,6 @@ close () { | ||
this[STATE] = CLOSED; | ||
/** | ||
* Emitted when the breaker is reset allowing the action to execute again | ||
* @event CircuitBreaker#close | ||
*/ | ||
this.emit('close'); | ||
@@ -163,2 +167,3 @@ } | ||
* that has been provided. | ||
* @fires CircuitBreaker#open | ||
*/ | ||
@@ -169,2 +174,6 @@ open () { | ||
this[STATE] = OPEN; | ||
/** | ||
* Emitted when the breaker action fails more than options.maxFailures | ||
* @event CircuitBreaker#open | ||
*/ | ||
this.emit('open'); | ||
@@ -206,5 +215,14 @@ } | ||
* a rejected Promise. | ||
* @param func {Function | CircuitBreaker} the fallback function to execute when the breaker | ||
* has opened or when a timeout or error occurs. | ||
* @return {@link CircuitBreaker} this | ||
*/ | ||
fallback (func) { | ||
this[FALLBACK_FUNCTION] = func; | ||
let fb = func; | ||
if (func instanceof CircuitBreaker) { | ||
fb = function () { | ||
return func.fire.apply(func, arguments); | ||
}; | ||
} | ||
this[FALLBACK_FUNCTION] = fb; | ||
return this; | ||
@@ -214,14 +232,31 @@ } | ||
/** | ||
* Execute the action for this circuit. | ||
* @returns a Promise that will be rejected if there is an error, the action | ||
* times out, or the action fails. If the action succeeds, or if there is a | ||
* fallback action that is executed, the Promise will resolve. | ||
* Execute the action for this circuit. If the action fails or times out, the | ||
* returned promise will be rejected. If the action succeeds, the promise will | ||
* resolve with the resolved value from action. | ||
* | ||
* @return {@link Promise} a Promise that resolves on success and is rejected | ||
* on failure of the action. | ||
* | ||
* @fires CircuitBreaker#failure | ||
* @fires CircuitBreaker#fallback | ||
* @fires CircuitBreaker#fire | ||
* @fires CircuitBreaker#reject | ||
* @fires CircuitBreaker#success | ||
* @fires CircuitBreaker#timeout | ||
*/ | ||
fire () { | ||
const args = Array.prototype.slice.call(arguments); | ||
/** | ||
* Emitted when the breaker action is executed | ||
* @event CircuitBreaker#fire | ||
*/ | ||
this.emit('fire', args); | ||
if (this.opened || (this.halfOpen && this[PENDING_CLOSE])) { | ||
/** | ||
* Emitted when the breaker is open and failing fast | ||
* @event CircuitBreaker#reject | ||
*/ | ||
this.emit('reject', new Error('Breaker is open')); | ||
return failFast(this, 'Breaker is open', args); | ||
return fail(this, 'Breaker is open', args); | ||
} | ||
@@ -234,14 +269,27 @@ this[PENDING_CLOSE] = this.halfOpen; | ||
return new this.Promise((resolve, reject) => { | ||
const timeout = setTimeout( | ||
timeout = setTimeout( | ||
() => { | ||
timeoutError = true; | ||
const error = new Error(`Timed out after ${this.options.timeout}ms`); | ||
/** | ||
* Emitted when the breaker action takes longer than options.timeout | ||
* @event CircuitBreaker#timeout | ||
*/ | ||
this.emit('timeout', error); | ||
failFast(this, error, args); | ||
fail(this, error, args); | ||
reject(error); | ||
}, this.options.timeout); | ||
Promise.resolve(this.action.apply(this.action, args)) | ||
const result = this.action.apply(this.action, args); | ||
const promise = (typeof result.then === 'function') | ||
? result | ||
: this.Promise.resolve(result); | ||
promise | ||
.then((result) => { | ||
if (!timeoutError) { | ||
/** | ||
* Emitted when the breaker action succeeds | ||
* @event CircuitBreaker#success | ||
*/ | ||
this.emit('success', result); | ||
@@ -253,3 +301,3 @@ resolve(result); | ||
.catch((error) => { | ||
failFast(this, error, args); | ||
fail(this, error, args); | ||
reject(error); | ||
@@ -261,3 +309,3 @@ clearTimeout(timeout); | ||
clearTimeout(timeout); | ||
return failFast(this, error, args); | ||
return fail(this, error, args); | ||
} | ||
@@ -267,3 +315,7 @@ } | ||
function failFast (circuit, err, args) { | ||
function fail (circuit, err, args) { | ||
/** | ||
* Emitted when the breaker action fails | ||
* @event CircuitBreaker#failure | ||
*/ | ||
circuit.emit('failure', err); | ||
@@ -279,2 +331,6 @@ circuit[NUM_FAILURES] += 1; | ||
const result = circuit[FALLBACK_FUNCTION].apply(circuit[FALLBACK_FUNCTION], args); | ||
/** | ||
* Emitted when the breaker executes a fallback function | ||
* @event CircuitBreaker#fallback | ||
*/ | ||
circuit.emit('fallback', result); | ||
@@ -281,0 +337,0 @@ resolve(result); |
@@ -13,7 +13,7 @@ 'use strict'; | ||
/** Detect free variable `global` from Node.js. */ | ||
// Detect free variable `global` from Node.js. | ||
const freeGlobal = typeof global === 'object' && global && global.Object === Object && global; | ||
/* eslint no-new-func: 0 */ | ||
/** Used as a reference to the global object. */ | ||
// Used as a reference to the global object. | ||
const root = freeGlobal || Function('return this')(); | ||
@@ -20,0 +20,0 @@ |
@@ -19,11 +19,2 @@ 'use strict'; | ||
* Constructs a {@link CircuitBreaker}. | ||
* @fires 'fire' When the action is executed | ||
* @fires 'reject' When the breaker is open but fire() has been called | ||
* @fires 'timeout' When the breaker action has timed out | ||
* @fires 'success' when the breaker action completes successfully | ||
* @fires 'failure' when the breaker action fails | ||
* @fires 'open' when the breaker enters the 'open' state | ||
* @fires 'close' when the breaker enters the 'closed' state | ||
* @fires 'halfOpen' when the breaker enters the 'halfOpen' state | ||
* @fires 'fallback' when a fallback function has executed | ||
* @param action {function} The action to fire for this {@link CircuitBreaker} instance | ||
@@ -39,2 +30,3 @@ * @param options {Object} Options for the {@link CircuitBreaker}. | ||
* the breaker to `halfOpen` state, and trying the action again. | ||
* @fires CircuitBreaker#halfOpen | ||
*/ | ||
@@ -44,4 +36,2 @@ class CircuitBreaker extends EventEmitter { | ||
super(); | ||
if (typeof action !== 'function') this.action = () => action; | ||
else this.action = action; | ||
this.options = options; | ||
@@ -55,2 +45,11 @@ this.Promise = options.Promise; | ||
if (typeof action !== 'function') this.action = () => this.Promise.resolve(action); | ||
else this.action = action; | ||
/** | ||
* Emitted after options.resetTimeout has elapsed, allowing for | ||
* a single attempt to call the service again. If that attempt is | ||
* successful, the circuit will be closed. Otherwise it remains open. | ||
* @event CircuitBreaker#halfOpen | ||
*/ | ||
function _startTimer (circuit) { | ||
@@ -74,2 +73,3 @@ return () => { | ||
* Closes the breaker, allowing the action to execute again | ||
* @fires CircuitBreaker#close | ||
*/ | ||
@@ -81,2 +81,6 @@ close () { | ||
this[STATE] = CLOSED; | ||
/** | ||
* Emitted when the breaker is reset allowing the action to execute again | ||
* @event CircuitBreaker#close | ||
*/ | ||
this.emit('close'); | ||
@@ -90,2 +94,3 @@ } | ||
* that has been provided. | ||
* @fires CircuitBreaker#open | ||
*/ | ||
@@ -96,2 +101,6 @@ open () { | ||
this[STATE] = OPEN; | ||
/** | ||
* Emitted when the breaker action fails more than options.maxFailures | ||
* @event CircuitBreaker#open | ||
*/ | ||
this.emit('open'); | ||
@@ -133,5 +142,14 @@ } | ||
* a rejected Promise. | ||
* @param func {Function | CircuitBreaker} the fallback function to execute when the breaker | ||
* has opened or when a timeout or error occurs. | ||
* @return {@link CircuitBreaker} this | ||
*/ | ||
fallback (func) { | ||
this[FALLBACK_FUNCTION] = func; | ||
let fb = func; | ||
if (func instanceof CircuitBreaker) { | ||
fb = function () { | ||
return func.fire.apply(func, arguments); | ||
}; | ||
} | ||
this[FALLBACK_FUNCTION] = fb; | ||
return this; | ||
@@ -141,14 +159,31 @@ } | ||
/** | ||
* Execute the action for this circuit. | ||
* @returns a Promise that will be rejected if there is an error, the action | ||
* times out, or the action fails. If the action succeeds, or if there is a | ||
* fallback action that is executed, the Promise will resolve. | ||
* Execute the action for this circuit. If the action fails or times out, the | ||
* returned promise will be rejected. If the action succeeds, the promise will | ||
* resolve with the resolved value from action. | ||
* | ||
* @return {@link Promise} a Promise that resolves on success and is rejected | ||
* on failure of the action. | ||
* | ||
* @fires CircuitBreaker#failure | ||
* @fires CircuitBreaker#fallback | ||
* @fires CircuitBreaker#fire | ||
* @fires CircuitBreaker#reject | ||
* @fires CircuitBreaker#success | ||
* @fires CircuitBreaker#timeout | ||
*/ | ||
fire () { | ||
const args = Array.prototype.slice.call(arguments); | ||
/** | ||
* Emitted when the breaker action is executed | ||
* @event CircuitBreaker#fire | ||
*/ | ||
this.emit('fire', args); | ||
if (this.opened || (this.halfOpen && this[PENDING_CLOSE])) { | ||
/** | ||
* Emitted when the breaker is open and failing fast | ||
* @event CircuitBreaker#reject | ||
*/ | ||
this.emit('reject', new Error('Breaker is open')); | ||
return failFast(this, 'Breaker is open', args); | ||
return fail(this, 'Breaker is open', args); | ||
} | ||
@@ -161,14 +196,27 @@ this[PENDING_CLOSE] = this.halfOpen; | ||
return new this.Promise((resolve, reject) => { | ||
const timeout = setTimeout( | ||
timeout = setTimeout( | ||
() => { | ||
timeoutError = true; | ||
const error = new Error(`Timed out after ${this.options.timeout}ms`); | ||
/** | ||
* Emitted when the breaker action takes longer than options.timeout | ||
* @event CircuitBreaker#timeout | ||
*/ | ||
this.emit('timeout', error); | ||
failFast(this, error, args); | ||
fail(this, error, args); | ||
reject(error); | ||
}, this.options.timeout); | ||
Promise.resolve(this.action.apply(this.action, args)) | ||
const result = this.action.apply(this.action, args); | ||
const promise = (typeof result.then === 'function') | ||
? result | ||
: this.Promise.resolve(result); | ||
promise | ||
.then((result) => { | ||
if (!timeoutError) { | ||
/** | ||
* Emitted when the breaker action succeeds | ||
* @event CircuitBreaker#success | ||
*/ | ||
this.emit('success', result); | ||
@@ -180,3 +228,3 @@ resolve(result); | ||
.catch((error) => { | ||
failFast(this, error, args); | ||
fail(this, error, args); | ||
reject(error); | ||
@@ -188,3 +236,3 @@ clearTimeout(timeout); | ||
clearTimeout(timeout); | ||
return failFast(this, error, args); | ||
return fail(this, error, args); | ||
} | ||
@@ -194,3 +242,7 @@ } | ||
function failFast (circuit, err, args) { | ||
function fail (circuit, err, args) { | ||
/** | ||
* Emitted when the breaker action fails | ||
* @event CircuitBreaker#failure | ||
*/ | ||
circuit.emit('failure', err); | ||
@@ -206,2 +258,6 @@ circuit[NUM_FAILURES] += 1; | ||
const result = circuit[FALLBACK_FUNCTION].apply(circuit[FALLBACK_FUNCTION], args); | ||
/** | ||
* Emitted when the breaker executes a fallback function | ||
* @event CircuitBreaker#fallback | ||
*/ | ||
circuit.emit('fallback', result); | ||
@@ -208,0 +264,0 @@ resolve(result); |
{ | ||
"name": "opossum", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"author": "Red Hat, Inc.", | ||
@@ -10,3 +10,2 @@ "license": "Apache-2.0", | ||
"build:browser": "browserify index.js lib/*.js > dist/opossum.js", | ||
"build:browser-test": "browserify ./test/test.js > browser-test.js", | ||
"build:compress": "escompress dist/opossum.js > dist/opossum-min.js", | ||
@@ -18,10 +17,10 @@ "build:docs": "jsdoc --verbose -d docs -t ./node_modules/ink-docstrap/template -R README.md index.js lib", | ||
"test:console": "tape test/*.js | tap-spec", | ||
"test:headless": "cat browser-test.js | tape-run", | ||
"test:headless": "browserify ./test/test.js | tape-run", | ||
"pretest:browser": "npm run build", | ||
"test:browser": "browserify ./test/test.js > test/browser/browserified-tests.js && opener http://localhost:9007/test/browser/index.html && http-server . -p 9007", | ||
"test:coverage": "istanbul cover tape test/*.js", | ||
"prepublish": "nsp check && npm run build:browser && npm run build:browser-test", | ||
"prepublish": "nsp check && npm run build:browser", | ||
"postpublish": "./publish-docs.sh", | ||
"prerelease": "npm test", | ||
"release": "standard-version", | ||
"release": "standard-version -s", | ||
"lint": "eslint test/*.js index.js lib/*.js", | ||
@@ -28,0 +27,0 @@ "dependency-check": "szero . --ci" |
137
README.md
@@ -67,2 +67,111 @@ # opossum | ||
### Browser | ||
Opossum really shines in a browser. You can use it to guard against network failures in your AJAX calls. A browserified version of module is available | ||
as a compressed file, or exploded in the `dist` folder. | ||
Here is an example using [hapi.js](hapijs.com). See the | ||
[examples](https://github.com/bucharest-gold/opossum/tree/master/examples/) | ||
folder for more detail. | ||
```js | ||
// server.js | ||
const server = new Hapi.Server(); | ||
server.register(require('inert', (err) => possibleError(err))); | ||
server.route({ | ||
method: 'GET', | ||
path: '/opossum.js', | ||
handler: { | ||
file: { | ||
path: path.join(__dirname, 'node_modules', 'opossum', 'dist', 'opossum-min.js'), | ||
} | ||
} | ||
}); | ||
``` | ||
```html | ||
<html> | ||
<head> | ||
<title>My Super App</title> | ||
<script type='text/javascript' src="/jquery.js"></script> | ||
<script type='text/javascript' src="/opossum.js"></script> | ||
<script type='text/javascript' src="/app.js"></script> | ||
<body> | ||
... | ||
</body> | ||
</head> | ||
</html> | ||
``` | ||
```js | ||
// app.js | ||
const route = 'https://example-service.com/rest/route'; | ||
const circuitBreakerOptions = { | ||
timeout: 500, | ||
maxFailures: 3, | ||
resetTimeout: 5000 | ||
}; | ||
const circuit = circuitBreaker(() => $.get(route), circuitBreakerOptions); | ||
circuit.fallback(() => `${route} unavailable right now. Try later.`)); | ||
circuit.on('success', (result) => $(element).append(JSON.stringify(result)})); | ||
$(() => { | ||
$('#serviceButton').click(() => circuit.fire().catch((e) => console.error(e))); | ||
}); | ||
``` | ||
### Events | ||
A `CircuitBreaker` will emit events for important things that occur. | ||
Here are the events you can listen for. | ||
* `fire` - emitted when the breaker is fired. | ||
* `reject` - emitted when the breaker is open (or halfOpen). | ||
* `timeout` - emitted when the breaker action times out. | ||
* `success` - emitted when the breaker action completes successfully | ||
* `failure` - emitted when the breaker action fails, called with the error | ||
* `open` - emitted when the breaker state changes to `open` | ||
* `close` - emitted when the breaker state changes to `closed` | ||
* `halfOpen` - emitted when the breaker state changes to `halfOpen` | ||
* `fallback` - emitted when the breaker has a fallback function and executes it | ||
Handling events gives a greater level of control over your application behavior. | ||
```js | ||
const circuit = circuitBreaker(() => $.get(route), circuitBreakerOptions); | ||
circuit.fallback(() => ({ body: `${route} unavailable right now. Try later.` })); | ||
circuit.on('success', | ||
(result) => $(element).append( | ||
makeNode(`SUCCESS: ${JSON.stringify(result)}`))); | ||
circuit.on('timeout', | ||
() => $(element).append( | ||
makeNode(`TIMEOUT: ${route} is taking too long to respond.`))); | ||
circuit.on('reject', | ||
() => $(element).append( | ||
makeNode(`REJECTED: The breaker for ${route} is open. Failing fast.`))); | ||
circuit.on('open', | ||
() => $(element).append( | ||
makeNode(`OPEN: The breaker for ${route} just opened.`))); | ||
circuit.on('halfOpen', | ||
() => $(element).append( | ||
makeNode(`HALF_OPEN: The breaker for ${route} is half open.`))); | ||
circuit.on('close', | ||
() => $(element).append( | ||
makeNode(`CLOSE: The breaker for ${route} has closed. Service OK.`))); | ||
circuit.on('fallback', | ||
(data) => $(element).append( | ||
makeNode(`FALLBACK: ${JSON.stringify(data)}`))); | ||
``` | ||
### Promises vs. Callbacks | ||
@@ -112,29 +221,1 @@ The `opossum` API uses a `Promise` as a return value for a breaker that | ||
``` | ||
### Events | ||
A `CircuitBreaker` will emit events for important things that occur. | ||
Here are the events you can listen for. | ||
* `fire` (or `execute`) - emitted when the breaker is fired. | ||
* `reject` - emitted when the breaker is open (or halfOpen). | ||
* `timeout` - emitted when the breaker action times out. | ||
* `success` - emitted when the breaker action completes successfully | ||
* `failure` - emitted when the breaker action fails, called with the error | ||
* `open` - emitted when the breaker state changes to `open` | ||
* `close` - emitted when the breaker state changes to `closed` | ||
* `halfOpen` - emitted when the breaker state changes to `halfOpen` | ||
* `fallback` - emitted when the breaker has a fallback function and executes it | ||
### Development | ||
Contributions to Opossum are welcome! When contributing, be sure that you've added a test for any code changes you've made, and that `make test` passes. | ||
### Releasing | ||
* Make sure everything works: `make clean && npm install && make ci` | ||
* Run standard-version: `npm run release` | ||
* Push to GitHub: `git push --follow-tags origin master` | ||
* Publish to npmjs.com: `npm publish` | ||
* Assuming all goes well, head over to https://github.com/bucharest-gold/opossum/releases and update the release with any relevant notes. The generated CHANGELOG.md file should be updated, so you can use it to document release changes. | ||
* Tweet, blog and otherwise promote your awesome success! |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
67659
1295
220