-
Notifications
You must be signed in to change notification settings - Fork 374
/
appManager.ts
141 lines (135 loc) · 5.38 KB
/
appManager.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import * as async from 'async';
import * as utils from '../../util/utils';
import { getLogger } from 'pinus-logger';
let logger = getLogger('pinus', __filename);
let transactionLogger = getLogger('transaction-log', __filename);
let transactionErrorLogger = getLogger('transaction-error-log', __filename);
export type TransactionCondictionFunction = (cb : (err ?:Error)=>void)=>void;
export type TransactionHandlerFunction = (cb : (err ?:Error)=>void)=>void;
export function transaction(name : string, conditions : TransactionCondictionFunction[], handlers : TransactionHandlerFunction[], retry: number)
{
if (!retry)
{
retry = 1;
}
if (typeof name !== 'string')
{
logger.error('transaction name is error format, name: %s.', name);
return;
}
if (typeof conditions !== 'object' || typeof handlers !== 'object')
{
logger.error('transaction conditions parameter is error format, conditions: %j, handlers: %j.', conditions, handlers);
return;
}
let cmethods : TransactionCondictionFunction[] = [];
let dmethods : TransactionHandlerFunction[] = [];
let cnames : string[] = [];
let dnames : string[] = [];
for (let key in conditions)
{
if (typeof key !== 'string' || typeof conditions[key] !== 'function')
{
logger.error('transaction conditions parameter is error format, condition name: %s, condition function: %j.', key, conditions[key]);
return;
}
cnames.push(key);
cmethods.push(conditions[key]);
}
let i = 0;
// execute conditions
async.forEachSeries(cmethods, function (method, cb)
{
method(cb);
transactionLogger.info('[%s]:[%s] condition is executed.', name, cnames[i]);
i++;
}, function (err : Error)
{
if (err)
{
process.nextTick(function ()
{
transactionLogger.error('[%s]:[%s] condition is executed with err: %j.', name, cnames[--i], err.stack);
let log = {
name: name,
method: cnames[i],
time: Date.now(),
type: 'condition',
description: err.stack
};
transactionErrorLogger.error(JSON.stringify(log));
});
return;
} else
{
// execute handlers
process.nextTick(function ()
{
for (let key in handlers)
{
if (typeof key !== 'string' || typeof handlers[key] !== 'function')
{
logger.error('transcation handlers parameter is error format, handler name: %s, handler function: %j.', key, handlers[key]);
return;
}
dnames.push(key);
dmethods.push(handlers[key]);
}
let flag = true;
let times = retry;
// do retry if failed util retry times
async.whilst(
function ()
{
return retry > 0 && flag;
},
function (callback)
{
let j = 0;
retry--;
async.forEachSeries(dmethods, function (method, cb)
{
method(cb);
transactionLogger.info('[%s]:[%s] handler is executed.', name, dnames[j]);
j++;
}, function (err : Error)
{
if (err)
{
process.nextTick(function ()
{
transactionLogger.error('[%s]:[%s]:[%s] handler is executed with err: %j.', name, dnames[--j], times - retry, err.stack);
let log = {
name: name,
method: dnames[j],
retry: times - retry,
time: Date.now(),
type: 'handler',
description: err.stack
};
transactionErrorLogger.error(JSON.stringify(log));
utils.invokeCallback(callback);
});
return;
}
flag = false;
utils.invokeCallback(callback);
process.nextTick(function ()
{
transactionLogger.info('[%s] all conditions and handlers are executed successfully.', name);
});
});
},
function (err)
{
if (err)
{
logger.error('transaction process is executed with error: %j', err);
}
// callback will not pass error
}
);
});
}
});
};