2021-12-26 19:43:48 -05:00
|
|
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
(function() {
|
|
|
|
|
|
2021-12-26 22:00:31 -05:00
|
|
|
let moto = self.moto = self.moto || {},
|
2021-12-26 19:43:48 -05:00
|
|
|
time = function() { return new Date().getTime() },
|
|
|
|
|
restarting = false,
|
|
|
|
|
running = {},
|
|
|
|
|
workurl = null,
|
|
|
|
|
worker = null,
|
|
|
|
|
seqid = 1;
|
|
|
|
|
|
2021-12-26 22:00:31 -05:00
|
|
|
if (moto.client) return;
|
|
|
|
|
|
2021-12-26 19:43:48 -05:00
|
|
|
/**
|
2021-12-26 22:00:31 -05:00
|
|
|
* @param {Function} fn name of function in moto.worker
|
2021-12-26 19:43:48 -05:00
|
|
|
* @param {Object} data to send to server
|
|
|
|
|
* @param {Function} onreply function to call on reply messages
|
|
|
|
|
* @param {Object[]} zerocopy array of objects to pass using zerocopy
|
|
|
|
|
*/
|
|
|
|
|
function send(fn, data, onreply, zerocopy) {
|
|
|
|
|
let seq = seqid++;
|
|
|
|
|
|
|
|
|
|
if (onreply) {
|
|
|
|
|
// establish listener and track replies
|
|
|
|
|
running[seq] = { fn:onreply };
|
|
|
|
|
}
|
|
|
|
|
let msg = {
|
|
|
|
|
seq: seq,
|
|
|
|
|
task: fn,
|
|
|
|
|
time: time(),
|
|
|
|
|
data: data
|
|
|
|
|
};
|
|
|
|
|
try {
|
|
|
|
|
worker.postMessage(msg, zerocopy);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.trace('work send error', {data, error});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// code is running in the browser / client context
|
2021-12-26 22:00:31 -05:00
|
|
|
let client = moto.client = {
|
2021-12-26 19:43:48 -05:00
|
|
|
send: send,
|
|
|
|
|
|
|
|
|
|
// factory can be overridden
|
|
|
|
|
newWorker: function(url = workurl) {
|
|
|
|
|
if (self.createWorker) {
|
|
|
|
|
return self.createWorker();
|
|
|
|
|
} else {
|
|
|
|
|
return new Worker(workurl = url);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// return number of running requests
|
|
|
|
|
current: function() {
|
|
|
|
|
let current = 0;
|
|
|
|
|
for (let rec of Object.values(running)) {
|
|
|
|
|
if (rec.fn) current++;
|
|
|
|
|
}
|
|
|
|
|
return current;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
stop: function() {
|
|
|
|
|
if (worker) {
|
|
|
|
|
worker.terminate();
|
|
|
|
|
worker = null;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// same as restart
|
|
|
|
|
start: function(url) {
|
2021-12-26 22:00:31 -05:00
|
|
|
client.restart(url);
|
2021-12-26 19:43:48 -05:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
restart: function(url) {
|
|
|
|
|
// prevent re-entry from cancel callback
|
|
|
|
|
if (restarting) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-26 22:00:31 -05:00
|
|
|
client.stop();
|
2021-12-26 19:43:48 -05:00
|
|
|
|
|
|
|
|
restarting = true;
|
|
|
|
|
|
|
|
|
|
for (let key in running) {
|
|
|
|
|
let rec = running[key];
|
|
|
|
|
if (rec.fn) {
|
|
|
|
|
rec.fn({error: "cancelled operation"});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
running = {};
|
2021-12-26 22:00:31 -05:00
|
|
|
worker = client.newWorker(url);
|
2021-12-26 19:43:48 -05:00
|
|
|
|
2021-12-26 22:00:31 -05:00
|
|
|
// bind to client to enable synth injections
|
|
|
|
|
client.onmessage = worker.onmessage = function(e) {
|
2021-12-26 19:43:48 -05:00
|
|
|
let now = time(),
|
|
|
|
|
reply = e.data,
|
|
|
|
|
record = running[reply.seq],
|
|
|
|
|
onreply = record ? record.fn : undefined;
|
|
|
|
|
|
2021-12-26 22:00:31 -05:00
|
|
|
if (reply.register) {
|
|
|
|
|
// console.log({register: reply.register});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-26 19:43:48 -05:00
|
|
|
if (reply.done) {
|
|
|
|
|
delete running[reply.seq];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// calculate and replace recv time
|
|
|
|
|
reply.time_recv = now - reply.time_recv;
|
|
|
|
|
|
|
|
|
|
if (onreply) {
|
|
|
|
|
onreply(reply.data, reply);
|
|
|
|
|
} else {
|
|
|
|
|
console.log({drop_reply: reply});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// signal worker client is ready
|
|
|
|
|
worker.postMessage("--init--");
|
|
|
|
|
|
|
|
|
|
restarting = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
})();
|