basic child-process peer stuff working, still playing with peer API...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2017-03-01 00:44:02 +03:00
parent bf6ff1c549
commit 5787941bf2
4 changed files with 90 additions and 22 deletions

View File

@ -34,6 +34,8 @@ core.ImageGridFeatures.Feature('viewer-minimal', [
'lifecycle', 'lifecycle',
'base-full', 'base-full',
'peer',
'image-marks', 'image-marks',
'image-bookmarks', 'image-bookmarks',
@ -48,6 +50,8 @@ core.ImageGridFeatures.Feature('viewer-testing', [
'viewer-commandline', 'viewer-commandline',
'viewer-minimal', 'viewer-minimal',
'peer',
'workspace', 'workspace',
'ui', 'ui',
'keyboard', 'keyboard',

View File

@ -9,6 +9,10 @@
(function(require){ var module={} // make module AMD/node compatible... (function(require){ var module={} // make module AMD/node compatible...
/*********************************************************************/ /*********************************************************************/
if(typeof(process) != 'undefined'){
var child_process = requirejs('child_process')
}
var actions = require('lib/actions') var actions = require('lib/actions')
var features = require('lib/features') var features = require('lib/features')
@ -259,6 +263,9 @@ module.Peer = core.ImageGridFeatures.Feature({
doc: '', doc: '',
tag: 'peer', tag: 'peer',
suggested: [
'child-process-peer',
],
actions: PeerActions, actions: PeerActions,
}) })
@ -271,23 +278,44 @@ module.Peer = core.ImageGridFeatures.Feature({
// XXX all the return values here will be ignored -- need a way to figure // XXX all the return values here will be ignored -- need a way to figure
// out a cooperative mechanic to return promises... // out a cooperative mechanic to return promises...
var ChildProcessPeerActions = actions.Actions({ var ChildProcessPeerActions = actions.Actions({
// XXX do better message handling...
peerConnect: ['- Peer/', peerConnect: ['- Peer/',
makeProtocolHandler('child', function(id, options){ makeProtocolHandler('child', function(id, options){
// XXX need a cooperative way to pass this to the root method return...
return new Promise((function(resolve, reject){ return new Promise((function(resolve, reject){
// already connected... // already connected...
// XXX check if child is alive... // XXX check if child is alive...
if(id in this.__peers){ if(this.__peers
&& id in this.__peers
&& this.__peers[id].peer.connected){
return resolve(id) return resolve(id)
} }
// XXX run ig.js in child_process + add peer feature to setup... this.__peers = this.__peers || {}
// XXX
var p = this.__peers[id] = {
id: id,
peer: child_process.fork('ig.js'),
}
var peer = p.peer
// XXX setup message handlers...
// ...should be about the same as in setup below...
// XXX use a standard handler....
peer.on('message', (function(msg){
if(msg.type == 'action-call-result'){
var callback = (this.__peer_result_callbacks || {})[msg.id]
callback
&& (delete this.__peer_result_callbacks[msg.id])
&& callback(msg.value, msg.error)
}
}).bind(this))
resolve(id)
}).bind(this)) }).bind(this))
})], })],
peerDisconnect: ['- Peer/', peerDisconnect: ['- Peer/',
makeProtocolHandler('child', function(id){ makeProtocolHandler('child', function(id){
// XXX need a cooperative way to pass this to the root method return...
return new Promise((function(resolve, reject){ return new Promise((function(resolve, reject){
var that = this var that = this
// already disconnected... // already disconnected...
@ -295,29 +323,37 @@ var ChildProcessPeerActions = actions.Actions({
return resolve(id) return resolve(id)
} }
// trigger stop... // terminate child...
this.peerCall(id, 'stop') that.__peers[id].peer.kill()
.then(function(){ delete that.__peers[id]
// XXX terminate child...
// XXX
delete that.__peers[id]
})
}).bind(this)) }).bind(this))
})], })],
peerCall: ['- Peer/', peerCall: ['- Peer/',
makeProtocolHandler('child', function(id, action){ makeProtocolHandler('child', function(id, action){
// XXX need a cooperative way to pass this to the root method return...
return new Promise((function(resolve, reject){ return new Promise((function(resolve, reject){
// XXX // XXX
}).bind(this)) }).bind(this))
})], })],
peerApply: ['- Peer/', peerApply: ['- Peer/',
makeProtocolHandler('child', function(id, action, args){ makeProtocolHandler('child', function(id, action, args){
// XXX need a cooperative way to pass this to the root method return...
return new Promise((function(resolve, reject){ return new Promise((function(resolve, reject){
// XXX // XXX is this the right way to go???
var call_id = id +'-'+ Date.now()
// do the call...
this.__peers[id].peer.send({
id: call_id,
type: 'action-call',
action: action,
args: args,
})
// handle return value...
var handlers = this.__peer_result_callbacks = this.__peer_result_callbacks || {}
handlers[call_id] = function(res, err){ err ? reject(err) : resolve(res) }
}).bind(this)) }).bind(this))
})], })],
}) })
@ -344,6 +380,10 @@ module.ChildProcessPeer = core.ImageGridFeatures.Feature({
['start', ['start',
function(){ function(){
var that = this var that = this
// XXX do we need to handle stdout/stderr here???
// XXX need to handle both the child and parent processes...
process.on('message', function(msg){ process.on('message', function(msg){
// Handle action call... // Handle action call...
// //
@ -360,13 +400,36 @@ module.ChildProcessPeer = core.ImageGridFeatures.Feature({
// ignore_return: <bool>, // ignore_return: <bool>,
// } // }
if(msg.type == 'action-call' && msg.action in that){ if(msg.type == 'action-call' && msg.action in that){
var res = that[msg.action].apply(that, msg.args || []) if(msg.action in that){
try{
// do the call...
var res = that[msg.action].apply(that, msg.args || [])
if(!msg.ignore_return){ // return the value...
if(!msg.ignore_return){
process.send({
type: 'action-call-result',
id: msg.id,
value: res === that ? null : res,
})
}
// error...
} catch(err){
process.send({
type: 'action-call-result',
id: msg.id,
// XXX is this serializable???
error: err,
})
}
// error: action does not exist...
} else {
process.send({ process.send({
type: 'action-call-result', type: 'action-call-result',
id: msg.id, id: msg.id,
value: res === that ? null : res, error: `Action "${msg.action}" does not exist.`,
}) })
} }
@ -383,7 +446,7 @@ module.ChildProcessPeer = core.ImageGridFeatures.Feature({
callback callback
&& (delete this.__peer_result_callbacks[msg.id]) && (delete this.__peer_result_callbacks[msg.id])
&& callback(msg.value) && callback(msg.value, msg.error)
// Handle logger calls... // Handle logger calls...
// //

View File

@ -61,7 +61,10 @@ module.ImageGridFeatures =
// setup actions and start... // setup actions and start...
ImageGridFeatures ImageGridFeatures
.setup(['viewer-commandline']) .setup([
'viewer-testing',
'viewer-commandline',
])
.start() .start()

View File

@ -218,8 +218,6 @@ $(function(){
} }
}) })
.start() .start()
}) })