samanbayaka 0.0.25 → 0.0.26

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
@@ -427,18 +427,30 @@ The `interMessageDelayMs` option introduces a delay between two consecutive mess
427
427
  ### Run the services
428
428
 
429
429
  * development/testing
430
+
430
431
  ```bash
431
432
  cd <your_path>/gateway
432
- node index.mjs
433
+ SBK_CONFIG_CRED='<your_etcs_user> <your_etcd_pass> <your_etcd_port>' node index.mjs
433
434
  cd <your_path>/hello
434
- node index.mjs
435
+ SBK_CONFIG_CRED='<your_etcs_user> <your_etcd_pass> <your_etcd_port>' node index.mjs
435
436
  ```
437
+ or
438
+ ```bash
439
+ pm2 stop "$(basename "$PWD")" && rm -rf node_modules/samanbayaka/ &&cp -r ../../samanbayaka/. node_modules/samanbayaka/ && SBK_CONFIG_CRED='sbk sbk@123 12379' pm2 start index.mjs --name "$(basename "$PWD")" --stop-exit-codes 1 --output /var/log/samanbayaka/sbk-out-${HOSTNAME}-$$.log --error /var/log/samanbayaka/sbk-err-${HOSTNAME}-$$.log
440
+ ```
436
441
  * production
437
442
  ```bash
438
443
  cd <your_path>/gateway
439
- node index.mjs >> /var/log/samanbayaka/sbk-${HOSTNAME}-$$.log 2>&1
444
+ SBK_CONFIG_CRED='<your_etcs_user> <your_etcd_pass> <your_etcd_port>' node index.mjs >> /var/log/samanbayaka/sbk-${HOSTNAME}-$$.log 2>&1
440
445
  cd <your_path>/hello
441
- node index.mjs >> /var/log/samanbayaka/sbk-${HOSTNAME}-$$.log 2>&1
446
+ SBK_CONFIG_CRED='<your_etcs_user> <your_etcd_pass> <your_etcd_port>' node index.mjs >> /var/log/samanbayaka/sbk-${HOSTNAME}-$$.log 2>&1
447
+ ```
448
+ or
449
+ ```bash
450
+ cd <your_path>/gateway
451
+ SBK_CONFIG_CRED='<your_etcs_user> <your_etcd_pass> <your_etcd_port>' pm2 start index.mjs --name "$(basename "$PWD")" --stop-exit-codes 1 --output /var/log/samanbayaka/sbk-out-${HOSTNAME}-$$.log --error /var/log/samanbayaka/sbk-err-${HOSTNAME}-$$.log
452
+ cd <your_path>/hello
453
+ SBK_CONFIG_CRED='<your_etcs_user> <your_etcd_pass> <your_etcd_port>' pm2 start index.mjs --name "$(basename "$PWD")" --stop-exit-codes 1 --output /var/log/samanbayaka/sbk-out-${HOSTNAME}-$$.log --error /var/log/samanbayaka/sbk-err-${HOSTNAME}-$$.log
442
454
  ```
443
455
 
444
456
  ## Demo
@@ -470,7 +482,7 @@ cd etcd
470
482
  touch docker-compose.yml
471
483
  export ETCD_ROOT_PW=<your_root_pass>
472
484
  export ETCD_CONFIG_ADMIN_PW=<your_config_admin_pass>
