fable 3.0.115 → 3.0.117

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fable",
3
- "version": "3.0.115",
3
+ "version": "3.0.117",
4
4
  "description": "Anentity behavior management and API bundling library.",
5
5
  "main": "source/Fable.js",
6
6
  "scripts": {
package/source/Fable.js CHANGED
@@ -72,11 +72,13 @@ class Fable extends libFableServiceBase.CoreServiceProviderBase
72
72
  this.addAndInstantiateServiceType('DataGeneration', require('./services/Fable-Service-DataGeneration.js'));
73
73
  this.addAndInstantiateServiceType('Utility', require('./services/Fable-Service-Utility.js'));
74
74
  this.addAndInstantiateServiceType('Math', require('./services/Fable-Service-Math.js'));
75
- this.addServiceType('Operation', require('./services/Fable-Service-Operation.js'));
76
75
  this.addServiceType('RestClient', require('./services/Fable-Service-RestClient.js'));
77
- this.addServiceType('CSVParser', require('./services/Fable-Service-CSVParser.js'));
78
76
  this.addServiceType('Manifest', require('manyfest'));
79
77
  this.addServiceType('ObjectCache', require('cachetrax'));
78
+ this.addServiceType('Operation', require('./services/Fable-Service-Operation.js'));
79
+ this.addServiceType('ProgressTracker', require('./services/Fable-Service-ProgressTracker.js'));
80
+ this.addAndInstantiateServiceType('ProgressTime', require('./services/Fable-Service-ProgressTime.js'));
81
+ this.addServiceType('CSVParser', require('./services/Fable-Service-CSVParser.js'));
80
82
  this.addServiceType('FilePersistence', require('./services/Fable-Service-FilePersistence.js'));
81
83
  }
82
84
 
@@ -31,7 +31,7 @@ class FableServiceDataGeneration extends libFableServiceBase
31
31
  randomNumericString(pLength, pMaxNumber)
32
32
  {
33
33
  let tmpLength = (typeof(pLength) === 'undefined') ? 10 : pLength;
34
- let tmpMaxNumber = (typeof(pMaxNumber) === 'undefined') ? ((10 ** tmpLength) - 1) : pMaxNumber;
34
+ let tmpMaxNumber = (typeof(pMaxNumber) === 'undefined') ? 9999999999 : pMaxNumber;
35
35
 
36
36
  return this.services.DataFormat.stringPadStart(this.randomIntegerUpTo(tmpMaxNumber), pLength, '0');
37
37
  }
@@ -1,11 +1,12 @@
1
1
  const libFableServiceBase = require('fable-serviceproviderbase');
2
2
 
3
3
  /**
4
- * Arbitrary Precision Math Operations
5
- * @author Steven Velozo <steven@velozo.com>
6
- * @description Simple functions that perform arbitrary precision math operations and return string resultant values. Wraps big.js
7
- */
8
-
4
+ * Arbitrary Precision Math Operations
5
+ * @author Steven Velozo <steven@velozo.com>
6
+ * @description Simple functions that perform arbitrary precision math operations and return string resultant values. Wraps big.js
7
+ * @class FableServiceMath
8
+ * @extends libFableServiceBase
9
+ */
9
10
  class FableServiceMath extends libFableServiceBase
10
11
  {
11
12
  constructor(pFable, pOptions, pServiceHash)
@@ -15,9 +16,8 @@ class FableServiceMath extends libFableServiceBase
15
16
  this.serviceType = 'Math';
16
17
  }
17
18
 
