1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const events_1 = require("events");
|
4 | const LogManager_1 = require("../log/LogManager");
|
5 | class 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 | }
|
45 | LifecycleState.all = [];
|
46 | LifecycleState.NOT_STARTED = new LifecycleState('NOT_STARTED', 0);
|
47 | LifecycleState.STARTING = new LifecycleState('STARTING', 1000);
|
48 | LifecycleState.STARTED = new LifecycleState('STARTED', 2000);
|
49 | LifecycleState.STOPPING = new LifecycleState('STOPPING', 10000);
|
50 | LifecycleState.STOPPED = new LifecycleState('STOPPED', 10001);
|
51 | exports.LifecycleState = LifecycleState;
|
52 |
|
53 | class LifecycleException extends Error {
|
54 | constructor(message, context) {
|
55 | super(message);
|
56 | this.context = context;
|
57 | }
|
58 | getContext() {
|
59 | return this.context;
|
60 | }
|
61 | }
|
62 | exports.LifecycleException = LifecycleException;
|
63 | class 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 |
|
72 |
|
73 |
|
74 |
|
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 |
|
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 | }
|
161 | exports.Lifecycle = Lifecycle;
|
162 |
|
\ | No newline at end of file |