Skip to content

Implementation_walker

Gaetano Perrone edited this page Dec 14, 2019 · 1 revision

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;
};