18
-
19
19
  /*
20
- Rounding Methods:
20
+ Pass-through Rounding Method Constants
21
21
 
22
22
  Property Value BigDecimal Equiv Description
23
23
  ---------- ----- ---------------- -----------
@@ -1,25 +1,20 @@
1
1
  module.exports = (
2
- {
3
- "Metadata": {
4
- "UUID": false,
5
- "Hash": false,
2
+ {
3
+ "Metadata": {
4
+ "UUID": false,
5
+ "Hash": false,
6
6
 
7
- "Name": "",
8
- "Summary": "",
7
+ "Name": "",
8
+ "Summary": "",
9
9
 
10
- "Version": 0
11
- },
12
- "Status": {
13
- "Completed": false,
14
-
15
- "CompletionProgress": 0,
16
- "CompletionTimeElapsed": 0,
17
-
18
- "TimeStart": 0,
19
- "TimeEnd": 0
20
- },
21
- "Steps": [],
22
- "Errors": [],
23
- "Log": []
24
- }
10
+ "Version": 0
11
+ },
12
+ "Status": {
13
+ "Completed": false,
14
+ "StepCount": 0
15
+ },
16
+ "Steps": [],
17
+ "Errors": [],
18
+ "Log": []
19
+ }
25
20
  );
@@ -1,3 +1,4 @@
1
+ const { PE } = require('big.js');
1
2
  const libFableServiceBase = require('fable-serviceproviderbase');
2
3
 
3
4
  const _OperationStatePrototypeString = JSON.stringify(require('./Fable-Service-Operation-DefaultSettings.js'));
@@ -12,9 +13,6 @@ class FableOperation extends libFableServiceBase
12
13
  // Timestamps will just be the long ints
13
14
  this.timeStamps = {};
14
15
 
15
- // ProgressTrackers have an object format of: {Hash:'SomeHash',EndTime:UINT,CurrentTime:UINT,TotalCount:INT,CurrentCount:INT}
16
- this.progressTrackers = {};
17
-
18
16
  this.serviceType = 'PhasedOperation';
19
17
 
20
18
  this.state = JSON.parse(_OperationStatePrototypeString);
@@ -29,96 +27,134 @@ class FableOperation extends libFableServiceBase
29
27
  this.state.Metadata.Name = (typeof(this.options.Name) == 'string') ? this.options.Name : `Unnamed Operation ${this.state.Metadata.UUID}`;
30
28
  this.name = this.state.Metadata.Name;
31
29
 
30
+ this.progressTrackers = this.fable.instantiateServiceProviderWithoutRegistration('ProgressTracker');
31
+
32
+ this.state.OverallProgressTracker = this.progressTrackers.createProgressTracker(`Overall-${this.state.Metadata.UUID}`);
33
+
34
+ // This is here to use the pass-through logging functions in the operation itself.
32
35
  this.log = this;
33
36
  }
34
37
 
35
38
  execute(fExecutionCompleteCallback)
36
39
  {
37
- if (this.state.Status.TimeStart)
40
+ // TODO: Should the same operation be allowed to execute more than one time?
41
+ if (this.state.OverallProgressTracker.StartTimeStamp > 0)
38
42
  {
39
43
  return fExecutionCompleteCallback(new Error(`Operation [${this.state.Metadata.UUID}] ${this.state.Metadata.Name} has already been executed!`));
40
44
  }
41
45
 
42
- this.state.Status.TimeStart = +new Date();
43
-
44
46
  let tmpAnticipate = this.fable.instantiateServiceProviderWithoutRegistration('Anticipate');
45
-
46
- for (let i = 0; i < this.state.Steps; i++)
47
- {
48
- tmpAnticipate.anticipate(this.stepFunctions[this.state.Steps[i].GUIDStep].bind(this));
47
+
48
+ this.progressTrackers.setProgressTrackerTotalOperations(this.state.OverallProgressTracker.Hash, this.state.Status.StepCount);
49
+ this.progressTrackers.startProgressTracker(this.state.OverallProgressTracker.Hash);
50
+ this.info(`Operation [${this.state.Metadata.UUID}] ${this.state.Metadata.Name} starting...`);
51
+
52
+ for (let i = 0; i < this.state.Steps.length; i++)
53
+ {
54
+ tmpAnticipate.anticipate(
55
+ function(fNext)
56
+ {
57
+ this.fable.log.info(`Step #${i} [${this.state.Steps[i].GUIDStep}] ${this.state.Steps[i].Name} starting...`);
58
+ this.progressTrackers.startProgressTracker(this.state.Steps[i].ProgressTracker.Hash);
59
+ return fNext();
60
+ }.bind(this));
61
+ // Steps are executed in a custom context with
62
+ tmpAnticipate.anticipate(this.stepFunctions[this.state.Steps[i].GUIDStep].bind(
63
+ {
64
+ log:this,
65
+ fable:this.fable,
66
+ ProgressTracker:this.progressTrackers.getProgressTracker(this.state.Steps[i].ProgressTracker.Hash),
67
+ updateProgressTracker: function(pProgressAmount)
68
+ {
69
+ return this.progressTrackers.updateProgressTracker(this.state.Steps[i].ProgressTracker.Hash, pProgressAmount);
70
+ }.bind(this),
71
+ incrementProgressTracker: function(pProgressIncrementAmount)
72
+ {
73
+ return this.progressTrackers.incrementProgressTracker(this.state.Steps[i].ProgressTracker.Hash, pProgressIncrementAmount);
74
+ }.bind(this),
75
+ setProgressTrackerTotalOperations: function(pTotalOperationCount)
76
+ {
77
+ return this.progressTrackers.setProgressTrackerTotalOperations(this.state.Steps[i].ProgressTracker.Hash, pTotalOperationCount);
78
+ }.bind(this),
79
+ getProgressTrackerStatusString: function()
80
+ {
81
+ return this.progressTrackers.getProgressTrackerStatusString(this.state.Steps[i].ProgressTracker.Hash);
82
+ }.bind(this),
83
+ logProgressTrackerStatus: function()
84
+ {
85
+ return this.log.info(`Step #${i} [${this.state.Steps[i].GUIDStep}]: ${this.progressTrackers.getProgressTrackerStatusString(this.state.Steps[i].ProgressTracker.Hash)}`);
86
+ }.bind(this),
87
+ OperationState:this.state,
88
+ StepState:this.state.Steps[i]
89
+ }));
90
+ tmpAnticipate.anticipate(
91
+ function(fNext)
92
+ {
93
+ this.progressTrackers.endProgressTracker(this.state.Steps[i].ProgressTracker.Hash);
94
+ let tmpStepTimingMessage = this.progressTrackers.getProgressTrackerStatusString(this.state.Steps[i].ProgressTracker.Hash);
95
+ this.fable.log.info(`Step #${i} [${this.state.Steps[i].GUIDStep}] ${this.state.Steps[i].Name} complete.`);
96
+ this.fable.log.info(`Step #${i} [${this.state.Steps[i].GUIDStep}] ${this.state.Steps[i].Name} ${tmpStepTimingMessage}.`);
97
+
98
+ this.progressTrackers.incrementProgressTracker(this.state.OverallProgressTracker.Hash, 1);
99
+ let tmpOperationTimingMessage = this.progressTrackers.getProgressTrackerStatusString(this.state.OverallProgressTracker.Hash);
100
+ this.fable.log.info(`Operation [${this.state.Metadata.UUID}] ${tmpOperationTimingMessage}.`);
101
+ return fNext();
102
+ }.bind(this));
49
103
  }
50
104
 
51
105
  // Wait for the anticipation to complete
52
106
  tmpAnticipate.wait(
53
107
  (pError) =>
54
108
  {
55
- this.state.Status.TimeEnd = +new Date();
109
+ if (pError)
110
+ {
111
+ this.fable.log.error(`Operation [${this.state.Metadata.UUID}] ${this.state.Metadata.Name} had an error: ${pError}`, pError);
112
+ return fExecutionCompleteCallback(pError);
113
+ }
114
+ this.info(`Operation [${this.state.Metadata.UUID}] ${this.state.Metadata.Name} complete.`);
115
+ let tmpOperationTimingMessage = this.progressTrackers.getProgressTrackerStatusString(this.state.OverallProgressTracker.Hash);
116
+ this.progressTrackers.endProgressTracker(this.state.OverallProgressTracker.Hash);
117
+ this.fable.log.info(`Operation [${this.state.Metadata.UUID}] ${tmpOperationTimingMessage}.`);
56
118
  return fExecutionCompleteCallback();
57
119
  });
58
120
  }
59
121
 
60
- /*
61
- TODO: I've gone back and forth on whether this should be an object, JSON
62
- object prototype, or set of functions here. Discuss with colleagues!
63
- */
64
- addStep(pGUIDStep, fStepFunction, pStepName, pStepDescription, pStepMetadata)
122
+ addStep(fStepFunction, pStepMetadata, pStepName, pStepDescription, pGUIDStep)
65
123
  {
66
124
  let tmpStep = {};
125
+
126
+ // GUID is optional
67
127
  tmpStep.GUIDStep = (typeof(pGUIDStep) !== 'undefined') ? pGUIDStep : `STEP-${this.state.Steps.length}-${this.fable.DataGeneration.randomNumericString()}`;
128
+
129
+
130
+ // Name is optional
68
131
  tmpStep.Name = (typeof(pStepName) !== 'undefined') ? pStepName : `Step [${tmpStep.GUIDStep}]`;
69
132
  tmpStep.Description = (typeof(pStepDescription) !== 'undefined') ? pStepDescription : `Step execution of ${tmpStep.Name}.`;
70
- // TODO: Right now this allows an Array... do we want to block that?
71
- tmpStep.Metadata = (typeof(pStepMetadata) === 'object') ? pStepMetadata : {};
72
133
 
73
- tmpStep.TimeStart = false;
74
- tmpStep.TimeEnd = false;
134
+ tmpStep.ProgressTracker = this.progressTrackers.createProgressTracker(tmpStep.GUIDStep);
135
+
136
+ tmpStep.Metadata = (typeof(pStepMetadata) === 'object') ? pStepMetadata : {};
75
137
 
76
138
  // There is an array of steps, in the Operation State itself ... push a step there
77
139
  this.state.Steps.push(tmpStep);
78
140
 
79
- this.stepMap[tmpStep.GUIDStep]
80
- this.stepFunctions[tmpStep.GUIDStep] = fStepFunction;
141
+ this.stepMap[tmpStep.GUIDStep] = tmpStep;
81
142
 
82
- this.state.Status.StepCount++;
83
- return tmpStep;
84
- }
143
+ this.stepFunctions[tmpStep.GUIDStep] = typeof(fStepFunction) == 'function' ? fStepFunction : function (fDone) { return fDone(); };
85
144
 
