@naanlang/naan 1.2.0 → 1.3.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 +1 -1
- package/README.md +1 -1
- package/bin/index.js +5 -2
- package/dist/env_web.js +11 -1
- package/dist/naan.min.js +5 -5
- package/frameworks/browser/https_request.nlg +2 -0
- package/frameworks/browser/sworker.js +23 -23
- package/frameworks/browser/terminals.nlg +132 -20
- package/frameworks/browser/workers.nlg +4 -1
- package/frameworks/browser/ws_client.nlg +9 -3
- package/frameworks/client/apiclient.nlg +8 -6
- package/frameworks/client/psm_client.nlg +4 -4
- package/frameworks/client/relaycon.nlg +5 -1
- package/frameworks/common/common.nlg +10 -4
- package/frameworks/node/apiserver.nlg +190 -4
- package/frameworks/node/worker.nlg +112 -10
- package/frameworks/node/ws_client.nlg +10 -3
- package/frameworks/project/build.nlg +13 -11
- package/frameworks/project/projects.nlg +7 -5
- package/frameworks/running/executors.nlg +124 -34
- package/frameworks/running/taskexec.nlg +5 -1
- package/lib/browser/env_web.js +17 -7
- package/lib/browser/env_webworker.js +22 -3
- package/lib/core/naanlib.js +5 -5
- package/lib/env_node.js +15 -4
- package/lib/env_nodeworker.js +21 -1
- package/package.json +8 -5
- package/plugins/serviceAws/aws/aws-sdk-node.min.js +2 -2
- package/plugins/serviceAws/aws/aws-sdk.min.js +3 -2
- package/plugins/serviceAws/aws_dynamo.nlg +19 -19
- package/plugins/serviceAws/dbt_aws.nlg +1 -1
- package/plugins/serviceYC/generic_api.yaml +36 -0
- package/plugins/serviceYC/naanide-relay-index.js +148 -0
- package/plugins/serviceYC/serviceYC.nlg +60 -0
- package/plugins/serviceYC/yc_apigateway.nlg +205 -0
- package/plugins/serviceYC/yc_function.nlg +163 -0
- package/plugins/serviceYC/yc_vm.nlg +207 -0
- package/test/test_02_context.nlg +1 -1
- package/test/test_03_jsinterop.nlg +2 -2
- package/test/test_05_strings.nlg +7 -4
- package/test/test_07_lingo.nlg +1 -1
|
@@ -52,19 +52,28 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
// execReceived
|
|
55
|
-
//
|
|
55
|
+
// The specified message was received from the instance, so signal it.
|
|
56
56
|
|
|
57
57
|
exec.execReceived = closure execReceived(data, local pending) {
|
|
58
58
|
pending = exec.pending[data.xid]
|
|
59
|
-
if !pending {
|
|
59
|
+
if !pending { // not waiting on message
|
|
60
60
|
if data.xmsg == "xready"
|
|
61
61
|
exec.pending.ready = true
|
|
62
|
+
if data.xmsg == "xattention"
|
|
63
|
+
{ }
|
|
62
64
|
return
|
|
63
65
|
}
|
|
64
66
|
exec.pending[data.xid] = undefined
|
|
65
67
|
pending.signal(list(false, data))
|
|
66
68
|
}
|
|
67
69
|
|
|
70
|
+
// execSetStatus
|
|
71
|
+
// Received a status update from the instance.
|
|
72
|
+
|
|
73
|
+
exec.execSetStatus = function execSetStatus(status) {
|
|
74
|
+
exec.xstatus = status
|
|
75
|
+
}
|
|
76
|
+
|
|
68
77
|
// execFailed
|
|
69
78
|
// Communication has failed.
|
|
70
79
|
|
|
@@ -263,21 +272,22 @@ closure ExecutorContext(exec, contextID, local context, util) {
|
|
|
263
272
|
*
|
|
264
273
|
* Allowable options are:
|
|
265
274
|
* {
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
275
|
+
* spawnLoc: <string> // e.g. "Local" (default) or "Host"
|
|
276
|
+
* maxcount: <integer> // maximum workers, default 4
|
|
277
|
+
* initeval: `(<expr>, <put>, <get>) // initializes each new worker
|
|
278
|
+
* basename: <string> // worker label for UI, default "batch"
|
|
269
279
|
* }
|
|
270
280
|
*
|
|
271
281
|
*/
|
|
272
282
|
|
|
273
|
-
closure ExecutorParallel(options, local maxcount,
|
|
283
|
+
closure ExecutorParallel(track, options, local maxcount, parallel, exqueue, crValue) {
|
|
274
284
|
global()
|
|
285
|
+
options = merge({
|
|
286
|
+
spawnLoc: "Local"
|
|
287
|
+
maxcount: 4
|
|
288
|
+
basename: "batch"
|
|
289
|
+
}, options)
|
|
275
290
|
maxcount = options.maxcount
|
|
276
|
-
if !maxcount
|
|
277
|
-
maxcount = 4 // default is 4 workers
|
|
278
|
-
basename = options.basename
|
|
279
|
-
if !string(basename)
|
|
280
|
-
basename = "batch"
|
|
281
291
|
exqueue = [] // waiting for execution
|
|
282
292
|
parallel = new(object, this)
|
|
283
293
|
parallel.workers = [] // array of worker executors
|
|
@@ -288,36 +298,41 @@ closure ExecutorParallel(options, local maxcount, basename, parallel, exqueue, c
|
|
|
288
298
|
//
|
|
289
299
|
// Return the next available worker. If no workers are available and we haven't hit the maximum
|
|
290
300
|
// then create an additional worker and return it. If we cannot allocate another worker then this
|
|
291
|
-
// returns
|
|
301
|
+
// returns { wait: true }.
|
|
292
302
|
|
|
293
303
|
closure acquireWorker(local workdex, name, worker, context, result) {
|
|
294
304
|
if parallel.available.length > 0
|
|
295
|
-
return (parallel.available.pop())
|
|
305
|
+
return (list(false, parallel.available.pop()))
|
|
296
306
|
workdex = parallel.workers.length
|
|
297
307
|
if workdex >= maxcount
|
|
298
|
-
return (false)
|
|
308
|
+
return (list(false, { wait: true }))
|
|
299
309
|
parallel.workers[workdex] = false // reserve our spot
|
|
300
|
-
name = basename.concat("-", workdex+1)
|
|
301
|
-
worker =
|
|
302
|
-
|
|
310
|
+
name = options.basename.concat("-", workdex+1)
|
|
311
|
+
worker = track.spawn(options.spawnLoc, name, {
|
|
312
|
+
workerID: "ExecutorParallel"
|
|
313
|
+
})
|
|
314
|
+
if worker.0 {
|
|
315
|
+
parallel.workers.splice(workdex, 1)
|
|
303
316
|
debuglog("execParallel: cannot spawn worker:", ErrorString(worker.0))
|
|
304
|
-
return (
|
|
317
|
+
return (list(worker.0))
|
|
305
318
|
}
|
|
306
319
|
worker = worker.1
|
|
307
320
|
context = worker.context()
|
|
308
321
|
if context.0 {
|
|
309
|
-
|
|
322
|
+
parallel.workers.splice(workdex, 1)
|
|
310
323
|
worker.destroy()
|
|
311
|
-
|
|
324
|
+
debuglog("execParallel: cannot create worker context:", ErrorString(context.0))
|
|
325
|
+
return (list(context.0))
|
|
312
326
|
}
|
|
313
327
|
context = context.1
|
|
314
328
|
parallel.workers[workdex] = worker
|
|
315
329
|
parallel.contexts[worker] = context
|
|
316
330
|
if tuple(options.initeval) {
|
|
317
331
|
result = apply(context.eval, options.initeval)
|
|
318
|
-
if result.0
|
|
319
|
-
debuglog("execParallel: cannot initialize worker", name, ErrorString(result.0))
|
|
320
|
-
|
|
332
|
+
if result.0 {
|
|
333
|
+
debuglog("execParallel: cannot initialize worker", name, ErrorString(result.0))
|
|
334
|
+
return (list(result.0)) } }
|
|
335
|
+
return (list(false, worker))
|
|
321
336
|
}
|
|
322
337
|
|
|
323
338
|
// releaseWorker
|
|
@@ -337,23 +352,26 @@ closure ExecutorParallel(options, local maxcount, basename, parallel, exqueue, c
|
|
|
337
352
|
// don't remove work from the queue until we already have a worker.
|
|
338
353
|
//
|
|
339
354
|
|
|
340
|
-
closure execNext(local worker, result) {
|
|
355
|
+
closure execNext(local error, worker, result) {
|
|
341
356
|
if exqueue.length > 0 {
|
|
342
|
-
worker = acquireWorker()
|
|
343
|
-
if
|
|
344
|
-
if maxcount > 0 && parallel.workers.length == 0
|
|
345
|
-
|
|
346
|
-
|
|
357
|
+
`(error, worker) = acquireWorker()
|
|
358
|
+
if error {
|
|
359
|
+
if maxcount > 0 && parallel.workers.length == 0 {
|
|
360
|
+
exqueue = []
|
|
361
|
+
throw("execParallel: cannot allocate any workers at all") }
|
|
362
|
+
return // one failed, so try again later
|
|
347
363
|
}
|
|
364
|
+
if worker.wait
|
|
365
|
+
return // we're busy, so try again later
|
|
348
366
|
future(function(local next, context) {
|
|
349
367
|
next = exqueue.splice(0, 1).0 // remove oldest entry, from start
|
|
350
368
|
if !next {
|
|
351
369
|
releaseWorker(worker) // someone else already processed this
|
|
352
370
|
return
|
|
353
|
-
|
|
371
|
+
}
|
|
354
372
|
context = parallel.contexts[worker]
|
|
355
373
|
if next.eval
|
|
356
|
-
result = apply(context.eval, next.
|
|
374
|
+
result = apply(context.eval, next.eval)
|
|
357
375
|
else if next.proc
|
|
358
376
|
result = context.rpc(next.proc, next.args)
|
|
359
377
|
else
|
|
@@ -372,7 +390,7 @@ closure ExecutorParallel(options, local maxcount, basename, parallel, exqueue, c
|
|
|
372
390
|
//
|
|
373
391
|
|
|
374
392
|
parallel.eval = closure evalf(expr, put, get, local pending) {
|
|
375
|
-
if
|
|
393
|
+
if maxcount == 0
|
|
376
394
|
return (crValue) // already destroyed
|
|
377
395
|
pending = new(nonce)
|
|
378
396
|
exqueue.push({
|
|
@@ -392,13 +410,55 @@ closure ExecutorParallel(options, local maxcount, basename, parallel, exqueue, c
|
|
|
392
410
|
evalf(expr, eval(put), eval(get))
|
|
393
411
|
}
|
|
394
412
|
|
|
413
|
+
// exBatch
|
|
414
|
+
//
|
|
415
|
+
// Remote helper to execute a batch function.
|
|
416
|
+
//
|
|
417
|
+
|
|
418
|
+
closure exBatch(expr, local pending) {
|
|
419
|
+
// evaluate the expression in batch mode
|
|
420
|
+
function execbat() {
|
|
421
|
+
try {
|
|
422
|
+
pending.signal(list(false, evalactive(expr)))
|
|
423
|
+
} catch {
|
|
424
|
+
pending.signal(list(Error(exception)))
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
pending = new(nonce)
|
|
429
|
+
exec(list(execbat))
|
|
430
|
+
pending.wait()
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// batch
|
|
434
|
+
//
|
|
435
|
+
// Execute eval above in a remote in batch mode, waiting until it is complete.
|
|
436
|
+
//
|
|
437
|
+
|
|
438
|
+
parallel.batch = closure batchf(expr, put, get, local result) {
|
|
439
|
+
result = evalf(list(exBatch, list(quote, expr)), `(exBatch).append(put), get)
|
|
440
|
+
if result.0 // unpack our error wrapper
|
|
441
|
+
result
|
|
442
|
+
else
|
|
443
|
+
result.1
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// batchq
|
|
447
|
+
//
|
|
448
|
+
// Evaluate the specified QUOTED expression in a remote in batch mode.
|
|
449
|
+
//
|
|
450
|
+
|
|
451
|
+
parallel.batchq = macro batchq(expr, put, get) {
|
|
452
|
+
batchf(expr, eval(put), eval(get))
|
|
453
|
+
}
|
|
454
|
+
|
|
395
455
|
// rpc
|
|
396
456
|
//
|
|
397
457
|
// Execute a procedure call in a remote worker.
|
|
398
458
|
//
|
|
399
459
|
|
|
400
460
|
parallel.rpc = closure rpc(proc, args, local pending) {
|
|
401
|
-
if
|
|
461
|
+
if maxcount == 0
|
|
402
462
|
return (crValue) // already destroyed
|
|
403
463
|
pending = new(nonce)
|
|
404
464
|
exqueue.push({
|
|
@@ -410,13 +470,36 @@ closure ExecutorParallel(options, local maxcount, basename, parallel, exqueue, c
|
|
|
410
470
|
pending.wait()
|
|
411
471
|
}
|
|
412
472
|
|
|
473
|
+
// status
|
|
474
|
+
//
|
|
475
|
+
// Report status of workers. Each worker has a dictionary:
|
|
476
|
+
// {
|
|
477
|
+
// state: <string> // "active" or "idle"
|
|
478
|
+
// status: <dict> // like runaverage(1)
|
|
479
|
+
// }
|
|
480
|
+
//
|
|
481
|
+
|
|
482
|
+
parallel.status = function status(local output, worker) {
|
|
483
|
+
output = []
|
|
484
|
+
for worker in parallel.workers {
|
|
485
|
+
output.push({
|
|
486
|
+
name: worker.name
|
|
487
|
+
type: worker.type
|
|
488
|
+
state: if parallel.available.indexOf(worker) >= 0
|
|
489
|
+
"idle" else "active"
|
|
490
|
+
status: worker.xstatus
|
|
491
|
+
})
|
|
492
|
+
}
|
|
493
|
+
output
|
|
494
|
+
}
|
|
495
|
+
|
|
413
496
|
// destroy
|
|
414
497
|
//
|
|
415
498
|
// Destroy the object by destroying the workers and failing pending requests with cancelResult.
|
|
416
499
|
//
|
|
417
500
|
|
|
418
501
|
parallel.destroy = closure destroy(cancelResult, local worker, next) {
|
|
419
|
-
if
|
|
502
|
+
if maxcount == 0
|
|
420
503
|
return (false) // already destroyed
|
|
421
504
|
crValue = cancelResult
|
|
422
505
|
maxcount = 0
|
|
@@ -542,6 +625,13 @@ closure ExecutorTracker(local xtrak) {
|
|
|
542
625
|
} (pop(args), args)
|
|
543
626
|
}
|
|
544
627
|
|
|
628
|
+
// parallel
|
|
629
|
+
// Return a new parallel executor with specified options.
|
|
630
|
+
|
|
631
|
+
xtrak.parallel = function parallel(options) {
|
|
632
|
+
ExecutorParallel(xtrak, options)
|
|
633
|
+
}
|
|
634
|
+
|
|
545
635
|
xtrak.register(execLambda, "Lambda")
|
|
546
636
|
|
|
547
637
|
// finis
|
|
@@ -28,12 +28,16 @@ closure TaskDispatcher(replier, local contexts, gohome, util) {
|
|
|
28
28
|
reply = {
|
|
29
29
|
xmsg: "error"
|
|
30
30
|
xid: data.xid
|
|
31
|
+
_guid: data._guid || undefined
|
|
31
32
|
error: "unknown operation"
|
|
32
33
|
}
|
|
33
34
|
try {
|
|
34
35
|
restorens = makeActivator()
|
|
35
36
|
if data.xmsg == "xstart"
|
|
36
|
-
reply = {
|
|
37
|
+
reply = { // ready to accept messages
|
|
38
|
+
xmsg: "xready"
|
|
39
|
+
_guid: data._guid || undefined
|
|
40
|
+
}
|
|
37
41
|
else if data.xmsg == "register" {
|
|
38
42
|
//
|
|
39
43
|
// register a new context to default namespace
|
package/lib/browser/env_web.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* column positioning: // // !
|
|
8
8
|
*
|
|
9
|
-
* Copyright (c) 2017-
|
|
9
|
+
* Copyright (c) 2017-2024 by Richard C. Zulch
|
|
10
10
|
*
|
|
11
11
|
*/
|
|
12
12
|
|
|
@@ -223,7 +223,17 @@ exports.NaanControllerWeb = function() {
|
|
|
223
223
|
}, 1);
|
|
224
224
|
};
|
|
225
225
|
|
|
226
|
+
var replyHook;
|
|
227
|
+
this.OnReplyHook = function OnReplyHook(proc) {
|
|
228
|
+
replyHook = proc;
|
|
229
|
+
return (proc);
|
|
230
|
+
};
|
|
231
|
+
|
|
226
232
|
this.ReplyMessage = function ReplyMessage(data) { // "remote" -> "local"
|
|
233
|
+
if (replyHook)
|
|
234
|
+
setTimeout(function() {
|
|
235
|
+
replyHook(data);
|
|
236
|
+
}, 1);
|
|
227
237
|
termlist.forEach(function(term) {
|
|
228
238
|
if (term.OnMessageOut)
|
|
229
239
|
term.OnMessageOut(data);
|
|
@@ -526,7 +536,7 @@ exports.NaanControllerWeb = function() {
|
|
|
526
536
|
statedoc.curversion = kStateCurrentVersion;
|
|
527
537
|
statedoc.firstver = kStateFirstVersion;
|
|
528
538
|
statedoc.licensee = "MIT-License";
|
|
529
|
-
statedoc.verstring = "1.
|
|
539
|
+
statedoc.verstring = "1.3.0+1";
|
|
530
540
|
statedoc.date = new Date().toISOString();
|
|
531
541
|
statedoc.prefs = prefs;
|
|
532
542
|
statedoc.naan = naanlib.saveState(false); // true to optimize, which is a bit slower
|
|
@@ -544,7 +554,7 @@ exports.NaanControllerWeb = function() {
|
|
|
544
554
|
|| statedoc.firstver > kStateCurrentVersion
|
|
545
555
|
|| statedoc.curversion < kStateFirstVersion
|
|
546
556
|
|| statedoc.licensee != "MIT-License"
|
|
547
|
-
|| statedoc.verstring != "1.
|
|
557
|
+
|| statedoc.verstring != "1.3.0+1")
|
|
548
558
|
{
|
|
549
559
|
localStorage.removeItem("NaanState_Hosted");
|
|
550
560
|
return (false);
|
|
@@ -603,7 +613,7 @@ exports.NaanControllerWeb = function() {
|
|
|
603
613
|
op: "VsiteOpen",
|
|
604
614
|
name: vsiteName,
|
|
605
615
|
naancont: contSelf,
|
|
606
|
-
title: vsiteName + " 1.
|
|
616
|
+
title: vsiteName + " 1.3.0+1"
|
|
607
617
|
});
|
|
608
618
|
}
|
|
609
619
|
} catch (e) {
|
|
@@ -617,7 +627,7 @@ exports.NaanControllerWeb = function() {
|
|
|
617
627
|
op: "VsiteClose",
|
|
618
628
|
name: vsiteName,
|
|
619
629
|
naancont: contSelf,
|
|
620
|
-
title: vsiteName + " 1.
|
|
630
|
+
title: vsiteName + " 1.3.0+1"
|
|
621
631
|
});
|
|
622
632
|
termTextOut("\x1b[90m\x1b[3m".concat("\nwindow closed", "\x1b[0m\n"));
|
|
623
633
|
}
|
|
@@ -632,8 +642,8 @@ exports.NaanControllerWeb = function() {
|
|
|
632
642
|
naanlib.banner();
|
|
633
643
|
var hostpath = naanlib.js.r("path").dirname(window.location.href);
|
|
634
644
|
naanlib.start({
|
|
635
|
-
cmd: 'App.version = "1.
|
|
636
|
-
+ 'App.cache = "
|
|
645
|
+
cmd: 'App.version = "1.3.0+1";;\r\n'
|
|
646
|
+
+ 'App.cache = "49a9b89fb804111a36026df163e15009";;\r\n'
|
|
637
647
|
+ 'Naan.module.requireQuery({ naanver: App.cache });;\r\n'
|
|
638
648
|
+ 'Naan.module.webparse("naan_init.nlg", "' + hostpath + '", { naanver: App.cache });;\r\n'
|
|
639
649
|
});
|
|
@@ -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
|
|
|
@@ -83,13 +83,27 @@ exports.NaanControllerWebWorker = function NaanControllerWebWorker() {
|
|
|
83
83
|
});
|
|
84
84
|
return (data);
|
|
85
85
|
};
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
var targetListener;
|
|
88
88
|
targSelf.OnMessage = function OnMessage(proc) {
|
|
89
89
|
targetListener = proc;
|
|
90
90
|
return (proc);
|
|
91
91
|
};
|
|
92
|
-
|
|
92
|
+
|
|
93
|
+
this.DispatchMessage = function DispatchMessage(data) {
|
|
94
|
+
postMessage({ // target is sending a message
|
|
95
|
+
id: "targetsend",
|
|
96
|
+
data: data
|
|
97
|
+
});
|
|
98
|
+
return (data);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
var targetReceiver;
|
|
102
|
+
targSelf.OnReceive = function OnReceive(proc) {
|
|
103
|
+
targetReceiver = proc;
|
|
104
|
+
return (proc);
|
|
105
|
+
};
|
|
106
|
+
|
|
93
107
|
targSelf.ReplyDebugger = function ReplyDebugger(data) {
|
|
94
108
|
postMessage({ // target is sending debug data
|
|
95
109
|
id: "debugout",
|
|
@@ -149,6 +163,11 @@ exports.NaanControllerWebWorker = function NaanControllerWebWorker() {
|
|
|
149
163
|
if (debugListener)
|
|
150
164
|
debugListener(msg.data); // target received a message
|
|
151
165
|
}
|
|
166
|
+
else if (msg.id == "targetreceive")
|
|
167
|
+
{
|
|
168
|
+
if (targetReceiver)
|
|
169
|
+
targetReceiver(msg.data);
|
|
170
|
+
}
|
|
152
171
|
};
|
|
153
172
|
|
|
154
173
|
//
|