473
- mkdir -p /usr/local/etc/<your_project_name>
485
+ sudo mkdir -p /usr/local/etc/<your_project_name>
474
486
  ```
475
487
 
476
488
  Open `docker-compose.yml` and paste the following:
@@ -561,6 +573,7 @@ services:
561
573
 
562
574
  etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role add default
563
575
  etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true default read /config/sbk/global/
576
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true default read /config/sbk/members/
564
577
 
565
578
  etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role add edge
566
579
  etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true edge read /config/sbk/edge/
@@ -605,12 +618,19 @@ services:
605
618
  etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role msg msg
606
619
 
607
620
  # ---------------------------------------------------------
621
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/envs/REVISION "" || true
622
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/envs/APP_ENV development || true
623
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/envs/LOG_LEVEL warn || true
624
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/envs/MAX_L1_TTL 120 || true
625
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/envs/MAX_L2_TTL 600 || true
626
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/envs/TELEMETRY false || true
608
627
 
609
628
  etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/broker/yaml/nats "$(cat /etcd-data/nats.yml)" || true
610
629
  etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/catcher/yaml/redis "$(cat /etcd-data/redis.yml)" || true
611
630
  etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/telemetry/yaml/openobserve "$(cat /etcd-data/openobserve.yml)" || true
612
631
 
613
632
  etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/edge/yaml/auth "$(cat /etcd-data/auth.yml)" || true
633
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/edge/asset/path public || true
614
634
 
615
635
  etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/bridge/yaml/kafka "$(cat /etcd-data/kafka.yml)" || true
616
636
  etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/bridge/yaml/mqtt "$(cat /etcd-data/mqtt.yml)" || true
@@ -629,26 +649,21 @@ services:
629
649
  etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/route-otp "$(cat /etcd-data/route-otp.yml)" || true
630
650
  etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/outlook "$(cat /etcd-data/outlook.yml)" || true
631
651
 
632
- etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/edge/port/api 8765 || true
633
- etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/edge/port/sysapi 9876 || true
634
- etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/edge/asset/path public || true
635
-
636
-
637
- etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/envs/APP_ENV development || true
638
- etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/envs/LOG_LEVEL info || true
639
- etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/envs/MAX_L1_TTL 120 || true
640
- etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/envs/MAX_L2_TTL 600 || true
641
-
652
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/demo true || true
642
653
 
643
- etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/members/system add || true
644
- etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/members/system/envs/LOG_LEVEL error || true
645
- etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/members/system/envs/MAX_L1_TTL 0 || true
646
- etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/members/system/envs/MAX_L2_TTL 0 || true
647
-
648
- etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/members/gateway add || true
649
- etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/members/test add || true
650
- etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/members/sms add || true
651
- etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/members/email add || true
654
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/system true || true
655
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/system/envs/PORT 8765 || true
656
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/system/envs/BROADCAST_INTERVAL 600000 || true
657
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/system/envs/LOG_LEVEL error || true
658
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/system/envs/MAX_L1_TTL 0 || true
659
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/system/envs/MAX_L2_TTL 0 || true
660
+
661
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/gateway true || true
662
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/gateway/envs/PORT 9876 || true
663
+
664
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/test true || true
665
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/sms add || true
666
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/email add || true
652
667
 
653
668
  #etcdctl --endpoints=http://etcd:2379 --user=<your_user>:<your_pass> get /config/sbk/ --prefix
654
669
  #etcdctl --endpoints=http://etcd:2379 --user=<your_user>:<your_pass> get /config/sbk/global/app_env
package/commit-hash.mjs CHANGED
@@ -1 +1 @@
1
- export const COMMIT_HASH = '08f296a';
1
+ export const COMMIT_HASH = '2a7a879';
package/config/nats.yml CHANGED
@@ -89,7 +89,7 @@ replOptions:
89
89
  metadata:
90
90
  # region: eu-west1
91
91
 
92
- logger: CustomPino
92
+ logger: CustomLogger
93
93
  logLevel: error
94
94
 
95
95
  transporter:
@@ -7,13 +7,17 @@ import os from "os"
7
7
  import { createRequire } from 'module'
8
8
 
9
9
  import chokidar from "chokidar"
10
- import { Etcd3 } from "etcd3"
11
- import YAML from 'yaml'
10
+ import * as configHld from '#hUti/config-handler.mjs'
12
11
 
13
12
  const __filename = fileURLToPath(import.meta.url)
14
13
  const __dirname = path.dirname(__filename)
15
14
  const require = createRequire(import.meta.url)
16
15
 
16
+ /**
17
+ * Edge configs
18
+ */
19
+ const EC_ASSET_PATH = (await configHld.getConfigs(`/config/sbk/edge/asset/path`)) || "public"
20
+
17
21
 
18
22
  /**
19
23
  * Configuration path
@@ -38,86 +42,9 @@ export const DEMO_SERVICES_DIR = path.join(ABSOLUTE_PATH, 'services', 'demo')
38
42
  /**
39
43
  * Feature services absolute path
40
44
  */
41
- const SERVICES_DIR = __dirname.split('node_modules')[0]
42
-
43
-
44
- /**
45
- * User credentials for accessing and reading configurations from
46
- * the configuration server.
47
- * @type {string}
48
- */
49
- const [configUser, ConfigPass, configPort] = (process.env.SBK_CONFIG_CRED || "ur:pa:2379").split(":")
50
-
51
-
52
- /**
53
- * Configuration Reader Client Options
54
- * @type {object}
55
- */
56
- const client = new Etcd3({
57
- hosts: `http://etcd:${configPort}`,
58
- auth: {
59
- username: configUser,
60
- password: ConfigPass
61
- }
62
- })
63
-
64
-
65
- /**
66
- * Getting configurations through dynamic loading of ESM modules
67
- * ftom the path defined in environment variable
68
- * @param {string}
69
- * @return {object}
70
- */
71
- export const getConfig = async (path) => {
72
- try {
73
- const yamlText = await client.get(`/config${path}`)
74
- if ( path.startsWith("/yaml/") ) {
75
- return Object.freeze( YAML.parse(yamlText?.toString()) )
76
- }
77
- else {
78
- return yamlText?.toString()
79
- }
80
-
81
- } catch (err) {
82
- throw new Error(`Unable to read configuration : ${err.message}`)
83
- }
84
- }
85
-
86
-
87
- export const watchConfig = async (path, callback) => {
88
- const watcher = await client
89
- .watch()
90
- .prefix(`/config${path}`)
91
- .create()
92
-
93
- watcher.on("put", event => {
94
- const evVal = path.startsWith("/yaml/")
95
- ? Object.freeze( YAML.parse(event.value.toString()) )
96
- : event.value?.toString()
97
- callback(
98
- "put",
99
- event.key?.toString(),
100
- evVal
101
- )
102
- })
103
-
104
- watcher.on("delete", event => {
105
- callback(
106
- "delete",
107
- event.key.toString(),
108
- null
109
- )
110
- })
111
-
112
- }
113
-
114
-
115
-
116
- /**
117
- * Getting server configuration.
118
- * @type {string}
119
- */
120
- const CONFIG = {assetPath: "public"} // await getConfig('server')
45
+ const SERVICES_DIR = /node_modules/.test(__dirname)
46
+ ? __dirname.split('node_modules')[0]
47
+ : __dirname.replace("/helper/file","")
121
48
 
122
49
 
123
50
  /**
@@ -127,7 +54,7 @@ export const assetPath = {
127
54
  rootFolder: path
128
55
  .join(
129
56
  ABSOLUTE_PATH,
130
- CONFIG.assetPath,
57
+ EC_ASSET_PATH,
131
58
  ),
132
59
  }
133
60
 
@@ -65,12 +65,17 @@ const pinoOptions = {
65
65
  }
66
66
 
67
67
 
68
- export default {
69
- type: "Pino",
70
- options: {
71
- level: (process.env.SBK_LOG_LEVEL || "info").toLowerCase(),
72
- pino: {
73
- options: pinoOptions
68
+ export default (opts) => {
69
+ const { logger, logLevel } = opts
70
+ return logger == "CustomLogger"
71
+ ? {
72
+ type: "Pino",
73
+ options: {
74
+ level: (logLevel || "info").toLowerCase(),
75
+ pino: {
76
+ options: pinoOptions
77
+ }
78
+ }
74
79
  }
75
- }
76
- }
80
+ : "Console"
81
+ }
@@ -1,7 +1,7 @@
1
1
  import { Cachers } from "moleculer"
2
2
 
3
- const MAX_L1_TTL = Math.min(process.env.MAX_L1_TTL || 600, 600) // 10 minutes in seconds
4
- const MAX_L2_TTL = Math.min(process.env.MAX_L2_TTL || 86400, 86400) // 24 hours in seconds
3
+ const MAX_L1_TTL = 600 // 10 minutes in seconds
4
+ const MAX_L2_TTL = 86400 // 24 hours in seconds
5
5
 
6
6
  export default class HybridCacher extends Cachers.Base {
7
7
  constructor(opts = {}) {
@@ -15,7 +15,7 @@ export const etcdCred = errHdl.validateConfigCred(process.env.SBK_CONFIG_CRED)
15
15
  * Configuration Reader Client Options
16
16
  * @type {object}
17
17
  */
