-
Notifications
You must be signed in to change notification settings - Fork 108
Implementation_walker
Walker
labs_walker.js module is the DSP Walker; client-side sidebar.html view and labs.html view show a complete tree of repositories and labs; when main.html is rendered a request is sent to the server to get all labs. Walker recursively traverses all directories starting from mainDir directory. How does DSP know that a directory is a DSP lab or repository? a DSP identificator is used, namely a “.dsp” empty file inside a directory means that it’s a docker directory.
Public module method is create that uses walk method of DSPWalk stampit object (look at Eric Elliot Stampit module to understand this module).
DSPWalk uses dspw object of type DSPWalker to walk the root directory; DSPWalker inherits from BaseWalker that has a walk function that recursively traverses all repos and labs directories and convert them in json objects; a specificaation of dirFound method is done in DSPWalk to filter only DSP directories.
const BaseWalker = stampit(MyEmitter).init(function init(obj) {
this.dir = path.join(homedir(), obj.dir);
this.basename = obj.dir;
// Those we'll be override
this.haveToFilter = function haveToFilter() {
return true;
};
this.dirFound = function dirFound() {
return null;
};
this.fileFound = function fileFound() {
};
// True if is the label
this.isLabel = function isLabel(file) {
return (file === path.join(this.dir, 'labels.json'));
};
this.isNetwork = function isInformation(file) {
return (file === path.join(this.dir, 'network.json'));
};
this.isInformation = function isInformation(file) {
return (file === path.join(this.dir, 'informations.json'));
};
// Filter only one subdirectory
this.haveToFilter = function haveToFilter(dir) {
const baseDir = this.dir;
const re = new RegExp(`${baseDir}/?([^/]+/?){0,1}$`);
return re.test(dir);
};
this.walk = function walk() {
const self = this;
const baseDir = self.dir;
Walker(baseDir)
.filterDir((dir) => {
const haveToFilter = self.haveToFilter(dir);
return haveToFilter;
})
.on('dir', (dir) => {
// skip base dir
if (dir !== baseDir) {
self.dirFound(dir);
}
})
.on('file', (file) => {
self.fileFound(file);
})
.on('end', () => {
self.walkEnded();
});
};
});
const DSPWalker = stampit(BaseWalker)
.init(function init() {
const self = this;
this.repos = [];
// A repo
this.dirFound = function dirFound(dir) {
// Explore labs
AppUtils.isDSPDir(dir, (exists) => {
if (exists) {
const name = path.basename(dir);
const p = path.join(self.basename, path.basename(dir));
const rw = RepoWalker({ dir: p });
self.repos.push({ name, repo: rw });
}
});
};
});
DSPWalker only returns the complete paths of labs, but no informations are loaded, so next step of DSPWalk are to get informations from labels.json and informations.json of each lab. When all the operation are done DSPWalker returns an array containing a set of repositories and each repository contains a set of labs.
const DSPWalk = stampit(MyEmitter)
.methods({
walk(dir) {
const dspw = DSPWalker({ dir });
const retObj = {};
const self = this;
async.waterfall([
// Walk main dspwalker
(cb) => {
dspw.walk();
dspw.onEnded(() => cb(null));
},
// For each repo
(cb) => {
const repos = dspw.repos;
// Each repo
async.each(repos, (ele, callback) => {
ele.repo.walk();
ele.repo.onEnded(() => callback(null));
}, (err) => cb(err));
},
// For each lab
(cb) => {
let labs = [];
// Take all labs
_.each(dspw.repos, (ele) => {
labs = labs.concat(ele.repo.labs);
});
// walk each lab
async.each(labs, (ele, callback) => {
ele.lab.walk();
ele.lab.onEnded(() => callback(null));
},
// Finish labs loaded
(err) => cb(err || null));
},
// convert all repo files
(cb) => {
retObj.repos = [];
const repos = dspw.repos;
async.each(repos, (ele, callback) => {
const r = { name: ele.name };
r.labs = ele.repo.labs;
const labelFile = ele.repo.labels;
if (labelFile) {
jsonfile.readFile(labelFile, (err, json) => {
// Parsing error
if (!err && json.labels) {
r.labels = json.labels;
}
retObj.repos.push(r);
callback(null);
});
} else {
retObj.repos.push(r);
callback(null);
}
},
(err) => cb(err || null));
},
// Convert all lab files
(cb) => {
// log.info("convert all lab files")
let repos = retObj.repos;
// Sort repos by name
repos = _.sortBy(repos, 'name');
retObj.repos = repos;
// For each repo
async.each(repos, (r, repocallback) => {
let labs = r.labs;
// Sort labs by name
labs = _.sortBy(labs, 'name');
const arrLabs = [];
async.each(labs, (ele, callback) => {
const l = { name: ele.name };
// inner parallel
async.parallel({
// Informations
informations(c) {
const fileInfo = ele.lab.informations;
if (fileInfo) {
jsonfile.readFile(fileInfo, c);
// File error
} else {
c(null);
}
},
state(c) {
log.info(`Taking state of ${r.name}/${l.name}`);
const state = LabStates.getState(r.name, l.name, c);
},
labels(c) {
const fileLabels = ele.lab.labels;
if (fileLabels) {
jsonfile.readFile(fileLabels, c);
} else {
// File error
c(null, { labels: [] });
}
},
},
// Loaded files
(err, results) => {
l.labels = results.labels.labels;
l.informations = results.informations;
l.state = results.state;
// log.warn(l.state);
arrLabs.push(l);
callback(null);
});
}, () => {
r.labs = arrLabs;
repocallback(null);
});
},
// End repos
() => cb(null));
},
], () => {
self.object = retObj;
self.walkEnded();
});
},
});
exports.create = () => {
const ret = DSPWalk.create();
return ret;
};