bundle-context.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /**
  2. * TODO here:
  3. * Create try catch in start and stop: modules are not being unloaded/reloaded if there is exception in stop
  4. * Improve fields, solve redundancy, on "on" and "after"
  5. * Maybe use the XPrefix to create an endpoint named events or fetch a channel
  6. * channel should work for emit aswell
  7. *
  8. * Separate vars in several contexts
  9. *
  10. * For the endpoint when bundle is stopped we could
  11. *
  12. * */
  13. var log = require('hlogger').createLogger('bundle-context');
  14. /**
  15. * Check method in bundleActivator if not check as bundleMethod
  16. */
  17. function solveMethod(instance,name) {
  18. if(instance.bundleActivator != undefined && instance.bundleActivator[name]!= undefined ) {
  19. return (context) => {instance.bundleActivator[name](context)};
  20. }
  21. var subName = "bundle" + name[0].toUpperCase() + name.slice(1);
  22. if(instance[subName] != undefined ) {
  23. return (context) => {instance[subName](context)};
  24. }
  25. return null;
  26. }
  27. // Maybe create channel code here and completelly remove on here
  28. //
  29. // This will contain the listeners for Activator
  30. class BundleContext /*extends XEventEmitter*/ {
  31. constructor(conf) {
  32. /*super();*/
  33. var info = {};
  34. ({id:info.id,
  35. name:info.name,
  36. manager:info.manager,
  37. instance:info.instance,
  38. modulePath:info.modulePath,
  39. pkgInfo:info.pkgInfo} = conf);
  40. //info = fromFields(["id","name","manager","instance","modulePath","pkgInfo"],conf);
  41. info.state = 0;
  42. info.loadDate = new Date();
  43. this.info = info;
  44. this._bundleContext = {
  45. intervals:[],
  46. timeouts:[],
  47. instanceStart: null,
  48. instanceStop: null
  49. };
  50. var dummyFunc = () => {};
  51. this._bundleContext.instanceStart = solveMethod(this.instance,"start") || dummyFunc;
  52. this._bundleContext.instanceStop = solveMethod(this.instance,"stop") || dummyFunc;
  53. }
  54. get id() {
  55. return this.info.id;
  56. }
  57. get modulePath() {
  58. return this.info.modulePath;
  59. }
  60. get name() {
  61. return this.info.name;
  62. }
  63. get instance() {
  64. return this.info.instance;
  65. }
  66. get manager() {
  67. return this.info.manager;
  68. }
  69. get version() {
  70. return this.info.version;
  71. }
  72. start() {
  73. if(this.info.state == 1) {
  74. log.warn("Instance is turned on trying to turn off first");
  75. this.stop();
  76. }
  77. process.nextTick(() => {
  78. try {
  79. this._bundleContext.instanceStart(this);
  80. } catch(e) {
  81. log.error("Bundle start error: " + this.name + "\n",e);
  82. }
  83. this.manager.events.toggleOn(this.name,this.instance);
  84. this.info.state = 1;
  85. this.info.startDate = new Date();
  86. });
  87. }
  88. stop() {
  89. if(this.info.state == 0) return;
  90. this.toggleOff("start");
  91. this.emit("stop");
  92. try {
  93. this._bundleContext.instanceStop(this);
  94. } catch( e) {
  95. log.error("Bundle stop error: " + this.name + "\n",e);
  96. }
  97. this.clearIntervals();
  98. this.clearTimeouts();
  99. this.manager.events.removeListener(this);
  100. this.info.state = 0;
  101. }
  102. /* Event wrappers */
  103. removeListener(ename) {
  104. this.manager.events.removeListener(this,ename);
  105. }
  106. emit(ename,arg,cb) {
  107. return this.manager.events.emit(this.name+":"+ename,arg,cb);
  108. }
  109. toggleOn(ename,arg) {
  110. this.manager.events.toggleOn(this.name+":"+ename,arg);
  111. }
  112. toggleOff(ename) {
  113. this.manager.events.toggleOff(this.name+":"+ename);
  114. }
  115. on(...args) {
  116. var cb = args.pop();
  117. var evtName = args.join(":");
  118. this.manager.events.on(this,evtName ,cb);
  119. return this;
  120. }
  121. after(...args) {
  122. var cb = args.pop();
  123. var evtName = args.join(":")
  124. this.manager.events.after(this,evtName ,cb);
  125. return this;
  126. }
  127. // Channel
  128. prefix(name) {
  129. return this.manager.events.prefix(this,name);
  130. }
  131. // Wrappers
  132. /**
  133. * @param {array} args
  134. * @param {function} callback
  135. */
  136. with(args,callback) {
  137. return this.manager.with(args,callback);
  138. }
  139. /**
  140. * @param {string} match
  141. * @param {variable} ...args
  142. */
  143. call(name,...args) {
  144. return this.manager.call(name,args);
  145. }
  146. /*
  147. get(name) {
  148. var ctx = this.manager.get(name);
  149. if(ctx == null || ctx.info.state != 1) {
  150. // Early bail
  151. return null;
  152. }
  153. return ctx.instance;
  154. }*/
  155. // Auto clear helpers
  156. //
  157. setInterval(cb,n) {
  158. var ret = setInterval(cb,n);
  159. this._bundleContext.intervals.push(ret);
  160. return ret;
  161. }
  162. clearIntervals() {
  163. this._bundleContext.intervals.forEach((v) => {
  164. clearInterval(v);
  165. });
  166. }
  167. setTimeout(cb,n) {
  168. var ret = setTimeout(cb,n);
  169. this._bundleContext.timeouts.push(ret);
  170. return ret;
  171. }
  172. clearTimeouts() {
  173. this._bundleContext.timeouts.forEach((v) => {
  174. clearTimeout(v);
  175. });
  176. }
  177. }
  178. module.exports = BundleContext;