18
- const client = new Etcd3({
18
+ export const client = new Etcd3({
19
19
  hosts: `http://etcd:${etcdCred[2]}`,
20
20
  auth: {
21
21
  username: etcdCred[0],
@@ -107,6 +107,7 @@ export const watchConfigs = async (path, callback) => {
107
107
  null
108
108
  )
109
109
  })
110
+ return watcher
110
111
  }
111
112
  catch (err) {
112
113
  throw new Error(`Unable to watck configuration: ${err.message}`)
@@ -114,3 +115,8 @@ export const watchConfigs = async (path, callback) => {
114
115
 
115
116
  }
116
117
 
118
+ export const putConfig = async(path, data) => {
119
+ await client.put(path)
120
+ .value(data)
121
+ }
122
+
@@ -12,6 +12,7 @@ const configCredRegex = /^[a-zA-Z0-9]{3,16} [a-zA-Z0-9!@#$^_-]{3,16} [0-9]{4,5}$
12
12
  const serviceNmRegx = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/
13
13
  const portRegx = /^876[0-9]$/
14
14
  const logLvlRegx = /^(fatal|error|warn|info|debug|trace)$/i
15
+ const telemetryRegx = /^(true|false)$/i
15
16
 
16
17
 
17
18
  /**
@@ -30,17 +31,16 @@ export const checkMinNoveVer = () => {
30
31
 
31
32
 
32
33
  /**
33
- * Validate NOVE_ENV entry
34
+ * Validate APP_ENV entry
34
35
  * @return {string}
35
36
  *
36
37
  * @throws error
37
38
  */
38
- export const isValidNodeEnv = () => {
39
- const env = process.env.NODE_ENV
40
- if (!envRegx.test(env || "//<>")) {
41
- throw new Error(`NODE_ENV is '${env}', it must be 'development', 'production', or 'testing'`)
39
+ export const isValidAppEnv = (env) => {
40
+ if (!envRegx.test(env)) {
41
+ throw new Error(`APP_ENV is '${env}', it must be 'development', 'production', or 'testing'`)
42
42
  }
43
- return sysClassification[process.env.NODE_ENV]
43
+ return sysClassification[env]
44
44
  }
45
45
 
46
46
 
@@ -62,8 +62,8 @@ export const isValidCommitHash = (hs) => {
62
62
  * Validate namespace
63
63
  * @retutn {string}
64
64
  */
65
- export const validateNamespace = () => {
66
- return `${isValidNodeEnv()}-sbk-${isValidCommitHash(COMMIT_HASH)}`.toUpperCase()
65
+ export const validateNamespace = (env) => {
66
+ return `${isValidAppEnv(env)}-sbk-${isValidCommitHash(COMMIT_HASH)}`.toUpperCase()
67
67
  }
68
68
 
69
69
 
@@ -74,29 +74,23 @@ export const validateNamespace = () => {
74
74
  * @throws error
75
75
  */
76
76
  export const validateConfigCred = (env) => {
77
- // const env = process.env.SBK_CONFIG_CRED
78
77
  if(!configCredRegex.test(env)){
79
- throw new Error(`SBK_CONFIG_CRED is "${env}". It must be a valid Etcd user credential in the format "user password port".`)
78
+ throw new Error(`Environment variable SBK_CONFIG_CRED is "${env}". It must be a valid Etcd user credential in the format "user password port".`)
80
79
  }
81
80
  return env.split(" ")
82
81
  }
83
82
 
84
83
 
85
84
  /**
86
- * Validate that the environment variable MAX_L1_TTL is defined and does not exceed 120 seconds
85
+ * Validate that the MAX_L1_TTL is defined and does not exceed 120 seconds
87
86
  * @return {number} between 0 to 120
88
87
  *
89
88
  * @throws error
90
89
  */
91
- export const validateL1TTL = () => {
92
- const ttl = process.env.MAX_L1_TTL
93
-
94
- if (ttl === undefined) return 120
95
-
90
+ export const validateL1TTL = (ttl = 120) => {
96
91
  const num = Number(ttl)
97
-
98
92
  if (!Number.isInteger(num) || num < 0 || num > 120) {
99
- throw new Error(`Environment variable 'MAX_L1_TTL' is ${ttl}, it must be between 0 and 120`)
93
+ throw new Error(`Configuration variable 'MAX_L1_TTL' is ${ttl}, it must be between 0 and 120`)
100
94
  }
101
95
 
102
96
  return num
@@ -104,20 +98,15 @@ export const validateL1TTL = () => {
104
98
 
105
99
 
106
100
  /**
107
- * Validate that the environment variable MAX_L2_TTL is defined and does not exceed 600 seconds
101
+ * Validate that the MAX_L2_TTL is defined and does not exceed 600 seconds
108
102
  * @return {number} between 0 to 600
109
103
  *
110
104
  * @throws error
111
105
  */
112
- export const validateL2TTL = () => {
113
- const ttl = process.env.MAX_L2_TTL
114
-
115
- if (ttl === undefined) return 600
116
-
106
+ export const validateL2TTL = (ttl = 600) => {
117
107
  const num = Number(ttl)
118
-
119
108
  if (!Number.isInteger(num) || num < 0 || num > 600) {
120
- throw new Error(`Environment variable 'MAX_L2_TTL' is ${ttl}, it must be between 0 and 600`)
109
+ throw new Error(`Configuration variable 'MAX_L2_TTL' is ${ttl}, it must be between 0 and 600`)
121
110
  }
122
111
 
123
112
  return num
@@ -125,16 +114,16 @@ export const validateL2TTL = () => {
125
114
 
126
115
 
127
116
  /**
128
- * Validate environment variable SBK_PORT for Apigateway port number
117
+ * Validate configuration variable SBK_PORT for Apigateway port number
129
118
  * @return {number} between 8760 to 8769
130
119
  *
131
120
  * @throws error
132
121
  */
133
- export const validatePort = () => {
134
- if ( process.env.SBK_PORT !== undefined && !(portRegx.test(process.env.SBK_PORT)) ) {
135
- throw new Error(`Environment variable 'SBK_PORT' is ${process.env.SBK_PORT}, it must be between 8760 and 8769`)
122
+ export const validatePort = (port) => {
123
+ if ( port !== undefined && !(portRegx.test(port)) ) {
124
+ throw new Error(`Configuration variable 'PORT' is ${port}, it must be between 8760 and 8769`)
136
125
  }
137
- return Number(process.env.SBK_PORT || 8765)
126
+ return Number(port || 8765)
138
127
  }
139
128
 
140
129
 
@@ -146,7 +135,7 @@ export const validatePort = () => {
146
135
  */
147
136
  export const validateLogLevel = (env) => {
148
137
  if ( !(logLvlRegx.test(env)) ) {
149
- throw new Error(`SBK_LOG_LEVEL is ${env}, it must be fatal | error | warn | info | debug | trace `)
138
+ throw new Error(`LOG_LEVEL is ${env}, it must be fatal | error | warn | info | debug | trace `)
150
139
  }
151
140
  return env
152
141
  }
@@ -202,22 +191,47 @@ export const validateServiceName = (schema, pkgName) => {
202
191
 
203
192
 
204
193
  /**
205
- * Graceful shutdown handler
194
+ * Telemetry enable or disable inputs
195
+ * @param {string}
196
+ * @return {boolean}
206
197
  */
207
- export const shutdownHdl = async (broker, signal, err=null) => {
208
- if(err){
209
- broker.logger.error({err}, `${signal}: `)
198
+ export const validateTelemetry = (env) => {
199
+ if ( !(telemetryRegx.test(env)) ) {
200
+ throw new Error(`TELEMETRY is ${env}, it must be true | false `)
210
201
  }
202
+ return env.toLowerCase() === "true" ? true : false
203
+ }
204
+
205
+ /**
206
+ * Validate config revision
207
+ * @param {string}
208
+ * @return {object}
209
+ */
210
+ export const validateConfRevision = (env) => {
211
+ env = env || '{"pub":0,"edg":0,"mem":{"system":0,"gateway":0}}'
212
+ return JSON.parse(env)
213
+ }
214
+
215
+
216
+ /**
217
+ * Graceful shutdown handler
218
+ */
219
+ export const gracefulShutdown = async (broker, signal, err=null) => {
211
220
 
212
- broker.logger.info({message: `Received ${signal}, Stopping broker...`})
213
-
221
+ broker.logger.info({message: `${signal} detected, Stopping the broker...`})
214
222
  try {
215
- await broker.stop()
216
- broker.logger.info({message: "Broker stopped gracefully."})
217
-
218
- process.exit(0)
219
- } catch (err) {
220
- broker.logger.error({err}, "Error during broker shutdown:")
223
+ if(err) {
224
+ await broker.stop()
225
+ broker.logger.error({message: `Broker stopped after detecting the ${signal} signal.`}, {err})
226
+ process.exit(1)
227
+ }
228
+ else{
229
+ await broker.stop()
230
+ broker.logger.info({message: "Broker stopped gracefully."})
231
+ process.exit(0)
232
+ }
233
+ } catch (brokerStoppingErr) {
234
+ broker.logger.error({brokerStoppingErr}, "Unable to stop the broker.")
221
235
  process.exit(1)
222
236
  }
223
237
  }
@@ -229,7 +243,7 @@ export const shutdownHdl = async (broker, signal, err=null) => {
229
243
  *
230
244
  * @type {Object}
231
245
  */
232
- export const SbkErrorMiddleware = {
246
+ export const ErrorFormatterMW = {
233
247
  localAction: (next) => {
234
248
  return async(ctx) => {
235
249
  try {
@@ -287,7 +301,7 @@ export const SbkErrorMiddleware = {
287
301
  * Ensures all errors include a standard set of fields such as status code,
288
302
  * message, and optional metadata for client consumption.
289
303
  */
290
- export const formatHttpErrors = (req, res, err)=>{
304
+ export const httpErrorFormatter = (req, res, err)=>{
291
305
  const code = err.code || 500
292
306
  const errorBody = {
293
307
  ...(err?.data || { message: err.message }),
@@ -4,14 +4,24 @@ export const validateGlobalConfigs = async(prefix) => {
4
4
  try{
5
5
  const nodeVer = errHdl.checkMinNoveVer()
6
6
  const configHdl = await import("./config-handler.mjs")
7
+ const { serviceDtls } = await import("#hFil/esm-loading.mjs")
7
8
  const globalConfigs = await configHdl.getConfigAll(prefix)
8
9
 
10
+
11
+ const isServiceRemoved = (((await configHdl.getConfigs( `/config/sbk/members/${serviceDtls.name}` )) || "false") == "false")
12
+ if ( serviceDtls.name != "samanbayaka" && isServiceRemoved ) {
13
+ throw new Error (`The service "${serviceDtls.name}" is not in the trusted list. Please contact your CONFIGADMIN for assistance.`)
14
+ }
15
+
9
16
  return Object.freeze({
10
17
  nodeVer,
11
18
  configCred: configHdl.etcdCred,
12
- maxL1TTL: errHdl.validateL1TTL(),
13
- maxL2TTL: errHdl.validateL2TTL(),
14
- logLevel: errHdl.validateLogLevel(globalConfigs.LOG_LEVEL),
19
+ maxL1TTL: errHdl.validateL1TTL(globalConfigs?.MAX_L1_TTL),
20
+ maxL2TTL: errHdl.validateL2TTL(globalConfigs?.MAX_L2_TTL),
21
+ logLevel: errHdl.validateLogLevel(globalConfigs?.LOG_LEVEL),
22
+ telemetry: errHdl.validateTelemetry(globalConfigs?.TELEMETRY),
23
+ configRevision: errHdl.validateConfRevision(globalConfigs?.REVISION),
24
+ serviceDtls,
15
25
  hostEntry: {
16
26
  nats: await errHdl.validateHostEntry('nats'),
17
27
  redis: await errHdl.validateHostEntry('redis'),
@@ -19,7 +29,7 @@ export const validateGlobalConfigs = async(prefix) => {
19
29
  redpanda: await errHdl.validateHostEntry('redpanda', true),
20
30
  openobserve: await errHdl.validateHostEntry('openobserve', true),
21
31
  },
22
- namespaceTxt: errHdl.validateNamespace(),
32
+ namespaceTxt: errHdl.validateNamespace(globalConfigs.APP_ENV),
23
33
  })
24
34
  }
25
35
  catch(err){
@@ -32,4 +42,4 @@ export const validateGlobalConfigs = async(prefix) => {
32
42
  /**
33
43
  * Validate the Samanbayaka global configurations
34
44
  */
35
- export const SBK_GLOBAL_CONFIGS = await validateGlobalConfigs("/config/sbk/global/envs/")
45
+ export const SBK_GLOBAL_CONFIGS = await validateGlobalConfigs("/config/sbk/global/envs/")
@@ -22,7 +22,7 @@ const resource = resourceFromAttributes({
22
22
  // })
23
23
 
24
24
 
25
- export const createSdk = (config) => {
25
+ export const createOpenTelemetryExporters = (config) => {
26
26
  const sdk = new NodeSDK({
27
27
  resource,
28
28
 
@@ -52,11 +52,9 @@ export const createSdk = (config) => {
52
52
  }
53
53
 
54
54
 
55
-
56
-
57
55
  const tracer = trace.getTracer("moleculer")
58
56
 
59
- export const OpenTelemetry = () => {
57
+ export const OpenTelemetryMW = (isEnabled) => {
60
58
  const meter = metrics.getMeter("moleculer")
61
59
 
62
60
  const requestCounter = meter.createCounter("moleculer_requests_total", {
@@ -73,8 +71,6 @@ export const OpenTelemetry = () => {
73
71
  name: "otel",
74
72
 
75
73
  localAction(next, action) {
76
- const isEnabled = process.env.SBK_TELEMETRY_ENABLE?.toLowerCase() === "true"
77
-
78
74
  if ( !isEnabled ) return next
79
75
  return async (ctx) => {
80
76
  const startTime = Date.now()
package/index.mjs CHANGED
@@ -2,104 +2,185 @@
2
2
  import { ServiceBroker, Errors } from "moleculer"
3
3
 
4
4
  import {SBK_GLOBAL_CONFIGS} from '#hUti/global-configs-validator.mjs'
5
- import {
6
- shutdownHdl,
7
- validateServiceName,
8
- SbkErrorMiddleware,
9
- } from '#hUti/error-handler.mjs'
10
-
11
- import * as configHld from '#hUti/config-handler.mjs'
12
-
13
- import { createSdk, OpenTelemetry } from '#hUti/telemetry.mjs'
14
- import {
15
- serviceDtls,
16
- getConfig,
17
- watchConfig,
18
- DEMO_SERVICES_DIR
19
- } from '#hFil/esm-loading.mjs'
5
+ import * as configHdl from '#hUti/config-handler.mjs'
6
+
20
7
  import AjvValidator from "#hMol/AjvValidator.mjs"
21
- import customLogger from "#hMol/CustomLogger.mjs"
8
+ import CustomLogger from "#hMol/CustomLogger.mjs"
22
9
  import HybridCacher from "#hMol/HybridCacher.mjs"
23
- import about from '#sAbt/index.mjs'
24
- import apiGateway from '#sApi/index.mjs'
25
- import sysApi from '#sSys/index.mjs'
26
- import { auxBrokerParamsValidator } from '#hUti/aux-broker-params-validator.mjs'
27
- import * as demo from '#sDmo/index.mjs'
28
-
29
-
30
- const BROKER_CONFIG = await configHld.getConfigs('/config/sbk/global/broker/yaml/nats')
31
- const CATCHER_CONFIG = await configHld.getConfigs('/config/sbk/global/catcher/yaml/redis')
32
- const TELEMETRY_CONFIG = await configHld.getConfigs('/config/sbk/global/telemetry/yaml/openobserve')
33
-
34
- const sbkLoggers = {
35
- "CustomPino": customLogger
36
- }
37
10
 
11
+ import { gracefulShutdown, validateServiceName, ErrorFormatterMW } from '#hUti/error-handler.mjs'
12
+ import { createOpenTelemetryExporters, OpenTelemetryMW } from '#hUti/telemetry.mjs'
38
13
 
39
14
  /**
40
- * Checks whether the REPL flag is passed in CLI arguments.
41
- * @type {Boolean}
15
+ * Global Configs
42
16
  */
43
- const isReplEnabled = (
44
- process.argv.includes("-r")
45
- || process.argv.includes("--repl")
46
- ) || false
17
+ const BROKER_CONFIG = await configHdl.getConfigs('/config/sbk/global/broker/yaml/nats')
18
+ const CATCHER_CONFIG = await configHdl.getConfigs('/config/sbk/global/catcher/yaml/redis')
19
+ const TELEMETRY_CONFIG = await configHdl.getConfigs('/config/sbk/global/telemetry/yaml/openobserve')
47
20
 
21
+ /**
22
+ * Local configs
23
+ */
24
+ const LC_LOG_LEVEL = await configHdl.getConfigs(`/config/sbk/members/${SBK_GLOBAL_CONFIGS.serviceDtls.name}/envs/LOG_LEVEL`)
25
+ const LC_TELEMETRY = await configHdl.getConfigs(`/config/sbk/members/${SBK_GLOBAL_CONFIGS.serviceDtls.name}/envs/TELEMETRY`)
26
+ const LC_MAX_L1_TTL = await configHdl.getConfigs(`/config/sbk/members/${SBK_GLOBAL_CONFIGS.serviceDtls.name}/envs/MAX_L1_TTL`)
27
+ const LC_MAX_L2_TTL = await configHdl.getConfigs(`/config/sbk/members/${SBK_GLOBAL_CONFIGS.serviceDtls.name}/envs/MAX_L2_TTL`)
48
28
 
49
29
  /**
50
- * Initialize OTLP metrics and telemetry exporter
30
+ * Service Broker initialization params with default values
51
31
  */
52
- const sdk = await createSdk(TELEMETRY_CONFIG)
32
+ const LOG_LEVEL = LC_LOG_LEVEL || SBK_GLOBAL_CONFIGS.logLevel || "debug"
33
+ const TELEMETRY = LC_TELEMETRY || SBK_GLOBAL_CONFIGS.telemetry || true
34
+ const MAX_L1_TTL = LC_MAX_L1_TTL || SBK_GLOBAL_CONFIGS.maxL1TTL || 120
35
+ const MAX_L2_TTL = LC_MAX_L2_TTL || SBK_GLOBAL_CONFIGS.maxL2TTL || 600
53
36
 
54
37
 
38
+ const createSbkServices = async(schemas, isREPL = false) => {
55
39
 
56
- /**
57
- * Moleculer srvice broker configurations
58
- * @type {ServiceBroker}
59
- */
60
- const brokerInit = (brokerConfig) => {
61
- return new ServiceBroker({
62
- ...brokerConfig,
63
- ...{
64
- namespace: SBK_GLOBAL_CONFIGS.namespaceTxt,
65
- nodeID: serviceDtls.id,
66
- validator: new AjvValidator(),
67
- logger: sbkLoggers[brokerConfig.logger] || "Console",
68
- cacher: new HybridCacher(CATCHER_CONFIG),
69
- },
70
- middlewares: [SbkErrorMiddleware, OpenTelemetry],
71
- })
72
- }
40
+ /**
41
+ * Initialize OTLP metrics and telemetry exporter
42
+ */
43
+ const sdk = await createOpenTelemetryExporters(TELEMETRY_CONFIG)
73
44
 
45
+ /**
46
+ * Moleculer srvice broker configurations
47
+ * @type {ServiceBroker}
48
+ */
49
+ const broker = new ServiceBroker({
50
+ ...BROKER_CONFIG,
51
+ ...{
52
+ namespace: SBK_GLOBAL_CONFIGS.namespaceTxt,
53
+ nodeID: SBK_GLOBAL_CONFIGS.serviceDtls.id,
54
+ validator: new AjvValidator(),
55
+ logLevel: LOG_LEVEL,
56
+ logger: CustomLogger({
57
+ logger: BROKER_CONFIG.logger,
58
+ logLevel: LOG_LEVEL
59
+ }),
60
+ cacher: new HybridCacher({
61
+ ...CATCHER_CONFIG,
62
+ ...{
63
+ ttl: [MAX_L2_TTL, MAX_L1_TTL]
64
+ }
65
+ }),
66
+ },
67
+ middlewares: [ErrorFormatterMW, OpenTelemetryMW(TELEMETRY)],
68
+ })
74
69
 
70
+ /**
71
+ * Creating moleculer services
72
+ */
73
+ schemas = Array.isArray(schemas) ? schemas : [schemas]
74
+ for ( const [index, schema] of schemas.entries() ) {
75
75
 
76
+ /**
77
+ * Listner for configuration revision
78
+ * @type {Object}
79
+ */
80
+ const configRevisionListner = {
81
+ "config.revisions": (ctx) => {
82
+ setImmediate(async () => {
83
+ ctx.broker.logger.debug({message: "Config revision received"}, ctx.params)
84
+
85
+ /**
86
+ * Restart the service when the global configuration is updated
87
+ */
88
+ if( SBK_GLOBAL_CONFIGS.configRevision.pub != ctx.params.pub ){
89
+ ctx.broker.logger.warn(`Global configuration deployed by CONFIGADMIN and the service "${SBK_GLOBAL_CONFIGS.serviceDtls.name}" is restarting in progress...`)
90
+ await ctx.broker.stop()
91
+ process.exit(0)
92
+ }
93
+
94
+ /**
95
+ * Restart the service if it is an edge service in response to an edge configuration update
96
+ */
97
+ if(
98
+ SBK_GLOBAL_CONFIGS.configRevision.edg != ctx.params.edg
99
+ && schema?.settings?.port != undefined
100
+ ){
101
+ ctx.broker.logger.warn(`Edge configuration deployed by CONFIGADMIN and the service "${SBK_GLOBAL_CONFIGS.serviceDtls.name}" is restarting in progress...`)
102
+ await ctx.broker.stop()
103
+ process.exit(0)
104
+ }
105
+
106
+ /**
107
+ * Restart the service when the corresponding configuration is updated
108
+ */
109
+ if(
110
+ SBK_GLOBAL_CONFIGS.configRevision.mem[SBK_GLOBAL_CONFIGS.serviceDtls.name] != ctx.params.mem[SBK_GLOBAL_CONFIGS.serviceDtls.name]
111
+ && ctx.params.mem[SBK_GLOBAL_CONFIGS.serviceDtls.name] >= 0
112
+ ){
113
+ ctx.broker.logger.warn(`Configuration deployed by CONFIGADMIN and the service "${SBK_GLOBAL_CONFIGS.serviceDtls.name}" is restarting in progress...`)
114
+ await ctx.broker.stop()
115
+ process.exit(0)
116
+ }
117
+
118
+ /**
119
+ * Stop the service when CONFIGADMIN removes it from the trusted list
120
+ */
121
+ if( ctx.params.mem[SBK_GLOBAL_CONFIGS.serviceDtls.name] < 0 ){
122
+ ctx.broker.logger.error(`The service "${SBK_GLOBAL_CONFIGS.serviceDtls.name}" was stopped by CONFIGADMIN.`)
123
+ await ctx.broker.stop()
124
+ process.exit(1)
125
+ }
126
+ })
127
+ }
76
128
 
77
- let broker = brokerInit(BROKER_CONFIG)
129
+ }
78
130
 
131
+ /**
132
+ * merge configuration listner with user defined events
133
+ * @type {Object}
134
+ */
135
+ schema.events = {
136
+ ...schema?.events,
137
+ ...configRevisionListner
138
+ }
79
139
 
80
- /**
81
- * Listen for force stop signals
82
- */
83
- process.on("beforeExit", async () => {
84
- await sdk.shutdown()
85
- })
86
- process.on("SIGINT", (signal) => {
87
- shutdownHdl(broker, signal)
88
- }) // Ctrl+C
89
- process.on("SIGTERM", (signal) => {
90
- shutdownHdl(broker, signal)
91
- }) // kill command
140
+ if( index == 0 ) validateServiceName(schema, SBK_GLOBAL_CONFIGS.serviceDtls.name)
141
+ broker.createService(schema)
142
+ }
92
143
 
93
144
 
94
- /**
95
- * Optional: handle uncaught errors
96
- */
97
- process.on("uncaughtException", (err) => {
98
- shutdownHdl(broker, "Uncaught Exception", err)
99
- })
100
- process.on("unhandledRejection", (err) => {
101
- shutdownHdl(broker, "Unhandled Rejection", err)
102
- })
145
+ if(isREPL){
146
+ /**
147
+ * Start broker with repl mode
148
+ */
149
+ broker.start().then(() => broker.repl())
150
+ }
151
+ else{
152
+ /**
153
+ * Start services
154
+ */
155
+ broker.start()
156
+ }
157
+
158
+
159
+ /**
160
+ * Listen for force stop signals
161
+ */
162
+ process.on("beforeExit", async () => {
163
+ await configHdl.client.close()
164
+ await sdk.shutdown()
165
+ })
166
+ process.on("SIGINT", (signal) => {
167
+ gracefulShutdown(broker, signal)
168
+ }) // Ctrl+C
169
+ process.on("SIGTERM", (signal) => {
170
+ gracefulShutdown(broker, signal)
171
+ }) // kill command
172
+
173
+
174
+ /**
175
+ * Optional: handle uncaught errors
176
+ */
177
+ process.on("uncaughtException", (err) => {
178
+ gracefulShutdown(broker, "Uncaught Exception", err)
179
+ })
180
+ process.on("unhandledRejection", (err) => {
181
+ gracefulShutdown(broker, "Unhandled Rejection", err)
182
+ })
183
+ }
103
184
 
104
185
 
105
186
  /**
@@ -107,26 +188,32 @@ process.on("unhandledRejection", (err) => {
107
188
  */
108
189
  export default {
109
190
  Errors,
110
- getConfig,
191
+ getConfigs: configHdl.getConfigs,
111
192
 
112
193
  /**
113
194
  * Loading Demo
114
195
  */
115
196
  createDemo: async() => {
116
- const gtWy = {...apiGateway}
117
- gtWy.settings.routes[0].path = "/api/demo"
118
- broker.createService(about)
119
- broker.createService(gtWy)
120
- broker.createService(demo.user)
121
- broker.createService(demo.role)
122
- broker.createService(demo.mail)
123
- broker.createService(demo.sms)
197
+ const { default: about } = await import('#sAbt/index.mjs')
198
+ const { default: apiGateway } = await import('#sApi/index.mjs')
199
+ const demo = await import('#sDmo/index.mjs')
124
200
 
201
+ const gtWy = {...apiGateway}
202
+ gtWy.name = "demo"
203
+ gtWy.settings.port = 3000
204
+ gtWy.settings.routes = gtWy.settings.routes.map((rt) => {
205
+ rt.path = `/demo${rt.path}`
206
+ return rt
207
+ })
208
+ createSbkServices([
209
+ gtWy,
210
+ about,
211
+ demo.user,
212
+ demo.role,
213
+ demo.mail,
214
+ demo.sms
215
+ ], true)
125
216
 
126
- /**
127
- * Start broker with repl mode
128
- */
129
- broker.start().then(() => broker.repl())
130
217
  },
131
218
 
132
219
  /**
@@ -134,80 +221,27 @@ export default {
134
221
  * @return {void}
135
222
  */
136
223
  registerSystemAPI: async () => {
137
- validateServiceName(sysApi, serviceDtls.name)
138
- broker.createService(sysApi)
139
-
140
- /**
141
- * Start broker
142
- */
143
- broker.start()
224
+ const { default: sysApi } = await import('#sSys/index.mjs')
225
+ createSbkServices(sysApi)
226
+
144
227
  },
145
228
 
146
229
  registerEdgeAPI: async () => {
147
- validateServiceName(apiGateway, serviceDtls.name)
148
- broker.createService(about)
149
- broker.createService(apiGateway)
150
-
151
- /**
152
- * Start broker
153
- */
154
- broker.start()
230
+ const { default: about } = await import('#sAbt/index.mjs')
231
+ const { default: apiGateway } = await import('#sApi/index.mjs')
232
+ createSbkServices([apiGateway, about])
155
233
 
156
234
  },
157
235
 
158
236
 
159
237
  registerServices: async (schema) => {
160
-
161
- validateServiceName(schema, serviceDtls.name)
162
- const whitelistedServices = await configHld.getConfigKeys( `/config/sbk/global/members/${serviceDtls.name}` )
163
-
164
- if ( !whitelistedServices.includes( serviceDtls.name ) ) {
165
- throw new Error (`The service "${serviceDtls.name}" is not whitelisted. Please contact your system administrator for assistance.`)
166
- }
167
-
168
- /**
169
- * Create moleculer service from schema object
170
- */
171
- broker.createService(schema)
172
-
173
- /**
174
- * Start broker
175
- */
176
- broker.start()
177
-
178
- /**
179
- * Restart service on configuration change
180
- * @param {string} config path like '/yaml/nats'
181
- * @param {function} async callback function
182
- * @return {void}
183
- */
184
- configHld.watchConfigs('/config/sbk/global/broker/yaml/nats', async (ev, key, val) => {
185
- broker.stop()
186
- broker.logger.warn(`New configuration deployed and the service ${serviceDtls.name} is restarting in progress...`)
187
-
188
- broker = brokerInit(val)
189
-
190
- broker.createService(schema)
191
- broker.start()
192
-
193
- broker.logger.warn(`The service ${serviceDtls.name} restarted with new configuration.`)
194
- })
195
-
196
- /**
197
- * Service stop on backlist of the service from congiguration
198
- */
199
- configHld.watchConfigs(`/config/sbk/global/members/${serviceDtls.name}`, async (ev, key, val) => {
200
- broker.stop()
201
- broker.logger.error(`The service ${serviceDtls.name} blacklisted and stopped.`)
202
- process.exit(0)
203
-
204
- })
238
+ createSbkServices(schema)
205
239
 
206
240
  },
207
241
 
208
242
 
209
243
  registerBridgeServices: async( type, brokerOpts = {}, callback = () => {}) => {
210
-
244
+ const { auxBrokerParamsValidator } = await import('#hUti/aux-broker-params-validator.mjs')
211
245
  const {logLevel, gzip, msgPack, rest, ...opts} = brokerOpts
212
246
  const paramObj = {type, opts, callback}
213
247
 
@@ -236,22 +270,14 @@ export default {
236
270
  * Service create for kafka producer
237
271
  * @type {object}
238
272
  */
239
- validateServiceName(opts, serviceDtls.name)
240
273
  if( opts.name.startsWith("producer") ){
241
- broker.createService(
242
- auxBroker.producer( opts, callback )
243
- )
274
+ createSbkServices(auxBroker.producer( opts, callback ))
275
+
244
276
  }
245
277
  else {
246
- broker.createService(
247
- auxBroker.consumer( opts, callback )
248
- )
278
+ createSbkServices(auxBroker.consumer( opts, callback ))
279
+
249
280
  }
250
-
251
- /**
252
- * Start broker
253
- */
254
- broker.start()
255
281
 
256
282
  },
257
283
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "samanbayaka",
3
- "version": "0.0.25",
3
+ "version": "0.0.26",
4
4
  "description": "Moleculer Gateway service with kafka transporter",
5
5
  "homepage": "https://gitlab.com/dalal.suvendu/samanbayaka#readme",
6
6
  "bugs": {
@@ -5,9 +5,15 @@ import cookieParser from "cookie-parser"
5
5
  import helmet from "helmet"
6
6
  import compression from "compression"
7
7
 
8
- import {formatHttpErrors} from '#hUti/error-handler.mjs'
8
+ import * as configHld from '#hUti/config-handler.mjs'
9
+ import {httpErrorFormatter} from '#hUti/error-handler.mjs'
9
10
  import { initOpenId, authorize } from '#hUti/access-token-validator.mjs'
10
11
 
12
+ /**
13
+ * Local configs
14
+ */
15
+ const LC_PORT = (await configHld.getConfigs(`/config/sbk/members/gateway/envs/PORT`)) || 8765
16
+
11
17
  export default {
12
18
  name: "gateway",
13
19
  mixins: [
@@ -22,7 +28,7 @@ export default {
22
28
  },
23
29
 
24
30
  settings: {
25
- port: process.env.SBK_PORT || 8765,
31
+ port: LC_PORT,
26
32
 
27
33
  /**
28
34
  * Middleware mode (for ExpressJS)
@@ -129,7 +135,7 @@ export default {
129
135
  */
130
136
  onError(req, res, err) {
131
137
 
132
- formatHttpErrors(req, res, err)
138
+ httpErrorFormatter(req, res, err)
133
139
 
134
140
  /**
135
141
  * Custom logging
@@ -1,10 +1,10 @@
1
1
  import { Kafka, logLevel, Partitioners, CompressionTypes } from 'kafkajs'
2
2
  import msgpack5 from 'msgpack5'
3
3
 
4
- import { getConfig } from '#hFil/esm-loading.mjs'
4
+ import * as configHdl from '#hUti/config-handler.mjs'
5
5
 
6
6
  const msgpack = msgpack5()
7
- // const KAFKA_CONFIG = await getConfig('/yaml/kafkajs')
7
+ const KAFKA_CONFIG = await configHdl.getConfigs('/config/sbk/bridge/yaml/kafka')
8
8
 
9
9
  const setKafkaConfig = (opts) => {
10
10
  opts.logLevel = opts?.logLevel ?? KAFKA_CONFIG.logLevel
@@ -163,7 +163,7 @@ export const consumer = (opts, callback) => {
163
163
 
164
164
  await consumer.subscribe({ topic: topicRegxObj, fromBeginning: true })
165
165
 
166
- // for debug only
166
+ // for debug only to consume individual message
167
167
  // await consumer.run({
168
168
  // eachMessage: async ({ topic, partition, message }) => {
169
169
  // const decoded = opts?.msgPack == false
@@ -8,11 +8,23 @@ import helmet from "helmet"
8
8
  import scalarHTML from "./scalar.mjs"
9
9
  import swStatsMw from "./sw-stats-mw.mjs"
10
10
  import {
11
- getConfig,
11
+ // getConfig,
12
12
  assetPath,
13
13
  // openApiConfig
14
14
  } from '#hFil/esm-loading.mjs'
15
15
 
16
+ import * as configHld from '#hUti/config-handler.mjs'
17
+ import * as errHdl from '#hUti/error-handler.mjs'
18
+
19
+
20
+ /**
21
+ * Local configs
22
+ */
23
+ const LC_PORT = (await configHld.getConfigs(`/config/sbk/members/system/envs/PORT`)) || 9876
24
+ const LC_BROADCAST_INTERVAL = await configHld.getConfigs(`/config/sbk/members/system/envs/BROADCAST_INTERVAL`)
25
+
26
+
27
+
16
28
  const CONFIG = {
17
29
  mgmPort: 9876,
18
30
 
@@ -21,7 +33,7 @@ const CONFIG = {
21
33
  */
22
34
  openApiInfo: [
23
35
  {
24
- url: `http://dev.sbk.wbsedcl.in:${9876}`,
36
+ url: `http://dev.sbk.wbsedcl.in:${LC_PORT}`,
25
37
  summary: "ESB",
26
38
  description: "An API Gateway service provider."
27
39
  }
@@ -43,11 +55,11 @@ export default {
43
55
  name: "system",
44
56
  mixins: [
45
57
  ApiGateway,
46
- OpenApi
58
+ // OpenApi
47
59
  ],
48
60
 
49
61
  settings: {
50
- port: CONFIG.mgmPort || 8089,
62
+ port: LC_PORT,
51
63
 
52
64
  /**
53
65
  * Global middlewares. Applied to all routes.
@@ -137,6 +149,11 @@ export default {
137
149
  return ctx.call("$node.actions")
138
150
  },
139
151
 
152
+ broadcastConfigRevision: async (ctx) => {
153
+ const CONFIG_REVISION = errHdl.validateConfRevision(await configHld.getConfigs(`/config/sbk/global/envs/REVISION`))
154
+ ctx.broker.broadcast("config.revisions", CONFIG_REVISION)
155
+ },
156
+
140
157
  openApiSpec: (ctx) => {
141
158
  return ctx.call("system.generateDocs")
142
159
  },
@@ -180,17 +197,17 @@ export default {
180
197
  * swagger-stats initialized with OpenAPI spec once the Gateway service started.
181
198
  */
182
199
  async started() {
183
-
184
- /**
185
- * Generate spec after service starts
186
- */
187
- const spec = await this.actions.generateDocs()
188
200
 
189
- /*Patch swagger-stats middleware with spec*/
190
- const swStats = this.settings.use.find(mw => mw.name === "swagger-stats")
191
- if (swStats && spec) {
192
- swStats.swaggerSpec = spec
193
- }
201
+ // /**
202
+ // * Generate spec after service starts
203
+ // */
204
+ // const spec = await this.actions.generateDocs()
205
+
206
+ // /*Patch swagger-stats middleware with spec*/
207
+ // const swStats = this.settings.use.find(mw => mw.name === "swagger-stats")
208
+ // if (swStats && spec) {
209
+ // swStats.swaggerSpec = spec
210
+ // }
194
211
 
195
212
  /**
196
213
  * add endpoints
@@ -237,7 +254,63 @@ export default {
237
254
  * Redirect to redpanda web client
238
255
  */
239
256
  "GET /redpanda": "system.redpandaUi",
257
+
258
+ /**
259
+ *
260
+ */
261
+ "GET /config/revision/brodcast/immediate": "system.broadcastConfigRevision",
240
262
  }
241
263
  })
264
+
265
+
266
+ this.interval = setInterval(async () => {
267
+ const CONFIG_REVISION = errHdl.validateConfRevision(await configHld.getConfigs(`/config/sbk/global/envs/REVISION`))
268
+ this.broker.logger.debug(CONFIG_REVISION, {message: `Brodcast Config revisions ${Date.now()}`})
269
+ this.broker.broadcast("config.revisions", CONFIG_REVISION)
270
+ }, LC_BROADCAST_INTERVAL)
271
+
272
+
273
+
274
+ configHld.watchConfigs('/config/sbk/', async (ev, key, val) => {
275
+ if( key == "/config/sbk/global/envs/REVISION" ){
276
+ return false
277
+ }
278
+
279
+ const CONFIG_REVISION = errHdl.validateConfRevision(await configHld.getConfigs(`/config/sbk/global/envs/REVISION`))
280
+
281
+ if( /^\/config\/sbk\/members\/[^/]+$/.test(key) && /^false$/i.test(val) ){
282
+ const serviceName = key.replace("/config/sbk/members/","")
283
+ CONFIG_REVISION.mem[serviceName] = -1
284
+ this.broker.broadcast("config.revisions", CONFIG_REVISION)
285
+ }
286
+
287
+ if( /^\/config\/sbk\/members\/[^/]+$/.test(key) && /^true$/i.test(val) ){
288
+ const serviceName = key.replace("/config/sbk/members/","")
289
+ CONFIG_REVISION.mem[serviceName] = 0
290
+ }
291
+
292
+ if( /^\/config\/sbk\/members\/[^/]+\/.+$/.test(key) ){
293
+ const memRegex = /^\/config\/sbk\/members\/([^/]+)\/.+$/
294
+ const serviceName = (key.match(memRegex))[1]
295
+
296
+ CONFIG_REVISION.mem[serviceName] = CONFIG_REVISION.mem[serviceName] == undefined
297
+ ? 0
298
+ : CONFIG_REVISION.mem[serviceName] >= 0
299
+ ? CONFIG_REVISION.mem[serviceName] + 1
300
+ : CONFIG_REVISION.mem[serviceName]
301
+ }
302
+
303
+ if( key.startsWith("/config/sbk/global/") ){
304
+ CONFIG_REVISION.pub++
305
+ }
306
+
307
+ if( key.startsWith("/config/sbk/edge/") ){
308
+ CONFIG_REVISION.edg++
309
+ }
310
+
311
+ await configHld.putConfig("/config/sbk/global/envs/REVISION", JSON.stringify(CONFIG_REVISION))
312
+ this.broker.logger.debug( {message: "Config revised"}, CONFIG_REVISION )
313
+ })
314
+
242
315
  },
243
316
  }
@@ -1,4 +1,3 @@
1
- import { getConfig } from '#hFil/esm-loading.mjs'
2
1
  const CONFIG = {openApiInfo:[{url:"dev.sbk.wbsedcl.in:9876"}]}
3
2
 
4
3
  export default `