etnbrd/flx-lib

View on GitHub
docs/index.html

Summary

Maintainability
Test Coverage
<!DOCTYPE html>

<html>
<head>
  <title>index.js</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
  <link rel="stylesheet" media="all" href="docco.css" />
</head>
<body>
  <div id="container">
    <div id="background"></div>
    
    <ul class="sections">
        
          <li id="title">
              <div class="annotation">
                  <h1>index.js</h1>
              </div>
          </li>
        
        
        
        <li id="section-1">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-1">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>),
    fork = <span class="hljs-built_in">require</span>(<span class="hljs-string">'child_process'</span>).fork;

<span class="hljs-keyword">var</span> flxRepo = {},
    minions = {},
    options = {
      allowFlxOverwrite: <span class="hljs-literal">false</span>, <span class="hljs-comment">// disallow the redifinition of fluxion (it will mess with remote fluxion)</span>
      immediateDeploy: <span class="hljs-literal">true</span>, <span class="hljs-comment">// Deploy minions immediatly after initialisation</span>
    };

<span class="hljs-comment">/* TODO a fluxion is an entry point for execution distributed over the network.
   It makes sense to say that multiple fluxions can share the same heap (but not scope), because they are on the same minion.
   So minions assure the low-level isolation, and fluxion assure the higher-level isolation.
   During the registration phase, the library should gather fluxion by minions, and then creates minions, so that the fluxions can actually share the heap, once deployed remotely.

   Also, it would make sense to preserve the cycles, we need a way to serialize that, and restore the memory as-is on the remote minions.
 */</span></pre></div></div>
            
        </li>
        
        
        <li id="section-2">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-2">&#182;</a>
              </div>
              <p>TODO refactor : message and some other functions are duplicated between index.js and minion.js</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">message</span><span class="hljs-params">(dest, body)</span> </span>{
  <span class="hljs-keyword">return</span> {
    dest: dest,
    body: body
  };
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">register</span><span class="hljs-params">(name, fn, scp, remote)</span> </span>{
  <span class="hljs-keyword">if</span> (flxRepo[name] &amp;&amp; !options.allowFlxOverwrite)
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> fn === <span class="hljs-string">'function'</span>) {
    scp = scp || {};
    scp.m = message;

    <span class="hljs-keyword">var</span> flx = {run: fn, scp: scp, minion: remote};

    <span class="hljs-keyword">if</span>(remote) {
      <span class="hljs-keyword">if</span> (!minions[remote]) minions[remote] = {name: remote, flx:{}};
      minions[remote].flx[name] = flx;
    }
    
    flxRepo[name] = flx;

    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }

  <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">receive</span><span class="hljs-params">(req)</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_receiveOne</span><span class="hljs-params">(dest)</span> </span>{
    <span class="hljs-keyword">if</span> (!flxRepo[dest]) {
      <span class="hljs-keyword">throw</span> <span class="hljs-string">'flx '</span> + dest + <span class="hljs-string">' is not defined'</span>;
    }

    <span class="hljs-keyword">if</span> (flxRepo[dest].worker) { <span class="hljs-comment">// flxRepo[dest].minion) { // should test on minion, but as deployement can be postponed, we actually test on the worker</span></pre></div></div>
            
        </li>
        
        
        <li id="section-3">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-3">&#182;</a>
              </div>
              <p>TODO do serialization here</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>      flxRepo[dest].minion.worker.send({reason: <span class="hljs-string">'post'</span>, data: message(dest, req.body)});
    } <span class="hljs-keyword">else</span> {
      process.nextTick(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>{
        <span class="hljs-keyword">var</span> res = flxRepo[dest].run.call(flxRepo[dest].scp, req.body);
        <span class="hljs-keyword">if</span> (res) receive(res);
      });
    }
  }

  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Array</span>.isArray(req.dest)) {
    req.dest.forEach(_receiveOne)
  } <span class="hljs-keyword">else</span> {
    _receiveOne(req.dest);
  }
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">rcvMsgFactory</span><span class="hljs-params">(name)</span> </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_receiveMessage</span><span class="hljs-params">(message)</span> </span>{
    <span class="hljs-keyword">if</span> (message.reason === <span class="hljs-string">'log'</span>)
      <span class="hljs-built_in">console</span>.log(name + <span class="hljs-string">'&gt;&gt; '</span>, message.data.join(<span class="hljs-string">' '</span>));

    <span class="hljs-keyword">if</span> (message.reason === <span class="hljs-string">'post'</span>) {
      receive(message.data)
    }
  }
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">bootstrapMinions</span><span class="hljs-params">()</span> </span>{

  <span class="hljs-comment">/* Warning, there might be a race condition in this fonction.
     I don't now if fork is synchronous or not, and I can't find anythin on the web.
     If it is synchronous, there is no race condition, but poor performance are to be expected.
     If it is asynchronous, there is potentially a race condition, if messages are dropped during the fork.
     If the pipes are buffered, there should be no race condition, however.
   */</span>

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> minionName <span class="hljs-keyword">in</span> minions) { <span class="hljs-keyword">var</span> minion = minions[minionName];

    <span class="hljs-keyword">if</span> (!minion.worker) {
      minion.worker = fork(__dirname + <span class="hljs-string">'/minion.js'</span>);
      minion.worker.on(<span class="hljs-string">'message'</span>, rcvMsgFactory(minionName));
    }

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> flxName <span class="hljs-keyword">in</span> minion.flx) { <span class="hljs-keyword">var</span> flx = minion.flx[flxName];
      <span class="hljs-keyword">if</span> (!flx.deployed) {</pre></div></div>
            
        </li>
        
        
        <li id="section-4">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-4">&#182;</a>
              </div>
              <p>TODO do serialization here</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        flx.minion = minion;
        flx.deployed = <span class="hljs-literal">true</span>; <span class="hljs-comment">// We are optimistic here. On the verge of ecstasy would be more a accurate definition, though.</span></pre></div></div>
            
        </li>
        
        
        <li id="section-5">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-5">&#182;</a>
              </div>
              <p>In flx, there is minion, which contains an object of the registered fluxion including flx itslef : circular dependency.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">var</span> remoteFlx = {
          run: flx.run,
          scp: flx.scp
        }

        minion.worker.send({reason:<span class="hljs-string">'register'</span>, data: remoteFlx})
      }

    }
  }
}</pre></div></div>
            
        </li>
        
        
        <li id="section-6">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-6">&#182;</a>
              </div>
              <p>Right after synchronously registering all the fluxions, we bootstrap the </p>

            </div>
            
            <div class="content"><div class='highlight'><pre>process.nextTick(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{
  <span class="hljs-keyword">if</span> (options.immediateDeploy) {
    bootstrapMinions
  }
});

<span class="hljs-built_in">module</span>.exports = {
  register: register,
  post: receive,
  start: receive,
  m: message,
  deploy: bootstrapMinions,
  options: options
}</pre></div></div>
            
        </li>
        
    </ul>
  </div>
</body>
</html>