86
- getStep(pGUIDStep)
87
- {
88
- if (this.stepMap.hasOwnProperty(pGUIDStep))
89
- {
90
- return this.stepMap[pGUIDStep];
91
- }
92
-
93
- return false;
94
- }
95
-
96
- startStep(pGUIDStep)
97
- {
98
- let tmpStep = this.getStep(pGUIDStep);
99
-
100
- if (tmpStep === false)
101
- {
102
- return false;
103
- }
104
-
105
- tmpStep.TimeStart = +new Date();
145
+ this.state.Status.StepCount++;
106
146
 
107
147
  return tmpStep;
108
148
  }
109
149
 
110
- stopStep(pGUIDStep)
150
+ setStepTotalOperations(pGUIDStep, pTotalOperationCount)
111
151
  {
112
- let tmpStep = this.getStep(pGUIDStep);
113
-
114
- if (tmpStep === false)
152
+ if (!this.stepMap.hasOwnProperty(pGUIDStep))
115
153
  {
116
- return false;
154
+ return new Error(`Step [${pGUIDStep}] does not exist in operation [${this.state.Metadata.UUID}] ${this.state.Metadata.Name} when attempting to set total operations to ${pTotalOperationCount}.`);
117
155
  }
118
156
 
119
- tmpStep.TimeEnd = +new Date();
120
-
121
- return tmpStep;
157
+ this.progressTrackers.setProgressTrackerTotalOperations(this.stepMap[pGUIDStep].ProgressTracker.Hash, pTotalOperationCount);
122
158
  }
