ldn-inbox-server 1.5.5 → 1.6.1
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/README.md +11 -1
- package/bin/ldn-inbox-server.js +2 -1
- package/config/inbox_config.json +4 -0
- package/handler/notification_handler/accept.js +0 -2
- package/handler/notification_handler/add_timemap_link.js +0 -2
- package/handler/notification_handler/eventlog.js +0 -2
- package/handler/notification_handler/jsonpath_filter.js +0 -2
- package/handler/notification_handler/multi.js +26 -0
- package/handler/notification_handler/nothing.js +17 -0
- package/handler/notification_handler/offer_memento.js +0 -2
- package/handler/notification_handler/on_error.js +28 -0
- package/handler/notification_handler/type_filter.js +0 -2
- package/handler/notification_handler/valid_artifact.js +0 -2
- package/handler/notification_handler/valid_eventlog.js +0 -2
- package/lib/handler.js +80 -33
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -176,7 +176,17 @@ The json path matches when one of:
|
|
|
176
176
|
|
|
177
177
|
### Multi handler
|
|
178
178
|
|
|
179
|
-
A `handler/multi_notification_handler.js` is available to start multiple handler for each notification messages. The handlers to start are specified in a configuration file that can be passed via the `config` parameter of an `handle_inbox`.
|
|
179
|
+
A `handler/multi_notification_handler.js` is available to start multiple handler for each notification messages. The handlers to start are specified in a configuration file that can be passed via the `config` parameter of an `handle_inbox`. For the commmand line tool `bin/ldn-inbox-server` the default location of such config file is `config/inbox_config.json` when processing an `@inbox`, and `config/outbox_config.json` when processing an `@outbox`.
|
|
180
|
+
|
|
181
|
+
The multi handler requires a configuration file with properties `notification_handler.multi.handlers` which is an array of array. Each outer array defines a list of handlers that should be executed sequentially on a notification until one handler returns a `false` response or the last handler returns a `true` response.
|
|
182
|
+
|
|
183
|
+
Each handler is defined by a hash containing as `id` property the path to the handler and optionally other property keys that will be passed to the handlers in the `config` section.
|
|
184
|
+
|
|
185
|
+
Optionally when a `fallback` handler is defined as option it will be attempted when a handler in a sequence returns a `false` response.
|
|
186
|
+
|
|
187
|
+
### On Error handler
|
|
188
|
+
|
|
189
|
+
A handler that sets the `fallback` for a workflow sequence.
|
|
180
190
|
|
|
181
191
|
### Offer memento handler
|
|
182
192
|
|
package/bin/ldn-inbox-server.js
CHANGED
|
@@ -89,12 +89,13 @@ program
|
|
|
89
89
|
.option('--outbox <outbox>','outbox',OUTBOX_PATH)
|
|
90
90
|
.option('--public <public>','public',PUBLIC_PATH)
|
|
91
91
|
.option('--error <errbox>','errbox',ERROR_PATH)
|
|
92
|
-
.option('--loop
|
|
92
|
+
.option('--loop', 'run in a loop')
|
|
93
93
|
.option('--batch_size <num>','batch size to process',INBOX_BATCH_SIZE)
|
|
94
94
|
.option('--glob <glob>','files to process in inbox',INBOX_GLOB)
|
|
95
95
|
.option('--config <path>','config file for handlers')
|
|
96
96
|
.option('-hi,--inbox_handler <handler>','inbox handler')
|
|
97
97
|
.option('-hn,--notification_handler <handler>','notification handler')
|
|
98
|
+
.option('-s,--single','handle this one specific notification')
|
|
98
99
|
.argument('<box>','box to process')
|
|
99
100
|
.action( async(box,options) => {
|
|
100
101
|
switch (box) {
|
package/config/inbox_config.json
CHANGED
|
@@ -7,8 +7,6 @@ const logger = require('../../lib/util.js').getLogger();
|
|
|
7
7
|
* Demonstration event log handler
|
|
8
8
|
*/
|
|
9
9
|
async function handle({path,options,config}) {
|
|
10
|
-
logger.info(`parsing notification ${path}`);
|
|
11
|
-
|
|
12
10
|
if (! config) {
|
|
13
11
|
logger.error('no configuration found for eventlog_notification_handler');
|
|
14
12
|
return { path, options, success: false };
|
|
@@ -7,8 +7,6 @@ const logger = require('../../lib/util.js').getLogger();
|
|
|
7
7
|
* matches a configurable list
|
|
8
8
|
*/
|
|
9
9
|
async function handle({path,options,config}) {
|
|
10
|
-
logger.info(`parsing notification ${path}`);
|
|
11
|
-
|
|
12
10
|
if (! config) {
|
|
13
11
|
logger.error('no configuration found for eventlog_notification_handler');
|
|
14
12
|
return { path, options, success: false };
|
|
@@ -65,6 +65,29 @@ async function handle({path,options}) {
|
|
|
65
65
|
else {
|
|
66
66
|
logger.error(`workflow[${i}] : failed ${step}`);
|
|
67
67
|
thisWorkflow = false;
|
|
68
|
+
|
|
69
|
+
if (options['fallback']) {
|
|
70
|
+
logger.debug(`loading fallback ${options['fallback']}`);
|
|
71
|
+
const fallback = dynamic_handler(options['fallback'],null);
|
|
72
|
+
|
|
73
|
+
if (!fallback) {
|
|
74
|
+
throw new Error(`failed to load ${options['fallback']}`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
logger.info(`workflow[${i}] : starting ${options['fallback']}`);
|
|
78
|
+
const fallback_result = await fallback({path,options,config,notification});
|
|
79
|
+
|
|
80
|
+
if (fallback_result['success']) {
|
|
81
|
+
logger.info(`workflow[${i}] : finished ${options['fallback']}`);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
logger.error(`workflow[${i}] : failed ${options['fallback']}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
logger.debug(`no fallBack defined`);
|
|
89
|
+
}
|
|
90
|
+
|
|
68
91
|
break;
|
|
69
92
|
}
|
|
70
93
|
}
|
|
@@ -81,6 +104,9 @@ async function handle({path,options}) {
|
|
|
81
104
|
else {
|
|
82
105
|
workflow_errors++;
|
|
83
106
|
}
|
|
107
|
+
|
|
108
|
+
// Each workflow needs to install its own fallBack
|
|
109
|
+
delete options['fallback'];
|
|
84
110
|
}
|
|
85
111
|
|
|
86
112
|
if (handlers.length > 0 && workflow_success > 0) {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const logger = require('../../lib/util.js').getLogger();
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Handler that does nothing (debug purposes)
|
|
5
|
+
*/
|
|
6
|
+
async function handle({path,options,config}) {
|
|
7
|
+
try {
|
|
8
|
+
return { path, options, success: true };
|
|
9
|
+
}
|
|
10
|
+
catch(e) {
|
|
11
|
+
logger.error(`failed to process ${path}`);
|
|
12
|
+
logger.error(e);
|
|
13
|
+
return { path, options, success: false };
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = { handle };
|
|
@@ -8,8 +8,6 @@ const logger = require('../../lib/util.js').getLogger();
|
|
|
8
8
|
* archivation of the event log.
|
|
9
9
|
*/
|
|
10
10
|
async function handle({path,options,config}) {
|
|
11
|
-
logger.info(`parsing notification ${path}`);
|
|
12
|
-
|
|
13
11
|
if (! config) {
|
|
14
12
|
logger.error('no configuration found for offer_memento');
|
|
15
13
|
return { path, options, success: false };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const logger = require('../../lib/util.js').getLogger();
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Handler that sets the 'fallback' handler option
|
|
5
|
+
*/
|
|
6
|
+
async function handle({path,options,config}) {
|
|
7
|
+
try {
|
|
8
|
+
const fallback = config['handler'];
|
|
9
|
+
|
|
10
|
+
if (!fallback) {
|
|
11
|
+
logger.error('no handler configuration found');
|
|
12
|
+
return { path, options, success: true };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
logger.info(`setting fallback to ${fallback}`);
|
|
16
|
+
|
|
17
|
+
options['fallback'] = fallback;
|
|
18
|
+
|
|
19
|
+
return { path, options, success: true };
|
|
20
|
+
}
|
|
21
|
+
catch(e) {
|
|
22
|
+
logger.error(`failed to process ${path}`);
|
|
23
|
+
logger.error(e);
|
|
24
|
+
return { path, options, success: false };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports = { handle };
|
|
@@ -6,8 +6,6 @@ const logger = require('../../lib/util.js').getLogger();
|
|
|
6
6
|
* matches a configurable list
|
|
7
7
|
*/
|
|
8
8
|
async function handle({path,options,config}) {
|
|
9
|
-
logger.info(`parsing notification ${path}`);
|
|
10
|
-
|
|
11
9
|
if (! config) {
|
|
12
10
|
logger.error('no configuration found for eventlog_notification_handler');
|
|
13
11
|
return { path, options, success: false };
|
|
@@ -6,8 +6,6 @@ const logger = require('../../lib/util.js').getLogger();
|
|
|
6
6
|
* message contains an artifact that is known to the data node
|
|
7
7
|
*/
|
|
8
8
|
async function handle({path,options,config}) {
|
|
9
|
-
logger.info(`parsing notification ${path}`);
|
|
10
|
-
|
|
11
9
|
try {
|
|
12
10
|
const json = parseAsJSON(path);
|
|
13
11
|
|
|
@@ -6,8 +6,6 @@ const logger = require('../../lib/util.js').getLogger();
|
|
|
6
6
|
* message contains an artifact that is known to the data node
|
|
7
7
|
*/
|
|
8
8
|
async function handle({path,options,config}) {
|
|
9
|
-
logger.info(`parsing notification ${path}`);
|
|
10
|
-
|
|
11
9
|
try {
|
|
12
10
|
const json = parseAsJSON(path);
|
|
13
11
|
|
package/lib/handler.js
CHANGED
|
@@ -3,11 +3,42 @@ const fsPath = require('path');
|
|
|
3
3
|
const lockfile = require('proper-lockfile');
|
|
4
4
|
const { dynamic_handler, moveTo } = require('../lib/util');
|
|
5
5
|
const piscina = require('piscina');
|
|
6
|
+
const chokidar = require('chokidar');
|
|
6
7
|
const logger = require('../lib/util.js').getLogger();
|
|
7
8
|
|
|
8
9
|
async function handle_inbox(path,options) {
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
if (options.single) {
|
|
11
|
+
logger.debug(`*single file execution*`);
|
|
12
|
+
handle_single(path,options);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
logger.debug(`*directory execution*`);
|
|
16
|
+
const handler = dynamic_handler(options['inbox_handler'],defaultInboxHandler);
|
|
17
|
+
return await handler({path,options});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function handle_single(path,options) {
|
|
22
|
+
const handler = dynamic_handler(
|
|
23
|
+
options['notification_handler'],
|
|
24
|
+
fsPath.resolve(__dirname,'..','lib','demoNotificationHandler.js')
|
|
25
|
+
);
|
|
26
|
+
const result = await handler({path,options});
|
|
27
|
+
const success = result['success'];
|
|
28
|
+
const notification = result['path'];
|
|
29
|
+
|
|
30
|
+
if (success) {
|
|
31
|
+
logger.info(`processing ${notification} is a success`);
|
|
32
|
+
if (fs.existsSync(notification)) {
|
|
33
|
+
logger.debug(`removing ${notification}`);
|
|
34
|
+
fs.unlinkSync(result['path']);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
logger.warn(`processing ${notification} is a failure`);
|
|
39
|
+
logger.debug(`moving ${notification} to ${options['error']}`);
|
|
40
|
+
moveTo(notification,options['error']);
|
|
41
|
+
}
|
|
11
42
|
}
|
|
12
43
|
|
|
13
44
|
async function defaultInboxHandler({path,options}) {
|
|
@@ -31,45 +62,61 @@ async function defaultInboxHandler({path,options}) {
|
|
|
31
62
|
maxQueue: queue_size
|
|
32
63
|
});
|
|
33
64
|
|
|
34
|
-
|
|
65
|
+
await poolRun(pool,path,options);
|
|
66
|
+
|
|
67
|
+
if (! options.loop) return;
|
|
35
68
|
|
|
36
|
-
|
|
37
|
-
try {
|
|
38
|
-
const [prms,locks] = await inboxProcessor(pool,path,options);
|
|
39
|
-
const results = await Promise.all(prms);
|
|
69
|
+
// Loop
|
|
40
70
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
71
|
+
const watcher = chokidar.watch(path, {
|
|
72
|
+
ignored: /(^|[\/\\])\../, // ignore dotfiles
|
|
73
|
+
persistent: true
|
|
74
|
+
});
|
|
45
75
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
76
|
+
watcher.on('ready', () => {
|
|
77
|
+
logger.info(`start watching ${path}...`);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
watcher.on('error', error => {
|
|
81
|
+
logger.error(error);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
watcher.on('add', async notification => {
|
|
85
|
+
logger.info(`new notifiction ${notification} detected`);
|
|
86
|
+
await poolRun(pool,path,options);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
58
89
|
|
|
59
|
-
|
|
60
|
-
|
|
90
|
+
async function poolRun(pool,path,options) {
|
|
91
|
+
try {
|
|
92
|
+
const [prms,locks] = await inboxProcessor(pool,path,options);
|
|
93
|
+
const results = await Promise.all(prms);
|
|
94
|
+
|
|
95
|
+
for (let i = 0 ; i < results.length ; i++) {
|
|
96
|
+
const result = results[i];
|
|
97
|
+
const success = result['success'];
|
|
98
|
+
const notification = result['path'];
|
|
99
|
+
|
|
100
|
+
if (success) {
|
|
101
|
+
logger.info(`processing ${notification} is a success`);
|
|
102
|
+
if (fs.existsSync(notification)) {
|
|
103
|
+
logger.debug(`removing ${notification}`);
|
|
104
|
+
fs.unlinkSync(result['path']);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
logger.warn(`processing ${notification} is a failure`);
|
|
109
|
+
logger.debug(`moving ${notification} to ${options['error']}`);
|
|
110
|
+
moveTo(notification,options['error']);
|
|
61
111
|
}
|
|
62
|
-
}
|
|
63
|
-
catch (e) {
|
|
64
|
-
logger.error(e);
|
|
65
|
-
}
|
|
66
112
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
await new Promise(resolve => setTimeout(resolve, loopWait*1000));
|
|
113
|
+
// release lock
|
|
114
|
+
if (locks[i]) locks[i]();
|
|
70
115
|
}
|
|
71
116
|
}
|
|
72
|
-
|
|
117
|
+
catch (e) {
|
|
118
|
+
logger.error(e);
|
|
119
|
+
}
|
|
73
120
|
}
|
|
74
121
|
|
|
75
122
|
async function inboxProcessor(pool,path,options) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ldn-inbox-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "A demonstration Event Notifications Inbox server",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"author": "Patrick Hochstenbach <Patrick.Hochstenbach@UGent.be>",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
],
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"dependencies": {
|
|
25
|
+
"chokidar": "^3.6.0",
|
|
25
26
|
"commander": "^12.0.0",
|
|
26
27
|
"dotenv": "^16.4.5",
|
|
27
28
|
"exponential-backoff": "^3.1.1",
|