UNPKG

5.41 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const events_1 = require("events");
4const LogManager_1 = require("../log/LogManager");
5class LifecycleState {
6 constructor(name, value) {
7 this.name = name;
8 this.value = value;
9 LifecycleState.all.push(this);
10 LifecycleState.all.sort((a, b) => {
11 if (a.getValue() < b.getValue()) {
12 return -1;
13 }
14 if (a.getValue() === b.getValue()) {
15 return 0;
16 }
17 return 1;
18 });
19 }
20 static getStatesBefore(val) {
21 return LifecycleState.all.filter((state) => state.getValue() < val.getValue());
22 }
23 toString() {
24 return this.name;
25 }
26 getName() {
27 return this.name;
28 }
29 getValue() {
30 return this.value;
31 }
32 isAfter(other) {
33 return this.getValue() > other.getValue();
34 }
35 isAtOrAfter(other) {
36 return !this.isBefore(other);
37 }
38 isBefore(other) {
39 return this.getValue() < other.getValue();
40 }
41 isAtOrBefore(other) {
42 return !this.isAfter(other);
43 }
44}
45LifecycleState.all = [];
46LifecycleState.NOT_STARTED = new LifecycleState('NOT_STARTED', 0);
47LifecycleState.STARTING = new LifecycleState('STARTING', 1000);
48LifecycleState.STARTED = new LifecycleState('STARTED', 2000);
49LifecycleState.STOPPING = new LifecycleState('STOPPING', 10000);
50LifecycleState.STOPPED = new LifecycleState('STOPPED', 10001);
51exports.LifecycleState = LifecycleState;
52// STATES.all = Object.keys(STATES).filter((n) => n !== 'fromValue' && n !== 'all');
53class LifecycleException extends Error {
54 constructor(message, context) {
55 super(message);
56 this.context = context;
57 }
58 getContext() {
59 return this.context;
60 }
61}
62exports.LifecycleException = LifecycleException;
63class Lifecycle extends events_1.EventEmitter {
64 constructor(name, logger) {
65 super();
66 this.name = name;
67 this.logger = logger || LogManager_1.LogManager.getLogger(__filename);
68 this.status = LifecycleState.NOT_STARTED;
69 }
70 /**
71 * Initiates the lifecycle of this object.
72 * This is the method you should call before using the object
73 *
74 * @return {Promise<void>} A promise that will resolve when this object's lifecycle has started
75 */
76 lcStart() {
77 return new Promise((resolve, reject) => {
78 if (!this.setStatus(LifecycleState.STARTING)) {
79 reject(new Error(`Can't start object ${this.name}. It's on state ${this.status}`));
80 }
81 else {
82 this.startTime = Date.now();
83 resolve();
84 }
85 })
86 .then(() => this.doStart())
87 .then(() => {
88 this.setStatus(LifecycleState.STARTED, { elapsed: (Date.now() - this.startTime) });
89 })
90 .catch((err) => {
91 if (this.logger) {
92 this.logger.error({ err }, `There was an error starting element ${this.name}`);
93 }
94 throw err;
95 });
96 }
97 lcStop() {
98 return new Promise((resolve, reject) => {
99 if (!this.setStatus(LifecycleState.STOPPING)) {
100 reject(new Error(`Can't stop object ${this.name}. It's on state ${this.status}`));
101 }
102 else {
103 this.stopTime = Date.now();
104 resolve();
105 }
106 })
107 .then(() => this.doStop())
108 .then(() => {
109 this.setStatus(LifecycleState.STOPPED, { elapsed: (Date.now() - this.startTime) });
110 })
111 .catch((err) => {
112 if (this.logger) {
113 this.logger.error({ err }, `There was an error stopping element ${this.name}`);
114 }
115 throw err;
116 });
117 }
118 setStatus(newStatus, eventPayload) {
119 if (newStatus.getValue() < this.status.getValue()) {
120 throw new LifecycleException(`Can't revert on the status chain. Object "${this.name}" can't go from ${this.status} to ${newStatus}`);
121 }
122 if (newStatus.getValue() === this.status.getValue()) {
123 return false;
124 }
125 if (this.logger) {
126 this.logger.debug(`Switching state for object ${this.name} from ${this.status} to ${newStatus}`);
127 }
128 this.status = newStatus;
129 this.emit(newStatus.getName(), this.name, eventPayload);
130 // Cleanup references to listeners that we may have skipped if any as they will never be called
131 LifecycleState.getStatesBefore(newStatus).forEach((state) => this.removeAllListeners(state.getName()));
132 return true;
133 }
134 getName() {
135 return this.name;
136 }
137 onState(state, callback) {
138 this.on(state.getName(), callback);
139 }
140 onStateOnce(state, callback) {
141 this.once(state.getName(), callback);
142 }
143 assertState(state) {
144 if (this.status !== state) {
145 throw new LifecycleException(`Operation requires state to be ${state.getName()} but is ${this.status.getName()}`);
146 }
147 }
148 getLogger() {
149 return this.logger;
150 }
151 copy() {
152 return this.constructor(this.name, this.logger);
153 }
154 getStatus() {
155 return this.status;
156 }
157 setLogger(logger) {
158 this.logger = logger;
159 }
160}
161exports.Lifecycle = Lifecycle;
162//# sourceMappingURL=Lifecycle.js.map
\No newline at end of file