123
159
 
124
160
  writeOperationLog(pLogLevel, pLogText, pLogObject)
@@ -178,189 +214,6 @@ class FableOperation extends libFableServiceBase
178
214
  this.writeOperationErrors(pLogText, pLogObject);
179
215
  this.fable.log.fatal(pLogText, pLogObject);
180
216
  }
181
-
182
-
183
- /************************************************************************
184
- * BEGINNING OF --> Telemetry Helpers
185
- */
186
- createTimeStamp(pTimeStampHash)
187
- {
188
- let tmpTimeStampHash = (typeof(pTimeStampHash) == 'string') ? pTimeStampHash : 'Default';
189
- this.timeStamps[tmpTimeStampHash] = +new Date();
190
- return this.timeStamps[tmpTimeStampHash];
191
- }
192
-
193
- getTimeDelta(pTimeStampHash)
194
- {
195
- let tmpTimeStampHash = (typeof(pTimeStampHash) == 'string') ? pTimeStampHash : 'Default';
196
- if (this.timeStamps.hasOwnProperty(tmpTimeStampHash))
197
- {
198
- let tmpEndTime = +new Date();
199
- return tmpEndTime-this.timeStamps[tmpTimeStampHash];
200
- }
201
- else
202
- {
203
- return -1;
204
- }
205
- }
206
-
207
- logTimeDelta(pTimeStampHash, pMessage)
208
- {
209
- let tmpTimeStampHash = (typeof(pTimeStampHash) == 'string') ? pTimeStampHash : 'Default';
210
- let tmpMessage = (typeof(pMessage) !== 'undefined') ? pMessage : `Elapsed for ${tmpTimeStampHash}: `;
211
- let tmpOperationTime = this.getTimeDelta(pTimeStampHash);
212
- this.info(tmpMessage +' ('+tmpOperationTime+'ms)');
213
- return tmpOperationTime;
214
- }
215
-
216
- createProgressTracker(pTotalOperations, pProgressTrackerHash)
217
- {
218
- let tmpProgressTrackerHash = (typeof(pProgressTrackerHash) == 'string') ? pProgressTrackerHash : 'DefaultProgressTracker';
219
- let tmpTotalOperations = (typeof(pTotalOperations) == 'number') ? pTotalOperations : 100;
220
-
221
- let tmpProgressTracker = (
222
- {
223
- Hash: tmpProgressTrackerHash,
224
- StartTime: this.createTimeStamp(tmpProgressTrackerHash),
225
- EndTime: 0,
226
- CurrentTime: 0,
227
- PercentComplete: -1,
228
- AverageOperationTime: -1,
229
- EstimatedCompletionTime: -1,
230
- TotalCount: tmpTotalOperations,
231
- CurrentCount:-1
232
- });
233
-
234
- this.progressTrackers[tmpProgressTrackerHash] = tmpProgressTracker;
235
-
236
- return tmpProgressTracker;
237
- }
238
-
239
- solveProgressTrackerStatus(pProgressTrackerHash)
240
- {
241
- let tmpProgressTrackerHash = (typeof(pProgressTrackerHash) == 'string') ? pProgressTrackerHash : 'DefaultProgressTracker';
242
-
243
- if (!this.progressTrackers.hasOwnProperty(tmpProgressTrackerHash))
244
- {
245
- this.createProgressTracker(100, tmpProgressTrackerHash);
246
- }
247
-
248
- let tmpProgressTracker = this.progressTrackers[tmpProgressTrackerHash];
249
-
250
- tmpProgressTracker.CurrentTime = this.getTimeDelta(tmpProgressTracker.Hash);
251
-
252
- if ((tmpProgressTracker.CurrentCount > 0) && (tmpProgressTracker.TotalCount > 0))
253
- {
254
- tmpProgressTracker.PercentComplete = (tmpProgressTracker.CurrentCount / tmpProgressTracker.TotalCount) * 100.0;
255
- }
256
-
257
- if ((tmpProgressTracker.CurrentCount > 0) && (tmpProgressTracker.CurrentTime > 0))
258
- {
259
- tmpProgressTracker.AverageOperationTime = tmpProgressTracker.CurrentTime / tmpProgressTracker.CurrentCount;
260
- }
261
-
262
- if ((tmpProgressTracker.CurrentCount < tmpProgressTracker.TotalCount) && (tmpProgressTracker.AverageOperationTime > 0))
263
- {
264
- tmpProgressTracker.EstimatedCompletionTime = (tmpProgressTracker.TotalCount - tmpProgressTracker.CurrentCount) * tmpProgressTracker.AverageOperationTime;
265
- }
266
- }
267
-
268
- updateProgressTrackerStatus(pProgressTrackerHash, pCurrentOperations)
269
- {
270
- let tmpProgressTrackerHash = (typeof(pProgressTrackerHash) == 'string') ? pProgressTrackerHash : 'DefaultProgressTracker';
271
- let tmpCurrentOperations = parseInt(pCurrentOperations);
272
-
273
- if (isNaN(tmpCurrentOperations))
274
- {
275
- return false;
276
- }
277
-
278
- if (!this.progressTrackers.hasOwnProperty(tmpProgressTrackerHash))
279
- {
280
- this.createProgressTracker(100, tmpProgressTrackerHash);
281
- }
282
-
283
- this.progressTrackers[tmpProgressTrackerHash].CurrentCount = tmpCurrentOperations;
284
- this.progressTrackers[tmpProgressTrackerHash].CurrentTime = this.getTimeDelta(tmpProgressTrackerHash);
285
-
286
- this.solveProgressTrackerStatus(tmpProgressTrackerHash);
287
-
288
- return this.progressTrackers[tmpProgressTrackerHash];
289
- }
290
-
291
- incrementProgressTrackerStatus(pProgressTrackerHash, pIncrementSize)
292
- {
293
- let tmpProgressTrackerHash = (typeof(pProgressTrackerHash) == 'string') ? pProgressTrackerHash : 'DefaultProgressTracker';
294
- let tmpIncrementSize = parseInt(pIncrementSize);
295
-
296
- if (isNaN(tmpIncrementSize))
297
- {
298
- return false;
299
- }
300
-
301
- if (!this.progressTrackers.hasOwnProperty(tmpProgressTrackerHash))
302
- {
303
- this.createProgressTracker(100, tmpProgressTrackerHash);
304
- }
305
-
306
- this.progressTrackers[tmpProgressTrackerHash].CurrentCount = this.progressTrackers[tmpProgressTrackerHash].CurrentCount + tmpIncrementSize;
307
- this.progressTrackers[tmpProgressTrackerHash].CurrentTime = this.getTimeDelta(tmpProgressTrackerHash);
308
-
309
- this.solveProgressTrackerStatus(tmpProgressTrackerHash);
310
-
311
- return this.progressTrackers[tmpProgressTrackerHash];
312
- }
313
-
314
- setProgressTrackerEndTime(pProgressTrackerHash, pCurrentOperations)
315
- {
316
- let tmpProgressTrackerHash = (typeof(pProgressTrackerHash) == 'string') ? pProgressTrackerHash : 'DefaultProgressTracker';
317
- let tmpCurrentOperations = parseInt(pCurrentOperations);
318
-
319
- if (!this.progressTrackers.hasOwnProperty(tmpProgressTrackerHash))
320
- {
321
- return false;
322
- }
323
- if (!isNaN(tmpCurrentOperations))
324
- {
325
- this.updateProgressTrackerStatus(tmpProgressTrackerHash, tmpCurrentOperations);
326
- }
327
-
328
- this.progressTrackers[tmpProgressTrackerHash].EndTime = this.getTimeDelta(tmpProgressTrackerHash);
329
-
330
- this.solveProgressTrackerStatus(tmpProgressTrackerHash);
331
-
332
- return this.progressTrackers[tmpProgressTrackerHash];
333
- }
334
-
335
- printProgressTrackerStatus(pProgressTrackerHash)
336
- {
337
- let tmpProgressTrackerHash = (typeof(pProgressTrackerHash) == 'string') ? pProgressTrackerHash : 'DefaultProgressTracker';
338
-
339
- if (!this.progressTrackers.hasOwnProperty(tmpProgressTrackerHash))
340
- {
341
- this.info(`>> Progress Tracker ${tmpProgressTrackerHash} does not exist! No stats to display.`);
342
- }
343
- else
344
- {
345
- const tmpProgressTracker = this.progressTrackers[tmpProgressTrackerHash];
346
-
347
- if (tmpProgressTracker.CurrentCount < 1)
348
- {
349
- this.info(`>> Progress Tracker ${tmpProgressTracker.Hash} has no completed operations. ${tmpProgressTracker.CurrentTime}ms have elapsed since it was started.`);
350
- }
351
- else if (tmpProgressTracker.EndTime < 1)
352
- {
353
- this.info(`>> Progress Tracker ${tmpProgressTracker.Hash} is ${tmpProgressTracker.PercentComplete.toFixed(3)}% completed - ${tmpProgressTracker.CurrentCount} / ${tmpProgressTracker.TotalCount} operations over ${tmpProgressTracker.CurrentTime}ms (median ${tmpProgressTracker.AverageOperationTime.toFixed(3)} per). Estimated completion in ${tmpProgressTracker.EstimatedCompletionTime.toFixed(0)}ms or ${(tmpProgressTracker.EstimatedCompletionTime / 1000 / 60).toFixed(2)}minutes`)
354
- }
355
- else
356
- {
357
- this.info(`>> Progress Tracker ${tmpProgressTracker.Hash} is done and completed ${tmpProgressTracker.CurrentCount} / ${tmpProgressTracker.TotalCount} operations in ${tmpProgressTracker.EndTime}ms.`)
358
- }
359
- }
360
- }
361
- /*
362
- * END OF --> Logging and Telemetry Helpers
363
- ************************************************************************/
364
217
  }
