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 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`. In 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`.
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
 
@@ -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 <seconds>', 'run in a loop',0)
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) {
@@ -40,6 +40,10 @@
40
40
  }
41
41
  ] ,
42
42
  [
43
+ {
44
+ "id": "@handler/notification_handler/on_error.js",
45
+ "handler": "@handler/notification_handler/nothing.js"
46
+ },
43
47
  {
44
48
  "id": "@handler/notification_handler/jsonpath_filter.js",
45
49
  "anyOf": [
@@ -9,8 +9,6 @@ const logger = require('../../lib/util.js').getLogger();
9
9
  * it in the outbox container.
10
10
  */
11
11
  async function handle({path,options,config}) {
12
- logger.info(`parsing notification ${path}`);
13
-
14
12
  try {
15
13
  const json = parseAsJSON(path);
16
14
 
@@ -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
  const eventlog = options['eventlog'];
13
11
 
14
12
  if (!eventlog) {
@@ -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
- const handler = dynamic_handler(options['inbox_handler'],defaultInboxHandler);
10
- return await handler({path,options});
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
- const loopWait = options['loop'] || 0;
65
+ await poolRun(pool,path,options);
66
+
67
+ if (! options.loop) return;
35
68
 
36
- do {
37
- try {
38
- const [prms,locks] = await inboxProcessor(pool,path,options);
39
- const results = await Promise.all(prms);
69
+ // Loop
40
70
 
41
- for (let i = 0 ; i < results.length ; i++) {
42
- const result = results[i];
43
- const success = result['success'];
44
- const notification = result['path'];
71
+ const watcher = chokidar.watch(path, {
72
+ ignored: /(^|[\/\\])\../, // ignore dotfiles
73
+ persistent: true
74
+ });
45
75
 
46
- if (success) {
47
- logger.info(`processing ${notification} is a success`);
48
- if (fs.existsSync(notification)) {
49
- logger.debug(`removing ${notification}`);
50
- fs.unlinkSync(result['path']);
51
- }
52
- }
53
- else {
54
- logger.warn(`processing ${notification} is a failure`);
55
- logger.debug(`moving ${notification} to ${options['error']}`);
56
- moveTo(notification,options['error']);
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
- // release lock
60
- if (locks[i]) locks[i]();
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
- if (loopWait) {
68
- logger.debug(`sleep ${loopWait} secs...`);
69
- await new Promise(resolve => setTimeout(resolve, loopWait*1000));
113
+ // release lock
114
+ if (locks[i]) locks[i]();
70
115
  }
71
116
  }
72
- while (loopWait > 0);
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.5.5",
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",