geonix 1.8.10 → 1.8.20

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": "geonix",
3
- "version": "1.8.10",
3
+ "version": "1.8.20",
4
4
  "type": "module",
5
5
  "description": "",
6
6
  "bin": {
@@ -16,13 +16,13 @@
16
16
  "license": "ISC",
17
17
  "dependencies": {
18
18
  "cookie-parser": "^1.4.6",
19
- "express": "^4.18.1",
19
+ "express": "^4.18.2",
20
20
  "express-async-errors": "^3.1.1",
21
21
  "express-ws": "^5.0.2",
22
22
  "multer": "^1.4.5-lts.1",
23
- "nats": "^2.15.1",
24
- "semver": "^7.3.7",
25
- "ws": "^8.8.1"
23
+ "nats": "^2.16.0",
24
+ "semver": "^7.5.4",
25
+ "ws": "^8.13.0"
26
26
  },
27
27
  "publishConfig": {
28
28
  "registry": "https://registry.npmjs.org/"
package/src/Connection.js CHANGED
@@ -55,6 +55,9 @@ class Connection {
55
55
  console.log('gx.connection.status', JSON.stringify(event))
56
56
  }
57
57
 
58
+ /**
59
+ * Wait for the connection to be safely closed
60
+ */
58
61
  async waitUntilClosed() {
59
62
  await this.#nc.closed()
60
63
  this.#closed = true
@@ -68,11 +71,21 @@ class Connection {
68
71
  process.exit(1)
69
72
  }
70
73
 
74
+ /**
75
+ * Wait for the connection to be fully established
76
+ */
71
77
  async waitUntilReady() {
72
78
  while (!this.#ready)
73
79
  await sleep(100)
74
80
  }
75
81
 
82
+ /**
83
+ * Publish JSON
84
+ *
85
+ * @param {string} subject
86
+ * @param {object} json
87
+ * @returns void
88
+ */
76
89
  async publish(subject, json) {
77
90
  if (this.#draining || this.#closed)
78
91
  return
@@ -86,6 +99,13 @@ class Connection {
86
99
  await this.#nc.publish(subject, payload)
87
100
  }
88
101
 
102
+ /**
103
+ * Publish RAW
104
+ *
105
+ * @param {string} subject
106
+ * @param {string | Buffer} data
107
+ * @returns void
108
+ */
89
109
  async publishRaw(subject, data) {
90
110
  if (this.#draining || this.#closed)
91
111
  return
@@ -93,8 +113,16 @@ class Connection {
93
113
  await this.#nc.publish(subject, data)
94
114
  }
95
115
 
116
+ /**
117
+ * Request/Reply pattern on top of pub/sub
118
+ *
119
+ * @param {string} subject
120
+ * @param {object} json
121
+ * @param {object} options
122
+ * @returns any
123
+ */
96
124
  async request(subject, json, options = { timeout: 300000 }) {
97
- const respondTo = `_INBOX.${picoid(32)}`
125
+ const respondTo = `gx2.r.${picoid(16)}`
98
126
 
99
127
  let payload = codec.encode({ $r: respondTo, p: json })
100
128
 
@@ -102,10 +130,10 @@ class Connection {
102
130
  if (payload.length > this.getMaxPayloadSize())
103
131
  payload = codec.encode(Stream(JSON.stringify({ $r: respondTo, p: json })))
104
132
 
105
- await this.#nc.publish(subject, payload)
106
-
107
133
  let response = await this.#nc.subscribe(respondTo, { max: 1, ...options })
108
134
 
135
+ await this.#nc.publish(subject, payload)
136
+
109
137
  for await (let event of response)
110
138
  return codec.decode(event.data)
111
139
  }
package/src/Request.js CHANGED
@@ -4,6 +4,7 @@ import { Service } from './Service.js'
4
4
  import { hash, sleep } from './Util.js'
5
5
  import { RequestOptionsClass } from './RequestOptions.js'
6
6
  import { isStream, streamToString } from './Stream.js'
7
+ import { inspect } from 'node:util'
7
8
 
8
9
  const REGISTRY_TIMEOUT = 300000
9
10
 
@@ -91,7 +92,7 @@ export async function Request(service, method, args = [], context = [], options)
91
92
  },
92
93
  options)
93
94
  } catch (e) {
94
- console.debug('GxError: Request', JSON.stringify({
95
+ console.debug('GxError: Request', inspect({
95
96
  originator, service, method, args, context, options,
96
97
  error: e, duration: Date.now() - requestBegin
97
98
  }))
package/test/.env ADDED
@@ -0,0 +1 @@
1
+ TRANSPORT=nats://phobos.tria.hr:4222
@@ -0,0 +1,60 @@
1
+ import { Service, Remote } from 'geonix'
2
+
3
+ const calc = Remote('Calculator')
4
+ const tp = Remote('TimeProvider')
5
+
6
+ class Logger {
7
+
8
+ constructor(prefix) {
9
+ this.prefix = prefix
10
+ }
11
+
12
+ log(...args) {
13
+ console.log(`${new Date().toISOString()}|${this.prefix}|`, ...args)
14
+ }
15
+ }
16
+
17
+ class BaseService extends Service {
18
+
19
+ logger = new Logger(this.constructor.name)
20
+
21
+ }
22
+
23
+
24
+ class CalculatorRepository {
25
+
26
+ constructor(service) {
27
+ this.logger = service.logger
28
+ }
29
+
30
+ async getCurrentTime() {
31
+ this.logger.log('getCurrentTime')
32
+ return await Remote('TimeProvider').now()
33
+ }
34
+
35
+ }
36
+
37
+ class Calculator extends BaseService {
38
+
39
+ repo = new CalculatorRepository(this)
40
+
41
+ async onStart() {
42
+ this.logger.log('current time =', await this.repo.getCurrentTime())
43
+ }
44
+
45
+ thisHere() {
46
+
47
+ }
48
+
49
+ }
50
+
51
+ class TimeProvider extends BaseService {
52
+
53
+ now() {
54
+ return new Date().toISOString()
55
+ }
56
+
57
+ }
58
+
59
+ Calculator.start()
60
+ TimeProvider.start()
package/test/package.json CHANGED
@@ -11,6 +11,8 @@
11
11
  "author": "",
12
12
  "license": "ISC",
13
13
  "dependencies": {
14
- "geonix": "file:.."
14
+ "dotenv": "^16.3.1",
15
+ "geonix": "file:..",
16
+ "nats": "^2.16.0"
15
17
  }
16
18
  }
@@ -0,0 +1,31 @@
1
+ export const OverlayObject = (object, overlay) => {
2
+ return new Proxy(object, {
3
+ get: (t, p) => overlay[p] !== undefined ? overlay[p] : t[p]
4
+ }
5
+ )
6
+ }
7
+
8
+ class Test {
9
+
10
+ #me = { works: true }
11
+
12
+ get me() { return this.#me }
13
+
14
+ external() {
15
+ return this.me
16
+ }
17
+
18
+ call(method) {
19
+ try {
20
+ const methodContext = { context: 'this is context value' }
21
+ const $context = OverlayObject(this, methodContext)
22
+ return instance[method].apply($context)
23
+ } catch (e) {
24
+ }
25
+ }
26
+
27
+ }
28
+
29
+ const instance = new Test()
30
+
31
+ console.log(instance.call('external'))
@@ -0,0 +1,29 @@
1
+ import { Service, Remote, registry } from '../exports.js'
2
+ import { sleep } from '../src/Util.js'
3
+
4
+ class First extends Service {
5
+
6
+ getTime() {
7
+ return new Date().toISOString()
8
+ }
9
+
10
+ }
11
+
12
+ class Second extends Service {
13
+
14
+ first = Remote('First')
15
+
16
+ async onStart() {
17
+ while (true) {
18
+ console.clear()
19
+ console.log('Time =', await this.first.getTime())
20
+ console.log('REGISTRY =', registry.getEntries())
21
+
22
+ await sleep(1000)
23
+ }
24
+ }
25
+
26
+ }
27
+
28
+ First.start({ port: 30001 })
29
+ Second.start({ port: 30002 })
package/test/stream.js CHANGED
@@ -8,7 +8,7 @@ await connection.waitUntilReady()
8
8
 
9
9
  const hash = data => createHash('sha512').update(data).digest('base64')
10
10
 
11
- const PAYLOAD_SIZE = 1024 * 1024 * 1024
11
+ const PAYLOAD_SIZE = 1024 * 1024 * 10
12
12
  const TEMP_FILE = '/tmp/geonix.stream_test'
13
13
 
14
14
  console.time('test')
@@ -0,0 +1,42 @@
1
+ import 'dotenv/config'
2
+ import { randomBytes } from 'node:crypto'
3
+ import { Stream, Remote, getReadable, connection, Service, streamToBuffer } from 'geonix'
4
+ import { createWriteStream, readFileSync } from 'node:fs'
5
+ import { createHash } from 'node:crypto'
6
+ import { pipeline } from 'node:stream/promises'
7
+
8
+ const hash = data => createHash('sha256').update(data).digest('base64')
9
+ const self = Remote('StreamTest')
10
+
11
+ class StreamTest extends Service {
12
+
13
+ async onStart() {
14
+ const perform = async (n) => {
15
+ const fileName = `${n}.random`
16
+ const { checksum, stream } = await self.readFile(fileName)
17
+ const data = await streamToBuffer(stream)
18
+ const verification = hash(data)
19
+
20
+ console.log(`${fileName} - ${data.length} bytes - ${checksum === verification}`)
21
+ }
22
+
23
+ const jobs = []
24
+ for (let n = 0; n < 1024; n++)
25
+ jobs.push(perform(n))
26
+
27
+ await Promise.all(jobs)
28
+
29
+ console.log('done')
30
+ }
31
+
32
+ async readFile(fileName, size = 1024 * Math.round(Math.random() * 1024)) {
33
+ const bytes = randomBytes(size)
34
+ const checksum = hash(bytes)
35
+
36
+ return { checksum, stream: Stream(bytes) }
37
+ }
38
+
39
+
40
+ }
41
+
42
+ StreamTest.start()
@@ -1,33 +0,0 @@
1
- export function serialize(input) {
2
- const process = (value) => {
3
- if (value instanceof Buffer) {
4
- console.log('this is buffer')
5
- }
6
-
7
- if (typeof value === 'object')
8
- for (let prop in value)
9
- serialize()
10
-
11
- return value
12
- }
13
-
14
- let state = input
15
-
16
- process(state)
17
-
18
- return JSON.stringify(state)
19
- }
20
-
21
- export function deserialize(input) {
22
-
23
- }
24
-
25
- const input = {
26
-
27
- }
28
-
29
- const s = serialize(input)
30
- const ds = deserialize(s)
31
-
32
- console.log(' serialized =', s)
33
- console.log('deserialized =', ds)