365
218
 
366
219
  module.exports = FableOperation;
@@ -0,0 +1,159 @@
1
+ const libFableServiceBase = require('fable-serviceproviderbase');
2
+
3
+ class FableServiceProgressTime extends libFableServiceBase
4
+ {
5
+ constructor(pFable, pOptions, pServiceHash)
6
+ {
7
+ super(pFable, pOptions, pServiceHash);
8
+
9
+ this.serviceType = 'ProgressTime';
10
+
11
+ this.timeStamps = {};
12
+ }
13
+
14
+ formatTimeDuration(pTimeDurationInMilliseconds)
15
+ {
16
+ let tmpTimeDuration = typeof(pTimeDurationInMilliseconds) == 'number' ? pTimeDurationInMilliseconds : 0;
17
+
18
+ if (pTimeDurationInMilliseconds < 0)
19
+ {
20
+ return 'unknown';
21
+ }
22
+
23
+ let tmpTimeDurationString = '';
24
+ if (tmpTimeDuration > 3600000)
25
+ {
26
+ tmpTimeDurationString += Math.floor(tmpTimeDuration/3600000)+'h ';
27
+ tmpTimeDuration = tmpTimeDuration % 3600000;
28
+ }
29
+ if (tmpTimeDuration > 60000)
30
+ {
31
+ tmpTimeDurationString += Math.floor(tmpTimeDuration/60000)+'m ';
32
+ tmpTimeDuration = tmpTimeDuration % 60000;
33
+ }
34
+ if (tmpTimeDuration > 1000)
35
+ {
36
+ tmpTimeDurationString += Math.floor(tmpTimeDuration/1000)+'s ';
37
+ tmpTimeDuration = tmpTimeDuration % 1000;
38
+ }
39
+ tmpTimeDurationString += Math.round(tmpTimeDuration)+'ms';
40
+
41
+ return tmpTimeDurationString;
42
+ }
43
+
44
+ createTimeStamp(pTimeStampHash)
45
+ {
46
+ let tmpTimeStampHash = (typeof(pTimeStampHash) == 'string') ? pTimeStampHash : 'Default';
47
+ this.timeStamps[tmpTimeStampHash] = +new Date();
48
+ return this.timeStamps[tmpTimeStampHash];
49
+ }
50
+
51
+ getTimeStampValue(pTimeStampHash)
52
+ {
53
+ let tmpTimeStampHash = (typeof(pTimeStampHash) == 'string') ? pTimeStampHash : 'Default';
54
+ return this.timeStamps.hasOwnProperty(tmpTimeStampHash) ? this.timeStamps[tmpTimeStampHash] : -1;
55
+ }
56
+
57
+ updateTimeStampValue(pTimeStampHash, pReferenceTime)
58
+ {
59
+ let tmpTimeStampHash = (typeof(pTimeStampHash) == 'string') ? pTimeStampHash : 'Default';
60
+ let tmpReferenceTime = false;
61
+
62
+ // This function allows the user to pass in either a reference time in ms, or, a hash of a timestamp.
63
+ if (typeof(pReferenceTime) == 'string')
64
+ {
65
+ tmpReferenceTime = this.timeStamps.hasOwnProperty(tmpReference) ? this.timeStamps[tmpReference] : false;
66
+ }
67
+ else if (typeof(pReferenceTime) == 'number')
68
+ {
69
+ tmpReferenceTime = pReferenceTime;
70
+ }
71
+ else
72
+ {
73
+ tmpReferenceTime = +new Date();
74
+ }
75
+
76
+ if (this.timeStamps.hasOwnProperty(tmpTimeStampHash) && tmpReferenceTime)
77
+ {
78
+ this.timeStamps[tmpTimeStampHash] = tmpReferenceTime;
79
+ return this.timeStamps[tmpTimeStampHash];
80
+ }
81
+ else
82
+ {
83
+ return -1;
84
+ }
85
+ }
86
+
87
+ removeTimeStamp(pTimeStampHash)
88
+ {
89
+ let tmpTimeStampHash = (typeof(pTimeStampHash) == 'string') ? pTimeStampHash : 'Default';
90
+ if (this.timeStamps.hasOwnProperty(tmpTimeStampHash))
91
+ {
92
+ delete this.timeStamps[tmpTimeStampHash];
93
+ return true;
94
+ }
95
+ else
96
+ {
97
+ return false;
98
+ }
99
+ }
100
+
101
+ getTimeStampDelta(pTimeStampHash, pReferenceTime)
102
+ {
103
+ let tmpTimeStampHash = (typeof(pTimeStampHash) == 'string') ? pTimeStampHash : 'Default';
104
+ let tmpReferenceTime = false;
105
+
106
+ // This function allows the user to pass in either a reference time in ms, or, a hash of a timestamp.
107
+ if (typeof(pReferenceTime) == 'string')
108
+ {
109
+ tmpReferenceTime = this.timeStamps.hasOwnProperty(tmpReference) ? this.timeStamps[tmpReference] : false;
110
+ }
111
+ else if (typeof(pReferenceTime) == 'number')
112
+ {
113
+ tmpReferenceTime = pReferenceTime;
114
+ }
115
+ else
116
+ {
117
+ tmpReferenceTime = +new Date();
118
+ }
119
+
120
+ if (this.timeStamps.hasOwnProperty(tmpTimeStampHash) && tmpReferenceTime)
121
+ {
122
+ return tmpReferenceTime-this.timeStamps[tmpTimeStampHash];
123
+ }
124
+ else
125
+ {
126
+ return -1;
127
+ }
128
+ }
129
+
130
+ getDurationBetweenTimestamps(pTimeStampHashStart, pTimeStampHashEnd)
131
+ {
132
+ let tmpTimeStampHashStart = (typeof(pTimeStampHashStart) == 'string') ? pTimeStampHashStart : 'Default';
133
+ let tmpTimeStampHashEnd = (typeof(pTimeStampHashEnd) == 'string') ? pTimeStampHashEnd : 'Default';
134
+ if (this.timeStamps.hasOwnProperty(tmpTimeStampHashStart) && this.timeStamps.hasOwnProperty(tmpTimeStampHashEnd))
135
+ {
136
+ return this.timeStamps[tmpTimeStampHashEnd]-this.timeStamps[tmpTimeStampHashStart];
137
+ }
138
+ else
139
+ {
140
+ return -1;
141
+ }
142
+ }
143
+
144
+ getTimeStampDeltaMessage(pTimeStampHash, pMessage, pReferenceTime)
145
+ {
146
+ let tmpTimeStampHash = (typeof(pTimeStampHash) == 'string') ? pTimeStampHash : 'Default';
147
+ let tmpMessage = (typeof(pMessage) !== 'undefined') ? pMessage : `Elapsed for ${tmpTimeStampHash}: `;
148
+ let tmpOperationTime = this.getTimeStampDelta(tmpTimeStampHash, pReferenceTime);
149
+
150
+ return `${tmpMessage} ${this.formatTimeDuration(tmpOperationTime)}`;
151
+ }
152
+
153
+ logTimeStampDelta(pTimeStampHash, pMessage, pReferenceTime)
154
+ {
155
+ this.fable.log.info(this.getTimeStampDeltaMessage(pTimeStampHash, pMessage, pReferenceTime));
156
+ }
157
+ }
158
+
159
+ module.exports = FableServiceProgressTime;