@naanlang/naan 1.0.16 → 1.2.0
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/LICENSE.md +2 -2
- package/README.md +13 -11
- package/bin/index.js +4 -4
- package/dist/naan.min.js +14 -14
- package/frameworks/browser/https_request.nlg +26 -10
- package/frameworks/browser/sworker.js +26 -25
- package/frameworks/browser/terminals.nlg +118 -55
- package/frameworks/browser/ws_client.nlg +124 -0
- package/frameworks/client/apiclient.nlg +82 -116
- package/frameworks/client/psm_client.nlg +37 -16
- package/frameworks/client/relaycon.nlg +308 -0
- package/frameworks/common/common.nlg +1 -1
- package/frameworks/common/utils.nlg +40 -2
- package/frameworks/node/apiserver.nlg +342 -103
- package/frameworks/node/https_request.nlg +32 -6
- package/frameworks/node/node.nlg +60 -2
- package/frameworks/node/psm_server.nlg +11 -7
- package/frameworks/node/worker.nlg +22 -9
- package/frameworks/node/ws_client.nlg +127 -0
- package/frameworks/project/build.nlg +3 -2
- package/frameworks/project/projects.nlg +8 -2
- package/frameworks/running/debugnub.nlg +2 -2
- package/frameworks/running/debugutil.nlg +1 -1
- package/frameworks/running/executors.nlg +69 -17
- package/frameworks/running/sourcecode.nlg +2 -2
- package/frameworks/running/taskexec.nlg +25 -25
- package/frameworks/storage/dbt_pouch.nlg +8 -6
- package/frameworks/storage/file_manager.nlg +6 -3
- package/frameworks/storage/psm.nlg +5 -3
- package/frameworks/storage/psm_dbtables.nlg +75 -53
- package/frameworks/storage/resources.nlg +4 -2
- package/lib/browser/env_web.js +6 -6
- package/lib/browser/env_webworker.js +1 -1
- package/lib/core/naanlib.js +14 -14
- package/lib/env_node.js +97 -8
- package/lib/env_nodeworker.js +22 -4
- package/package.json +1 -1
- package/plugins/serviceAws/aws/lambda_rest_index.js +5 -1
- package/plugins/serviceAws/aws_dynamo.nlg +91 -32
- package/plugins/serviceAws/dbt_aws.nlg +5 -5
- package/plugins/serviceAws/psm_aws.nlg +2 -2
- package/test/harness.nlg +1 -1
- package/test/test_01_core.nlg +30 -4
- package/test/test_02_context.nlg +2 -2
- package/test/test_07_lingo.nlg +3 -0
package/frameworks/node/node.nlg
CHANGED
|
@@ -6,11 +6,66 @@
|
|
|
6
6
|
*
|
|
7
7
|
* column positioning: // // !
|
|
8
8
|
*
|
|
9
|
-
* Copyright (c) 2020-
|
|
9
|
+
* Copyright (c) 2020-2024 by Richard C. Zulch
|
|
10
10
|
*
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
|
|
14
|
+
/*
|
|
15
|
+
* NaanlangDir
|
|
16
|
+
*
|
|
17
|
+
* Ensure the naanlang directory exists, returning a result tuple.
|
|
18
|
+
*
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
closure NaanlangDir(local path, errmkdir, errstat, stat) {
|
|
22
|
+
global(JSpath, os, App, fs)
|
|
23
|
+
path = JSpath.join(os.homedir(), ".naanlang/")
|
|
24
|
+
`(errmkdir) = await(fs.promises.mkdir(path))
|
|
25
|
+
if errmkdir.code == "EEXIST" {
|
|
26
|
+
`(errstat, stat) = await(fs.promises.stat(path))
|
|
27
|
+
if errstat || !stat.isDirectory()
|
|
28
|
+
return (list(Error("mkdir conflict:", errmkdir))) // file in the way
|
|
29
|
+
}
|
|
30
|
+
else if errmkdir
|
|
31
|
+
return (list(Error("mkdir failed:", errmkdir)))
|
|
32
|
+
await(fs.promises.mkdir(JSpath.join(path, "nidecom"))) // ignore errors here
|
|
33
|
+
App.config = merge({
|
|
34
|
+
prefsdir: path
|
|
35
|
+
})
|
|
36
|
+
list(false, path)
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
/*
|
|
41
|
+
* NaanlangRC
|
|
42
|
+
*
|
|
43
|
+
* Return the naanlang RC file if found, or an empty dictionary otherwise.
|
|
44
|
+
*
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
closure NaanlangRC(local path, error, config) {
|
|
48
|
+
global(JSpath, fs, App)
|
|
49
|
+
`(error, path) = NaanlangDir()
|
|
50
|
+
if path {
|
|
51
|
+
path = JSpath.join(path, "naanlangrc")
|
|
52
|
+
`(error, config) = await(fs.promises.readFile(path, {
|
|
53
|
+
encoding: "utf8"
|
|
54
|
+
}))
|
|
55
|
+
if !error
|
|
56
|
+
`(error, config) = JsonParse(config)
|
|
57
|
+
}
|
|
58
|
+
if config
|
|
59
|
+
App.config = merge({
|
|
60
|
+
rcpath: path
|
|
61
|
+
config: config
|
|
62
|
+
})
|
|
63
|
+
else
|
|
64
|
+
config = { }
|
|
65
|
+
config
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
|
|
14
69
|
/*
|
|
15
70
|
* NodeStreamLiner
|
|
16
71
|
*
|
|
@@ -63,7 +118,7 @@ closure NodeStreamLiner(endings, local liner) {
|
|
|
63
118
|
*/
|
|
64
119
|
|
|
65
120
|
function nodrInit(local manifest) {
|
|
66
|
-
manifest = `(NodeStreamLiner, nodrInit)
|
|
121
|
+
manifest = `(NaanlangDir, NaanlangRC, NodeStreamLiner, nodrInit)
|
|
67
122
|
|
|
68
123
|
if !js.g
|
|
69
124
|
throw("module frameworks/node cannot be used from a browser")
|
|
@@ -77,7 +132,10 @@ function nodrInit(local manifest) {
|
|
|
77
132
|
stream = js.r("stream")
|
|
78
133
|
nodeHttps = js.r("https")
|
|
79
134
|
nodeUrl= js.r("url")
|
|
135
|
+
threads = js.r("worker_threads")
|
|
80
136
|
}()
|
|
81
137
|
module.reload = nodrReload
|
|
138
|
+
module.exports.NaanlangDir = NaanlangDir
|
|
139
|
+
module.exports.NaanlangRC = NaanlangRC
|
|
82
140
|
})
|
|
83
141
|
} ();
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* column positioning: // // !
|
|
8
8
|
*
|
|
9
|
-
* Copyright (c) 2019-
|
|
9
|
+
* Copyright (c) 2019-2023 by Richard C. Zulch
|
|
10
10
|
*
|
|
11
11
|
*/
|
|
12
12
|
|
|
@@ -450,8 +450,8 @@ closure psmsFsConnector(psm, api, local connClassID, connector, watch) {
|
|
|
450
450
|
connector.info = function info(resID, local info, error, creds) {
|
|
451
451
|
info = {
|
|
452
452
|
classID: connClassID
|
|
453
|
-
type: "remote
|
|
454
|
-
services: ["NideFS", "NideHostAPI"]
|
|
453
|
+
type: "remote server"
|
|
454
|
+
services: ["NideFS", "NideHostAPI", "NideTerminal"]
|
|
455
455
|
}
|
|
456
456
|
if resID == "Host" {
|
|
457
457
|
info.name = "Host"
|
|
@@ -517,13 +517,17 @@ closure psmsFsConnector(psm, api, local connClassID, connector, watch) {
|
|
|
517
517
|
*
|
|
518
518
|
*/
|
|
519
519
|
|
|
520
|
-
function MakeServerPSM(api, local importPSM) {
|
|
520
|
+
function MakeServerPSM(api, name, local importPSM, error, path, psm) {
|
|
521
521
|
importPSM = require("../storage/psm.nlg")
|
|
522
|
-
|
|
523
|
-
if
|
|
522
|
+
`(error, path) = NaanlangDir() // put database in ~/.naanlang/
|
|
523
|
+
if !error
|
|
524
|
+
`(error, psm) = importPSM.MakePSM(JSpath.join(path, "${name}DB_${api.port.tostring}"))
|
|
525
|
+
if !error {
|
|
526
|
+
App.psm = psm
|
|
524
527
|
psmsFsConnector(App.psm, api)
|
|
525
528
|
require("frameworks/storage/dbt_pouch.nlg").DbConnector(App.psm) // Pouch databases as filesystems
|
|
526
|
-
}
|
|
529
|
+
} else
|
|
530
|
+
ErrorDebuglog("Cannot create PSM", error)
|
|
527
531
|
App.psm
|
|
528
532
|
};
|
|
529
533
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* column positioning: // // !
|
|
8
8
|
*
|
|
9
|
-
* Copyright (c) 2019-
|
|
9
|
+
* Copyright (c) 2019-2024 by Richard C. Zulch
|
|
10
10
|
*
|
|
11
11
|
*/
|
|
12
12
|
|
|
@@ -18,9 +18,11 @@
|
|
|
18
18
|
*
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
closure workCurrent(workerID, local current) {
|
|
21
|
+
closure workCurrent(workerID, startup, local current) {
|
|
22
|
+
global()
|
|
22
23
|
current = new(object, this)
|
|
23
24
|
current.workerID = workerID
|
|
25
|
+
current.name = startup.name
|
|
24
26
|
current.links = []
|
|
25
27
|
current.termif = xnew({
|
|
26
28
|
textout: ONtextOut.proc
|
|
@@ -177,14 +179,17 @@ closure workCurrent(workerID, local current) {
|
|
|
177
179
|
*
|
|
178
180
|
*/
|
|
179
181
|
|
|
180
|
-
closure workThread(workerID, startup, local worker, subChannel, deathWatcher) {
|
|
182
|
+
closure workThread(workerID, startup, local worker, options, subChannel, deathWatcher) {
|
|
183
|
+
global(threads, JSpath)
|
|
181
184
|
worker = new(object, this)
|
|
185
|
+
worker.name = startup.name
|
|
182
186
|
worker.workerID = workerID
|
|
183
187
|
worker.links = []
|
|
184
188
|
|
|
185
189
|
// create our worker thread
|
|
186
190
|
|
|
187
|
-
|
|
191
|
+
// options = { execArgv: ["--inspect-brk"] } // uncomment for NodeJS debugging
|
|
192
|
+
worker.thread = xnew(threads.Worker, JSpath.resolve(js.d, "node_worker.js"), options)
|
|
188
193
|
subChannel = xnew(threads.MessageChannel)
|
|
189
194
|
worker.thread.postMessage({ hereIsYourPort: subChannel.port1 }, [subChannel.port1])
|
|
190
195
|
worker.msgport = subChannel.port2
|
|
@@ -224,7 +229,7 @@ closure workThread(workerID, startup, local worker, subChannel, deathWatcher) {
|
|
|
224
229
|
|
|
225
230
|
worker.thread.on("error", function onerror(error) {
|
|
226
231
|
debuglog("worker terminated with error", workerID, error)
|
|
227
|
-
exitNotify(
|
|
232
|
+
exitNotify(-1)
|
|
228
233
|
})
|
|
229
234
|
|
|
230
235
|
//
|
|
@@ -341,6 +346,7 @@ closure workThread(workerID, startup, local worker, subChannel, deathWatcher) {
|
|
|
341
346
|
*/
|
|
342
347
|
|
|
343
348
|
closure workLink(workco, conn, worker, sender, local link) {
|
|
349
|
+
global()
|
|
344
350
|
link = new(object, this)
|
|
345
351
|
|
|
346
352
|
//
|
|
@@ -393,6 +399,7 @@ closure workLink(workco, conn, worker, sender, local link) {
|
|
|
393
399
|
*/
|
|
394
400
|
|
|
395
401
|
closure workController(api, local workco) {
|
|
402
|
+
global()
|
|
396
403
|
workco = new(object, this)
|
|
397
404
|
workco.serverID = "Workers" // our serverID, used for communications
|
|
398
405
|
workco.workers = { } // dictionary of workers by workerID
|
|
@@ -480,7 +487,7 @@ closure workController(api, local workco) {
|
|
|
480
487
|
else if message.workerOp == "spawn" {
|
|
481
488
|
if !worker { // create worker if needed
|
|
482
489
|
if message.workerID == "NideServer"
|
|
483
|
-
worker = workco.current = workCurrent(message.workerID)
|
|
490
|
+
worker = workco.current = workCurrent(message.workerID, message.payload)
|
|
484
491
|
else
|
|
485
492
|
worker = workThread(message.workerID, message.payload)
|
|
486
493
|
workco.workers[message.workerID] = worker }
|
|
@@ -489,7 +496,14 @@ closure workController(api, local workco) {
|
|
|
489
496
|
if message.workerID == "NideServer"
|
|
490
497
|
workco.current.vitalUpdate({
|
|
491
498
|
id: "workerlist", // send the initial list of workers
|
|
492
|
-
|
|
499
|
+
workers: let(workers, workerID, worker) {
|
|
500
|
+
workers = { }
|
|
501
|
+
for `(workerID, worker) in workco.workers
|
|
502
|
+
workers[workerID] = {
|
|
503
|
+
name: worker.name
|
|
504
|
+
}
|
|
505
|
+
workers
|
|
506
|
+
}()
|
|
493
507
|
})
|
|
494
508
|
else {
|
|
495
509
|
worker.vitalWatch(termination)
|
|
@@ -516,7 +530,7 @@ closure workController(api, local workco) {
|
|
|
516
530
|
// Note that the connection with the client was closed.
|
|
517
531
|
//
|
|
518
532
|
|
|
519
|
-
workco.wsClose = function wsClose(conn, local workerID) {
|
|
533
|
+
workco.wsClose = function wsClose(conn, local workerID, link) {
|
|
520
534
|
for workerID in workco.workers {
|
|
521
535
|
link = workco.links[conn][workerID]
|
|
522
536
|
if link
|
|
@@ -553,7 +567,6 @@ function workInit(local manifest) {
|
|
|
553
567
|
|
|
554
568
|
Naan.module.build(module.id, "worker", function(modobj, compobj) {
|
|
555
569
|
require("./node.nlg")
|
|
556
|
-
threads = js.r("worker_threads") // ### should be on reload
|
|
557
570
|
compobj.manifest = manifest
|
|
558
571
|
modobj.exports.WorkerController = workController
|
|
559
572
|
})
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* ws_client.nlg
|
|
3
|
+
*
|
|
4
|
+
* WebSocket client operations for NodeJS.
|
|
5
|
+
*
|
|
6
|
+
* column positioning: // // !
|
|
7
|
+
*
|
|
8
|
+
* Copyright (c) 2023 by Richard C. Zulch
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* WebSocket
|
|
15
|
+
*
|
|
16
|
+
* Create a WebSocket client connection object using the existing HTTPS connection.
|
|
17
|
+
*
|
|
18
|
+
* Required:
|
|
19
|
+
* host: <string> // host:port
|
|
20
|
+
*
|
|
21
|
+
* Options:
|
|
22
|
+
* {
|
|
23
|
+
* onopen: <proc>(e) // connection has opened
|
|
24
|
+
* onmessage: <proc>(e, message) // message received
|
|
25
|
+
* onerror: <proc>(e) // error occurred
|
|
26
|
+
* onclose: <proc>(e) // connection has closed
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
closure WebSocket(host, options, local wsock) {
|
|
32
|
+
global(js)
|
|
33
|
+
wsock = new(object, this)
|
|
34
|
+
options = new(options) || { }
|
|
35
|
+
|
|
36
|
+
// connect
|
|
37
|
+
//
|
|
38
|
+
// Connect with the host if not already connected, returning a result tuple.
|
|
39
|
+
//
|
|
40
|
+
wsock.connect = closure connect(local pending, error, ws) {
|
|
41
|
+
if wsock.ws
|
|
42
|
+
return (list(false, { open: true }))
|
|
43
|
+
`(error, ws) = await(js.i("ws"))
|
|
44
|
+
if error
|
|
45
|
+
return (list(error))
|
|
46
|
+
wsock.ws = xnew(ws.default, "ws://${host}")
|
|
47
|
+
pending = new(nonce)
|
|
48
|
+
|
|
49
|
+
// onopen
|
|
50
|
+
// The WebSocket connection is now open.
|
|
51
|
+
wsock.ws.onopen = closure onopen(e) {
|
|
52
|
+
pending.signal(list(false, { ok: true }))
|
|
53
|
+
options.onopen(e, e.target, e.type)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// onmessage
|
|
57
|
+
// A message was received from the worker via WebSockets.
|
|
58
|
+
wsock.ws.onmessage = closure onmessage(e, local message) {
|
|
59
|
+
try {
|
|
60
|
+
message = new(JSONparse(e.data))
|
|
61
|
+
} catch {
|
|
62
|
+
debuglog("can't decode incoming ws message:", exception)
|
|
63
|
+
options.onerror(Error("can't decode incoming message:", exception))
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
options.onmessage(e, message)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// onerror
|
|
70
|
+
// An error occurred on the WebSocket connection.
|
|
71
|
+
wsock.ws.onerror = closure onerror(e, local error) {
|
|
72
|
+
error = Error("websocket failed", e)
|
|
73
|
+
options.onerror(e, error)
|
|
74
|
+
pending.signal(list(error)) // ensure connect completes
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// onclose
|
|
78
|
+
// The WebSocket connection was closed.
|
|
79
|
+
wsock.ws.onclose = closure onclose(e) {
|
|
80
|
+
options.onclose(e, e.code, e.reason)
|
|
81
|
+
pending.signal(list(Error("connection closed"))) // ensure connect completes
|
|
82
|
+
wsock.ws = false
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
pending.wait()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// send
|
|
89
|
+
//
|
|
90
|
+
// Send a message dictionary.
|
|
91
|
+
//
|
|
92
|
+
wsock.send = function send(message) {
|
|
93
|
+
wsock.ws.send(JSONstringify(message))
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// close
|
|
97
|
+
//
|
|
98
|
+
// Close the connection.
|
|
99
|
+
//
|
|
100
|
+
wsock.close = function close(reason) {
|
|
101
|
+
if !reason
|
|
102
|
+
reason = 1000 // normal close
|
|
103
|
+
wsock.ws.close(reason)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// finis
|
|
107
|
+
|
|
108
|
+
wsock
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
/*
|
|
113
|
+
* ws_clientInit
|
|
114
|
+
*
|
|
115
|
+
* Initialize WebSocket client operations for browsers.
|
|
116
|
+
*
|
|
117
|
+
*/
|
|
118
|
+
|
|
119
|
+
function ws_clientInit(local manifest) {
|
|
120
|
+
manifest = `(WebSocket, ws_clientInit)
|
|
121
|
+
|
|
122
|
+
Naan.module.build(module.id, "ws_client", function(modobj, compobj) {
|
|
123
|
+
require("node.nlg")
|
|
124
|
+
compobj.manifest = manifest
|
|
125
|
+
modobj.exports.WebSocket = WebSocket
|
|
126
|
+
})
|
|
127
|
+
}();
|
|
@@ -933,7 +933,7 @@ closure Builder(rules, operation, fs, srcpath, destpath, local build, group, new
|
|
|
933
933
|
xvrFileDefs = { }
|
|
934
934
|
xvrFileDefs.BuildNumber = buildno
|
|
935
935
|
`(error, verFileDefs) = readSubstitutionFile(build.verfilepath, xvrFileDefs)
|
|
936
|
-
build.version = verFileDefs["Version"]
|
|
936
|
+
build.version = verFileDefs["Version"].trim()
|
|
937
937
|
verFileDefs["CacheBuster"] = HashMD5(build.version.concat(Math.random()))
|
|
938
938
|
}
|
|
939
939
|
if build.tasks.catenate > 0 || build.tasks.zip > 0 {
|
|
@@ -1195,7 +1195,8 @@ closure Builder(rules, operation, fs, srcpath, destpath, local build, group, new
|
|
|
1195
1195
|
if error
|
|
1196
1196
|
error = Error("Builder: cannot read main file", error)
|
|
1197
1197
|
else {
|
|
1198
|
-
`(error, executor) = track.spawn(build.runway.spawn.0,
|
|
1198
|
+
`(error, executor) = track.spawn(build.runway.spawn.0, "${rules.name} ${build.version}", {
|
|
1199
|
+
workerID: "Run-${build.buildnum}"
|
|
1199
1200
|
startup: {
|
|
1200
1201
|
initcmds: maintext
|
|
1201
1202
|
dirpath: fs.path.resolve(fs.path.sep, fs.rootpath, build.destpath)
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* column positioning: // // !
|
|
8
8
|
*
|
|
9
|
-
* Copyright (c) 2016-
|
|
9
|
+
* Copyright (c) 2016-2024 by Richard C. Zulch
|
|
10
10
|
*
|
|
11
11
|
*/
|
|
12
12
|
|
|
@@ -296,7 +296,7 @@ closure projConnector(projman, projtype, local connector, watch) {
|
|
|
296
296
|
*
|
|
297
297
|
* Nide.proj/
|
|
298
298
|
* nide_cliser.cfg - JSON definition of the project (see below)
|
|
299
|
-
* NaanIDE_version.txt - [default] substitution file defining 1.0
|
|
299
|
+
* NaanIDE_version.txt - [default] substitution file defining 1.2.0+1 etc.
|
|
300
300
|
* NaanIDE_version_builds.txt - [default] contains current build number as decimal string
|
|
301
301
|
* build/ - [optional] default build output location
|
|
302
302
|
* NaanIDE.lic - [optional] defines Zulch Laboratories, Inc. and other license info
|
|
@@ -602,6 +602,8 @@ closure projConfig(projman, where, projID, local procon, fs, configpath) {
|
|
|
602
602
|
//
|
|
603
603
|
procon.run = closure run(stage, buildonly,
|
|
604
604
|
local error, rules, builder, buildpath, buildnum) {
|
|
605
|
+
if procon.builder
|
|
606
|
+
return (list(Error("build in progress")))
|
|
605
607
|
`(error, rules) = buildrules(stage)
|
|
606
608
|
if error
|
|
607
609
|
return (list(error))
|
|
@@ -615,6 +617,7 @@ closure projConfig(projman, where, projID, local procon, fs, configpath) {
|
|
|
615
617
|
`(error, builder) = Builder(rules, rules.operation, fs, "", buildpath)
|
|
616
618
|
if error
|
|
617
619
|
return (list(error))
|
|
620
|
+
procon.builder = builder
|
|
618
621
|
`(error, buildnum) = builder.increment()
|
|
619
622
|
if error {
|
|
620
623
|
ErrorDebuglog("build number increment failed", error)
|
|
@@ -631,6 +634,7 @@ closure projConfig(projman, where, projID, local procon, fs, configpath) {
|
|
|
631
634
|
`(error) = builder.run(projman.track)
|
|
632
635
|
}
|
|
633
636
|
builder.destroy()
|
|
637
|
+
procon.builder = false
|
|
634
638
|
if error
|
|
635
639
|
list(error)
|
|
636
640
|
else
|
|
@@ -650,6 +654,8 @@ closure projConfig(projman, where, projID, local procon, fs, configpath) {
|
|
|
650
654
|
//
|
|
651
655
|
procon.publish = closure publish(stage,
|
|
652
656
|
local error, rules, where, publish, outOptions, outfs, inpath) {
|
|
657
|
+
if procon.builder
|
|
658
|
+
return (list(Error("cannot publish while building")))
|
|
653
659
|
`(error, rules) = buildrules(stage)
|
|
654
660
|
if error
|
|
655
661
|
return (list(error))
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* column positioning: // // !
|
|
7
7
|
*
|
|
8
|
-
* Copyright (c) 2021 by Richard C. Zulch
|
|
8
|
+
* Copyright (c) 2021-2024 by Richard C. Zulch
|
|
9
9
|
*
|
|
10
10
|
*/
|
|
11
11
|
|
|
@@ -480,7 +480,7 @@ closure DebugNub(local nub, debug, paused) {
|
|
|
480
480
|
locals = localist(frame)
|
|
481
481
|
ns = frame.3.1.namespace
|
|
482
482
|
if ns !== nsactive().0 {
|
|
483
|
-
mod = module.owner.
|
|
483
|
+
mod = module.owner.find(function(mod){ mod.namespace === ns })
|
|
484
484
|
if mod {
|
|
485
485
|
gohome = makeActivator(nsactive())
|
|
486
486
|
chns(mod.id)
|
|
@@ -458,7 +458,7 @@ closure DebugRemote(commander, local remoter, here, there, library) {
|
|
|
458
458
|
// .undefined
|
|
459
459
|
// Execute methods remotely, returning a standard `(error, data) tuple.
|
|
460
460
|
|
|
461
|
-
remoter[".undefined"] = closure remoter args {
|
|
461
|
+
remoter@[".undefined"] = closure remoter args {
|
|
462
462
|
closure (selector, arglist, local error, context, result) {
|
|
463
463
|
if !there[selector] { // not over there yet
|
|
464
464
|
proc = here[selector]
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* column positioning: // // !
|
|
7
7
|
*
|
|
8
|
-
* Copyright (c) 2020-
|
|
8
|
+
* Copyright (c) 2020-2024 by Richard C. Zulch
|
|
9
9
|
*
|
|
10
10
|
*/
|
|
11
11
|
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
closure ExecutorBase(track, type, name, local exec) {
|
|
21
|
+
global()
|
|
21
22
|
exec = new(object, this)
|
|
22
23
|
exec.type = type
|
|
23
24
|
exec.name = name
|
|
@@ -36,7 +37,7 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
36
37
|
// Send a message to the running instance and return a nonce to wait on. If data is not a
|
|
37
38
|
// dictionary then it is ignored.
|
|
38
39
|
|
|
39
|
-
exec.execSend = closure execSend(msg, data, local pending) {
|
|
40
|
+
exec.execSend = closure execSend(msg, data, local pending, error) {
|
|
40
41
|
if !dictionary(data)
|
|
41
42
|
data = { }
|
|
42
43
|
data.xmsg = msg
|
|
@@ -44,7 +45,9 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
44
45
|
pending = new(nonce)
|
|
45
46
|
pending.msgout = data
|
|
46
47
|
exec.pending[data.xid] = pending
|
|
47
|
-
exec.PostMessage(data)
|
|
48
|
+
`(error) = exec.PostMessage(data)
|
|
49
|
+
if error
|
|
50
|
+
pending.signal(Error("execSend failed", error))
|
|
48
51
|
pending
|
|
49
52
|
}
|
|
50
53
|
|
|
@@ -62,10 +65,19 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
62
65
|
pending.signal(list(false, data))
|
|
63
66
|
}
|
|
64
67
|
|
|
68
|
+
// execFailed
|
|
69
|
+
// Communication has failed.
|
|
70
|
+
|
|
71
|
+
exec.execFailed = closure execFailed(error, local xid, pending) {
|
|
72
|
+
exec.pending.error = error
|
|
73
|
+
for `(xid, pending) in exec.pending
|
|
74
|
+
pending.signal(list(error))
|
|
75
|
+
}
|
|
76
|
+
|
|
65
77
|
// execClosed
|
|
66
78
|
// Note that the connection has closed, so signal all the waiters.
|
|
67
79
|
|
|
68
|
-
exec.execClosed = closure execClosed(error, local xid) {
|
|
80
|
+
exec.execClosed = closure execClosed(error, local xid, pending) {
|
|
69
81
|
for `(xid, pending) in exec.pending {
|
|
70
82
|
pending.signal(list(error))
|
|
71
83
|
pending[xid] = undefined
|
|
@@ -76,18 +88,25 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
76
88
|
// Return a context object for the instance, or an error, in a result tuple. Currently this does
|
|
77
89
|
// not ever reclaim old contexts on the instance end of things, but it should. ###
|
|
78
90
|
|
|
79
|
-
exec.context = closure context(local
|
|
91
|
+
exec.context = closure context(local error, retries, ms, delta, excon) {
|
|
80
92
|
retries = 0
|
|
81
93
|
ms = milliseconds()
|
|
94
|
+
delta = 1
|
|
82
95
|
while !exec.pending.ready {
|
|
83
|
-
exec.PostMessage({
|
|
96
|
+
`(error) = exec.PostMessage({
|
|
84
97
|
xmsg: "xstart"
|
|
85
98
|
})
|
|
99
|
+
if error
|
|
100
|
+
return (Error("exec.context failed", error))
|
|
86
101
|
if ++retries > 100
|
|
87
|
-
return (list(Error("timeout creating remote
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
102
|
+
return (list(Error("timeout creating remote context", type, name)))
|
|
103
|
+
if exec.pending.error
|
|
104
|
+
return (list(Error("cannot create remote context", exec.pending.error)))
|
|
105
|
+
sleep(delta)
|
|
106
|
+
if delta < 100
|
|
107
|
+
delta *= 2 }
|
|
108
|
+
excon = ExecutorContext(exec, exec.nextContextID++)
|
|
109
|
+
excon.register()
|
|
91
110
|
}
|
|
92
111
|
|
|
93
112
|
// attention
|
|
@@ -117,6 +136,7 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
117
136
|
*/
|
|
118
137
|
|
|
119
138
|
closure ExecutorContext(exec, contextID, local context, util) {
|
|
139
|
+
global(apply)
|
|
120
140
|
context = new(object, this)
|
|
121
141
|
util = modlist().Util.exports
|
|
122
142
|
|
|
@@ -172,13 +192,35 @@ closure ExecutorContext(exec, contextID, local context, util) {
|
|
|
172
192
|
context.evalq = macro evalq(expr, put, get) {
|
|
173
193
|
evalf(expr, eval(put), eval(get))
|
|
174
194
|
}
|
|
195
|
+
|
|
196
|
+
// apply
|
|
197
|
+
// Apply list of arguments to the specified procure evaluated remotely. If the procedure is a
|
|
198
|
+
// not a tuple then this uses the tuple definition if there is one.
|
|
199
|
+
|
|
200
|
+
context.apply = closure applyf(proc, args, put, get) {
|
|
201
|
+
if !tuple(proc) && tuple(proc.proc)
|
|
202
|
+
proc = proc.proc
|
|
203
|
+
evalf(list(apply, proc, args), eval(put), eval(get))
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// call
|
|
207
|
+
// Call the specified function remotely using local arguments:
|
|
208
|
+
// context.call(proc, args...)
|
|
175
209
|
|
|
210
|
+
context.call = macro callf args {
|
|
211
|
+
closure (proc, arglist, local eargs) {
|
|
212
|
+
while arglist
|
|
213
|
+
push(eval(pop(arglist)), eargs)
|
|
214
|
+
applyf(eval(proc), eargs)
|
|
215
|
+
} (pop(args), reverse(args))
|
|
216
|
+
}
|
|
217
|
+
|
|
176
218
|
// rpc
|
|
177
219
|
// Execute a remote procedure call without package translation, to reduce overhead. This will not
|
|
178
220
|
// properly transfer Naan-specific types like symbols, and the results will be native JavaScript.
|
|
179
221
|
// The procedure must be specified as a symbol or string.
|
|
180
222
|
|
|
181
|
-
context.rpc = closure rpc(proc, args, local data, result) {
|
|
223
|
+
context.rpc = closure rpc(proc, args, local data, pending, result) {
|
|
182
224
|
data = {
|
|
183
225
|
contextID: contextID
|
|
184
226
|
proc: proc
|
|
@@ -187,8 +229,12 @@ closure ExecutorContext(exec, contextID, local context, util) {
|
|
|
187
229
|
result = pending.wait()
|
|
188
230
|
if result.1.error
|
|
189
231
|
list(Error(result.1.error))
|
|
190
|
-
else
|
|
191
|
-
|
|
232
|
+
else {
|
|
233
|
+
result = result.1.result
|
|
234
|
+
if Array.isArray(result)
|
|
235
|
+
result = totuple(result)
|
|
236
|
+
list(false, result)
|
|
237
|
+
}
|
|
192
238
|
}
|
|
193
239
|
|
|
194
240
|
// finis
|
|
@@ -225,6 +271,7 @@ closure ExecutorContext(exec, contextID, local context, util) {
|
|
|
225
271
|
*/
|
|
226
272
|
|
|
227
273
|
closure ExecutorParallel(options, local maxcount, basename, parallel, exqueue, crValue) {
|
|
274
|
+
global()
|
|
228
275
|
maxcount = options.maxcount
|
|
229
276
|
if !maxcount
|
|
230
277
|
maxcount = 4 // default is 4 workers
|
|
@@ -251,7 +298,7 @@ closure ExecutorParallel(options, local maxcount, basename, parallel, exqueue, c
|
|
|
251
298
|
return (false)
|
|
252
299
|
parallel.workers[workdex] = false // reserve our spot
|
|
253
300
|
name = basename.concat("-", workdex+1)
|
|
254
|
-
worker = App.nide.track.spawn("Local", name, "ExecutorParallel")
|
|
301
|
+
worker = App.nide.track.spawn("Local", name, "ExecutorParallel") // ### App.nide.track.spawn may not exist
|
|
255
302
|
if worker.0 { // ### wasting space on workers list
|
|
256
303
|
debuglog("execParallel: cannot spawn worker:", ErrorString(worker.0))
|
|
257
304
|
return (false)
|
|
@@ -401,6 +448,7 @@ closure ExecutorParallel(options, local maxcount, basename, parallel, exqueue, c
|
|
|
401
448
|
*/
|
|
402
449
|
|
|
403
450
|
closure ExecutorTracker(local xtrak) {
|
|
451
|
+
global()
|
|
404
452
|
xtrak = new(object, this)
|
|
405
453
|
xtrak.instances = []
|
|
406
454
|
xtrak.watchers = []
|
|
@@ -451,7 +499,7 @@ closure ExecutorTracker(local xtrak) {
|
|
|
451
499
|
// enumlist
|
|
452
500
|
// Enumerate the list of executors.
|
|
453
501
|
|
|
454
|
-
xtrak.enumlist = function enumlist(local results) {
|
|
502
|
+
xtrak.enumlist = function enumlist(local results, instance) {
|
|
455
503
|
results = []
|
|
456
504
|
for instance in xtrak.instances
|
|
457
505
|
results.push(instance.executor)
|
|
@@ -509,6 +557,7 @@ closure ExecutorTracker(local xtrak) {
|
|
|
509
557
|
*/
|
|
510
558
|
|
|
511
559
|
closure execLambda(track, url, name, workerID, local target, nlregex, clientID, serverID) {
|
|
560
|
+
global()
|
|
512
561
|
target = ExecutorBase(track, "Lambda", name)
|
|
513
562
|
clientID = "DebugWorkers"
|
|
514
563
|
serverID = "Workers"
|
|
@@ -670,11 +719,15 @@ closure execLambda(track, url, name, workerID, local target, nlregex, clientID,
|
|
|
670
719
|
// Post a message to the target.
|
|
671
720
|
//
|
|
672
721
|
|
|
673
|
-
target.PostMessage = function PostMessage(data) {
|
|
722
|
+
target.PostMessage = function PostMessage(data, local result) {
|
|
723
|
+
result = connect()
|
|
724
|
+
if result.0
|
|
725
|
+
return (result)
|
|
674
726
|
target.ws.send({ // send user-entered text to worker
|
|
675
727
|
id: "msgin",
|
|
676
728
|
data: data
|
|
677
729
|
})
|
|
730
|
+
list(false, { posted: true })
|
|
678
731
|
}
|
|
679
732
|
|
|
680
733
|
//
|
|
@@ -753,7 +806,6 @@ closure execLambda(track, url, name, workerID, local target, nlregex, clientID,
|
|
|
753
806
|
*/
|
|
754
807
|
|
|
755
808
|
function execInit(local manifest) {
|
|
756
|
-
|
|
757
809
|
manifest = `(ExecutorBase, ExecutorContext, ExecutorParallel, ExecutorTracker, execLambda, execInit)
|
|
758
810
|
|
|
759
811
|
Naan.module.build(module.id, "executors", function(modobj, compobj) {
|