Arquivos
deepforge/src/plugins/CreateExecution/CreateExecution.js
T
Brian Broll 9508351c54 Fixes #83 Added plugin for snapshotting pipelines (#87)
WIP #83 Added CreateExecution plugin

WIP #83 Fixed pointer resolution for data nodes

WIP #83 Added 'Job boxing'

WIP #83 Fixed connection ptr resolution

WIP #83. Skipping CE tests
2016-05-24 13:32:15 -05:00

189 linhas
6.6 KiB
JavaScript

/*globals define*/
/*jshint node:true, browser:true*/
/**
* Generated by PluginGenerator 1.7.0 from webgme on Mon May 23 2016 14:23:16 GMT-0500 (CDT).
* A plugin that inherits from the PluginBase. To see source code documentation about available
* properties and methods visit %host%/docs/source/PluginBase.html.
*/
define([
'q',
'text!./metadata.json',
'plugin/PluginBase'
], function (
Q,
pluginMetadata,
PluginBase
) {
'use strict';
pluginMetadata = JSON.parse(pluginMetadata);
/**
* Initializes a new instance of CreateExecution.
* @class
* @augments {PluginBase}
* @classdesc This class represents the plugin CreateExecution.
* @constructor
*/
var CreateExecution = function () {
// Call base class' constructor.
PluginBase.call(this);
this.pluginMetadata = pluginMetadata;
};
/**
* Metadata associated with the plugin. Contains id, name, version, description, icon, configStructue etc.
* This is also available at the instance at this.pluginMetadata.
* @type {object}
*/
CreateExecution.metadata = pluginMetadata;
// Prototypical inheritance from PluginBase.
CreateExecution.prototype = Object.create(PluginBase.prototype);
CreateExecution.prototype.constructor = CreateExecution;
/**
* Main function for the plugin to execute. This will perform the execution.
* Notes:
* - Always log with the provided logger.[error,warning,info,debug].
* - Do NOT put any user interaction logic UI, etc. inside this method.
* - callback always has to be called even if error happened.
*
* @param {function(string, plugin.PluginResult)} callback - the result callback
*/
CreateExecution.prototype.main = function (callback) {
var self = this,
name = this.core.getAttribute(this.activeNode, 'name');
// Verify that the activeNode is a pipeline
if (!this.core.isTypeOf(this.activeNode, this.META.Pipeline)) {
return callback(`Current node is not a Pipeline!`, this.result);
}
// Given a pipeline, copy all the operations to a custom job
// - Copy the operations
// - Wrap the operations in "Job" boxes which contain running info
// - eg,
// - 'debug' the given run (download all execution files)
// - 'console' show console output (future feature)
// - Update the references
var tgtNode,
copies,
operations,
dataMapping = {};
tgtNode = this.core.createNode({
base: this.META.Execution,
parent: this.rootNode
});
this.core.setAttribute(tgtNode, 'name', `${name} Execution`);
this.core.loadChildren(this.activeNode)
.then(children => {
copies = this.core.copyNodes(children, tgtNode);
operations = copies
.filter(copy => this.core.isTypeOf(copy, this.META.Operation))
// Create a mapping of old names to new names
return Q.all(operations.map((copy, i) =>
// Add the input/output mappings to the dataMapping
this.addDataToMap(children[i], copy, dataMapping)
)
);
})
.then(() => { // datamapping is set!
this.updateReferences(copies, dataMapping)
this.boxOperations(operations, tgtNode);
return this.save(`Created execution of ${name}`);
})
.then(function () {
self.result.setSuccess(true);
callback(null, self.result);
})
.catch(err => callback(err, self.result));
};
CreateExecution.prototype.getExecutionsDir = function () {
return this.rootNode;
};
CreateExecution.prototype.addDataToMap = function (srcOp, dstOp, map) {
return Q.all(
[srcOp, dstOp]
.map(op => {
// Get the inputs and outputs for both
return this.core.loadChildren(op)
.then(containers => {
var names = containers.map(c => this.core.getAttribute(c, 'name')),
inputs = containers
.find((c, i) => names[i] === 'Inputs'),
outputs = containers
.find((c, i) => names[i] === 'Outputs');
return Q.all([inputs, outputs].map(c => this.core.loadChildren(c)));
});
})
)
.then(ios => {
var srcIO,
dstIO;
srcIO = ios[0].map(c => this.sortIOByName(c));
dstIO = ios[1].map(c => this.sortIOByName(c));
// match the nodes by same name!
srcIO.forEach((srcContainer, c) => srcContainer.forEach((node, n) =>
map[this.core.getPath(node)] = dstIO[c][n] // old id -> new node
)
);
return true;
});
};
CreateExecution.prototype.sortIOByName = function (container) {
return container.sort((a, b) =>
// sort by name
this.core.getAttribute(a, 'name') < this.core.getAttribute(b, 'name')
? 1 : -1
);
};
// Wrap each Operation with a Job 'box'
CreateExecution.prototype.boxOperations = function (operations, container) {
operations.forEach(copy => {
var name = this.core.getAttribute(copy, 'name'),
job;
// Create job
job = this.core.createNode({
base: this.META.Job,
parent: container
});
this.core.setAttribute(job, 'name', name);
// Move the given copy into the Job node
this.core.moveNode(copy, job);
});
};
CreateExecution.prototype.updateReferences = function (nodes, map) {
// For each new node, update the references (other than base)
// to the correct nodeId
nodes.forEach(copy => {
this.core.getPointerNames(copy)
.filter(name => name !== 'base')
.forEach(name => {
var tgt = this.core.getPointerPath(copy, name);
if (map[tgt]) {
this.logger.info(`Updating ptr ${name}`);
this.core.setPointer(copy, name, map[tgt]);
}
});
});
};
return CreateExecution;
});