Skip to content

Commit 6d5075a

Browse files
committed
fix serverless adapter, refactor wasm interop
1 parent 20fa2ff commit 6d5075a

File tree

6 files changed

+83
-52
lines changed

6 files changed

+83
-52
lines changed

src/adapters/serverless/index.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { makeServerlessAdapter } from './serverless-adapter'
22
import * as localParsers from './parsers'
33

4-
const getRemoteParsers = async () => import('aegis-services/parsers')``
4+
//const getRemoteParsers = async () => import('aegis-services/parsers')``
55
export const getParsers = async function () {
66
try {
7-
const remoteParsers = await getRemoteParsers()
8-
if (!remoteParsers) return localParsers
9-
return { ...localParsers, ...remoteParsers }
7+
// const remoteParsers = await getRemoteParsers()
8+
// if (!remoteParsers) return localParsers
9+
// return { ...localParsers, ...remoteParsers }
10+
return localParsers
1011
} catch (e) {
1112
console.error('serverless.parsers', e.message)
1213
}

src/adapters/serverless/parsers/aws-parser.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export const aws = {
4242
query: args.queryStringParameters,
4343
params: args.pathParameters,
4444
body: handleMultiline(args.body),
45+
headers: args.headers,
4546
all: { ...args }
4647
},
4748
res

src/adapters/webassembly/wasm-interop.js

Lines changed: 65 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,6 @@ exports.WasmInterop = function (wasmExports) {
2929
_exports
3030
} = wasmExports
3131

32-
function parse (v) {
33-
return !isNaN(parseInt(v))
34-
? parseInt(v)
35-
: !isNaN(parseFloat(v))
36-
? parseFloat(v)
37-
: /true/i.test(v)
38-
? true
39-
: /false/i.test(v)
40-
? false
41-
: v
42-
}
43-
4432
/**
4533
*
4634
* @param {string} fn function name
@@ -58,8 +46,6 @@ exports.WasmInterop = function (wasmExports) {
5846
2,
5947
_exports[fn](kv) >>> 0
6048
)
61-
.map(([k, v]) => ({ [k]: parse(v) }))
62-
.reduce((a, b) => ({ ...a, ...b }))
6349
}
6450

6551
/**
@@ -90,39 +76,81 @@ exports.WasmInterop = function (wasmExports) {
9076
)
9177
}
9278

93-
function clean (obj) {
94-
const convert = obj =>
95-
Object.entries(obj)
96-
.filter(([k, v]) => ['string', 'number', 'boolean'].includes(typeof v))
97-
.map(([k, v]) => [k, v.toString()])
79+
/**
80+
*
81+
* @param {string} v - value
82+
* @returns {string|number|boolean}
83+
*/
84+
function parseString (v) {
85+
return !isNaN(parseFloat(v))
86+
? parseFloat(v)
87+
: /^true$/i.test(v)
88+
? true
89+
: /^false$/i.test(v)
90+
? false
91+
: v
92+
}
93+
94+
/**
95+
*
96+
* @param {object} o
97+
* @returns {string[][]}
98+
*/
99+
function parseObject (o) {
100+
return Object.entries(o)
101+
.filter(([k, v]) => ['string', 'number', 'boolean'].includes(typeof v))
102+
.map(([k, v]) => [k, v.toString()])
103+
}
98104

105+
/**
106+
*
107+
* @param {object} obj
108+
* @returns {string[][]}
109+
*/
110+
function toKeyValueArray (obj) {
99111
// handle custom port format
100-
if (obj.port && obj.args) return convert(obj.args)
101-
return convert(obj)
112+
if (obj.port && obj.args) return parseObject(obj.args)
113+
return parseObject(obj)
102114
}
103115

104116
/**
105-
* Parse the input object into a multidimensional array of key-value pairs
106-
* and pass it as an argument to the exported wasm function. Do the reverse for
107-
* the response. Consequently, any wasm port or command function must accept a
108-
* multidemensional array of strings (numbers are converted to strings) and return
109-
* a multidimensional array of strings. Before they can be called, they must be
110-
* registered in a modelspec, i.e. getPorts() and getCommands() must return
111-
* appropria metadata.
117+
*
118+
* @param {string[][]} kv
119+
* @returns {object}
120+
*/
121+
function fromKeyValueArray (kv) {
122+
return kv
123+
.map(([k, v]) => ({ [k]: parseString(v) }))
124+
.reduce((a, b) => ({ ...a, ...b }))
125+
}
112126

113-
* @param {string} fn exported wasm function name
114-
* @param {object|number} [obj] object, see above
115-
* @returns {object|number} object
127+
/**
128+
* Parse the input object into a multidimensional array of key-value string pairs
129+
* and pass it as an argument to the exported wasm function. Do the reverse for
130+
* the return value. The interface requires that any wasm port or command function
131+
* accept a multidemensional array of strings (numbers and booleans are converted
132+
* to strings) and return a multidimensional array of strings. These functions must
133+
* be defined in the ModelSpec, i.e. `getPorts()` and `getCommands()` list the names
134+
* of functions to be exported from the wasm module that implement the interface,
135+
* ```js
136+
* (string[][]) => string[][]
137+
* ```
138+
* or
139+
* ```js
140+
* () => string[][]
141+
*```
142+
* @param {string} fn name of exported function
143+
* @param {object} [obj] object; see above
144+
* @returns {object} object
116145
*/
117146
function callWasmFunction (fn, obj) {
118-
return lift(fn, lower(clean(obj)))
147+
return fromKeyValueArray(lift(fn, lower(toKeyValueArray(obj))))
119148
}
120149

121150
return Object.freeze({
122151
/**
123152
* For every command in {@link getCommands} create a
124-
* an entry that will invoke one or more of the exported
125-
* wasm functions.
153+
* an entry that will invoke the exported wasm function.
126154
*/
127155
importWasmCommands () {
128156
const commandNames = getCommands()
@@ -144,10 +172,9 @@ exports.WasmInterop = function (wasmExports) {
144172
},
145173

146174
/**
147-
* For every port in {@link getPorts} create a
148-
* an entry that in the {@link ModelSpecification.ports}
149-
* that will invoke one or more of the exported
150-
* wasm functions.
175+
* For every `port` in {@link getPorts} create a
176+
* an entry in {@link ModelSpecification.ports}
177+
* that will invoke the exported wasm function.
151178
*/
152179
importWasmPorts () {
153180
const ports = getPorts()

src/aegis.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,9 @@ async function handle (path, method, req, res) {
215215
return result
216216
} catch (error) {
217217
console.error({ fn: handle.name, error })
218-
res.status(500).send(error.message)
218+
if (!res.headersSent) res.status(500).send(error.message)
219219
} finally {
220-
const msg = `exit context ${requestContext.getStore().get('id')}`
220+
const msg = `exit context ${requestContext.getStore()?.get('id')}`
221221
requestContext.exit(() => console.log(msg))
222222
}
223223
}

src/domain/index.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,11 @@
212212
* "./models": "./src/domain",
213213
* "./adapters": "./src/adapters",
214214
* "./services": "./src/services",
215-
* },
216-
* }),
215+
* "./ports": "./src/domain/ports"
216+
* }
217+
* })
217218
* ```
219+
*
218220
* @property {string} [repo] if using github, name of the github repo
219221
* @property {string} [owner] if using gitbub, owner of the repo
220222
* @property {string} [filedir] if using gitub, path to the remoteEntry.js file
@@ -223,7 +225,7 @@
223225
* @property {string} [serviceName] optional name of the service to which the module belongs
224226
* - use to group model, adapaters and services together
225227
* at startup instead of waiting until a request for the model has been received
226-
* model, adapter or service
228+
* modor serviceel, adapter
227229
* @property {string} [worker] Creates a model that is controlled by a custom worker
228230
* instead of the system default worker. Developers can do whatever they want with the worker
229231
* and needn't use the associated model at all. That said, developers may want to make use of

src/services/cluster.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,11 @@ function stopWorker () {
7575
* @param {number} waitms - Delay execution by `waitms`
7676
* milliseconds so your app has time to start
7777
*/
78-
function continueReload (callback, waitms) {
78+
function handleReload (callback, waitms = 2000) {
7979
const failedWorker =
8080
!reloading &&
8181
workerList.length < numCores &&
82-
callback.name.includes('start')
82+
callback.name === startWorker.name
8383

8484
if (reloading || failedWorker) {
8585
setTimeout(callback, failedWorker ? 60000 : waitms)
@@ -109,16 +109,16 @@ exports.startCluster = function (startService, waitms = 2000) {
109109
// Worker stopped. If reloading, start a new one.
110110
cluster.on('exit', function (worker) {
111111
console.log('worker down', worker.process.pid)
112-
continueReload(startWorker, 0)
112+
handleReload(startWorker, 0)
113113
})
114114

115115
// Worker started. If reloading, stop the next one.
116116
cluster.on('online', function (worker) {
117117
console.log('worker up', worker.process.pid)
118-
continueReload(stopWorker, waitms)
118+
handleReload(stopWorker, waitms)
119119
})
120120

121-
setInterval(continueReload, 60000, startWorker, waitms)
121+
setInterval(() => handleReload(startWorker, 0), 60000)
122122

123123
console.log(`master starting ${numCores} workers 🌎`)
124124
// Run a copy of this program on each core

0 commit comments

Comments
 (0)