spas
Version:
spas is a pragmatic tool for bundling multiple API requests into a single request/response for the end user. spas throttles, caches, parses, filters, concatenates and minifies API responses. It serves them all up in one tidy little package resulting in fe
197 lines (166 loc) • 65.5 kB
HTML
<!DOCTYPE html> <html> <head> <title>engine.js</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> engine.js </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="kd">var</span> <span class="nx">nconf</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'nconf'</span><span class="p">)</span>
<span class="p">,</span> <span class="nx">redis</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"redis"</span><span class="p">)</span>
<span class="p">,</span> <span class="nx">_</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'underscore'</span><span class="p">).</span><span class="nx">_</span>
<span class="p">,</span> <span class="nx">neuron</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'neuron'</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>, crypto = require('crypto')
, sha = crypto.createHash('sha1')
, zlib = require('zlib')</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">;</span>
<span class="nx">require</span><span class="p">(</span><span class="s1">'date-utils'</span><span class="p">);</span>
</pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Use nconf to grab commandline params and read config.json</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">nconf</span><span class="p">.</span><span class="nx">argv</span><span class="p">().</span><span class="nx">file</span><span class="p">({</span> <span class="nx">file</span><span class="o">:</span> <span class="s1">'config.json'</span> <span class="p">});</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>If --dev is passed use the development config section</p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">var</span> <span class="nx">config</span> <span class="o">=</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">'dev'</span><span class="p">)</span> <span class="o">?</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">'development'</span><span class="p">)</span> <span class="o">:</span> <span class="nx">nconf</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">'live'</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Connect to redis</p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">var</span> <span class="nx">client</span> <span class="o">=</span> <span class="nx">redis</span><span class="p">.</span><span class="nx">createClient</span><span class="p">(</span><span class="nx">config</span><span class="p">.</span><span class="nx">redis</span><span class="p">.</span><span class="nx">port</span><span class="p">,</span> <span class="nx">config</span><span class="p">.</span><span class="nx">redis</span><span class="p">.</span><span class="nx">address</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">nconf</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">config</span><span class="p">.</span><span class="nx">redis</span><span class="p">.</span><span class="nx">auth</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">client</span><span class="p">.</span><span class="nx">auth</span><span class="p">(</span><span class="nx">config</span><span class="p">.</span><span class="nx">redis</span><span class="p">.</span><span class="nx">auth</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span> </pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>handle err; </p> </td> <td class="code"> <div class="highlight"><pre> <span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <h2>Recursive function to remove unwanted elements from API response</h2> </td> <td class="code"> <div class="highlight"><pre><span class="kd">var</span> <span class="nx">filter</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">map</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">isArray</span><span class="p">(</span><span class="nx">source</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">item</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="p">{</span> <span class="nx">filter</span><span class="p">(</span> <span class="nx">item</span><span class="p">,</span> <span class="nx">map</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span> <span class="p">});</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">isString</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">||</span> <span class="nx">map</span> <span class="o">===</span> <span class="kc">true</span> <span class="o">||</span> <span class="nx">_</span><span class="p">.</span><span class="nx">isUndefined</span><span class="p">(</span><span class="nx">map</span><span class="p">))</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">source</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">isUndefined</span><span class="p">(</span><span class="nx">map</span><span class="p">[</span><span class="nx">key</span><span class="p">]))</span> <span class="p">{</span>
<span class="k">delete</span> <span class="nx">source</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">filter</span><span class="p">(</span> <span class="nx">obj</span><span class="p">,</span> <span class="nx">map</span><span class="p">[</span><span class="nx">key</span><span class="p">]);</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">};</span>
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <h2>Perform scheduled refresh</h2> </td> <td class="code"> <div class="highlight"><pre><span class="nx">exports</span><span class="p">.</span><span class="nx">refresh</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">api</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">bid</span><span class="p">,</span> <span class="nx">bundle</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>We're forcing a refresh of the content so run the api.code</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">api</span><span class="p">.</span><span class="nx">resource</span><span class="p">(</span> <span class="nx">api</span><span class="p">.</span><span class="nx">params</span><span class="p">,</span> <span class="nx">api</span><span class="p">.</span><span class="nx">credentials</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span> <span class="nx">err</span><span class="p">,</span> <span class="nx">res</span> <span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span> <span class="nx">err</span> <span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>We got an error so set our output object to be the error and expire immediately</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">api</span><span class="p">.</span><span class="nx">expires</span> <span class="o">=</span> <span class="p">(</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">()</span> <span class="p">);</span>
<span class="kd">var</span> <span class="nx">tout</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">expires</span><span class="o">:</span> <span class="nx">api</span><span class="p">.</span><span class="nx">expires</span><span class="p">,</span>
<span class="nx">result</span><span class="o">:</span> <span class="nx">err</span><span class="p">,</span>
<span class="nx">iid</span><span class="o">:</span> <span class="nx">bid</span><span class="o">+</span><span class="nx">key</span><span class="p">,</span>
<span class="nx">cname</span><span class="o">:</span> <span class="nx">key</span><span class="p">,</span>
<span class="nx">scheduled</span><span class="o">:</span> <span class="kc">true</span>
<span class="p">};</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Filter the response</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">api</span><span class="p">.</span><span class="nx">filter</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">filter</span> <span class="p">(</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">api</span><span class="p">.</span><span class="nx">filter</span> <span class="p">);</span>
<span class="p">}</span>
</pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Perform cleanup function on API response</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">api</span><span class="p">,</span> <span class="s1">'cleanup'</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">res</span> <span class="o">=</span> <span class="nx">api</span><span class="p">.</span><span class="nx">cleanup</span><span class="p">(</span><span class="nx">res</span><span class="p">);</span>
<span class="p">}</span>
</pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Build the stored response</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">api</span><span class="p">.</span><span class="nx">expires</span> <span class="o">=</span> <span class="p">(</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">()</span> <span class="p">).</span><span class="nx">addSeconds</span><span class="p">(</span> <span class="nx">api</span><span class="p">.</span><span class="nx">cacheduration</span> <span class="p">);</span>
<span class="nx">bundle</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">api</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">tout</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">expires</span><span class="o">:</span> <span class="nx">api</span><span class="p">.</span><span class="nx">expires</span><span class="p">,</span>
<span class="nx">result</span><span class="o">:</span> <span class="nx">res</span><span class="p">,</span>
<span class="nx">iid</span><span class="o">:</span> <span class="nx">api</span><span class="p">.</span><span class="nx">iid</span><span class="p">,</span>
<span class="nx">cname</span><span class="o">:</span> <span class="nx">key</span><span class="p">,</span>
<span class="nx">scheduled</span><span class="o">:</span> <span class="kc">true</span>
<span class="p">};</span>
</pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Save response to Redis</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">client</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">bid</span><span class="o">+</span><span class="nx">key</span><span class="p">,</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">tout</span><span class="p">));</span>
</pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>Update the bundle</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">client</span><span class="p">.</span><span class="nx">del</span><span class="p">(</span><span class="s1">'bundle'</span><span class="o">+</span><span class="nx">bid</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <h2>Retrieve the requested bundle</h2> </td> <td class="code"> <div class="highlight"><pre><span class="nx">exports</span><span class="p">.</span><span class="nx">fulfill</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span> <span class="nx">myRes</span><span class="p">,</span> <span class="nx">bid</span><span class="p">,</span> <span class="nx">bundle</span><span class="p">,</span> <span class="nx">callback</span><span class="p">,</span> <span class="nx">override</span> <span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">bundle</span> <span class="o">===</span> <span class="s1">'undefined'</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">myRes</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">404</span><span class="p">);</span>
<span class="nx">myRes</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
</pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>Count the number of queries in this bundle so we know when we are ready to respond</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">queriesInThisBundle</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">size</span><span class="p">(</span><span class="nx">bundle</span><span class="p">),</span>
<span class="nx">thisResponse</span> <span class="o">=</span> <span class="p">{};</span>
</pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>cleanup is not an API request</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span><span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">bundle</span><span class="p">,</span> <span class="s1">'cleanup'</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">queriesInThisBundle</span><span class="o">--</span><span class="p">;</span>
<span class="p">}</span>
</pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>If override was not passed</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span><span class="p">(</span> <span class="nx">_</span><span class="p">.</span><span class="nx">isUndefined</span><span class="p">(</span> <span class="nx">override</span> <span class="p">))</span> <span class="p">{</span>
</pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>Retrieve bundle response from Redis</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">client</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">'bid'</span><span class="o">+</span><span class="nx">bid</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span> <span class="nx">err</span><span class="p">,</span> <span class="nx">doc</span> <span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span> <span class="nx">err</span> <span class="o">||</span> <span class="nx">doc</span> <span class="o">===</span> <span class="kc">null</span> <span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>There was an error so force refresh on bundle</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">exports</span><span class="p">.</span><span class="nx">fulfill</span><span class="p">(</span> <span class="nx">myRes</span><span class="p">,</span> <span class="nx">bid</span><span class="p">,</span> <span class="nx">bundle</span><span class="p">,</span> <span class="nx">callback</span><span class="p">,</span> <span class="kc">true</span> <span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">doc</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span> <span class="nx">doc</span> <span class="p">);</span>
</pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">¶</a> </div> <p>If there is a valid expiration date for the bundle</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">doc</span><span class="p">.</span><span class="nx">expires</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="nx">doc</span><span class="p">.</span><span class="nx">expires</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span> <span class="s1">'expires'</span> <span class="k">in</span> <span class="nx">doc</span> <span class="o">&&</span> <span class="nx">_</span><span class="p">.</span><span class="nx">isDate</span><span class="p">(</span><span class="nx">doc</span><span class="p">.</span><span class="nx">expires</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span>
<span class="nx">doc</span><span class="p">.</span><span class="nx">secleft</span> <span class="o">=</span> <span class="nx">doc</span><span class="p">.</span><span class="nx">expires</span><span class="p">.</span><span class="nx">getSecondsBetween</span><span class="p">(</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">()</span> <span class="p">)</span> <span class="o">*</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">¶</a> </div> <p>This should never happen</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">doc</span><span class="p">.</span><span class="nx">secleft</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">Number</span><span class="p">(</span><span class="nx">doc</span><span class="p">.</span><span class="nx">secleft</span><span class="p">)</span> <span class="o"><</span> <span class="mi">0</span> <span class="p">)</span> <span class="p">{</span>
</pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">¶</a> </div> <p>The bundle has expired. Force a refresh</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">exports</span><span class="p">.</span><span class="nx">fulfill</span><span class="p">(</span> <span class="nx">myRes</span><span class="p">,</span> <span class="nx">bid</span><span class="p">,</span> <span class="nx">bundle</span><span class="p">,</span> <span class="nx">callback</span><span class="p">,</span> <span class="kc">true</span> <span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">¶</a> </div> <p>Respond with the cached data</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">doc</span><span class="p">.</span><span class="nx">fromcache</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">responseType</span> <span class="o">=</span> <span class="nx">callback</span> <span class="o">?</span> <span class="s1">'application/javascript'</span> <span class="o">:</span> <span class="s1">'application/json'</span><span class="p">;</span>
<span class="nx">myRes</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="p">{</span><span class="s1">'Content-Type'</span><span class="o">:</span> <span class="nx">responseType</span><span class="p">,</span> <span class="s1">'max-age'</span><span class="o">:</span> <span class="nx">doc</span><span class="p">.</span><span class="nx">secleft</span><span class="p">,</span> <span class="s1">'cache-control'</span><span class="o">:</span> <span class="s1">'public, max-age='</span><span class="o">+</span><span class="nx">doc</span><span class="p">.</span><span class="nx">secleft</span><span class="o">+</span><span class="s1">', no-transform'</span><span class="p">,</span> <span class="s2">"Expires"</span><span class="o">:</span> <span class="nx">doc</span><span class="p">.</span><span class="nx">expires</span> <span class="p">});</span>
</pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">¶</a> </div> <p>If a callback name was passed, use it. Otherwise, just output the object</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">tbuf</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Buffer</span><span class="p">(</span> <span class="p">(</span> <span class="o">!</span><span class="nx">callback</span> <span class="p">)</span> <span class="o">?</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span> <span class="nx">doc</span> <span class="p">)</span> <span class="o">:</span> <span class="nx">callback</span> <span class="o">+</span> <span class="s1">'('</span> <span class="o">+</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span> <span class="nx">doc</span> <span class="p">)</span> <span class="o">+</span> <span class="s1">');'</span> <span class="p">);</span>
<span class="nx">myRes</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="nx">tbuf</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">¶</a> </div> <h3>Override was passed so wew ar eforcing a refresh</h3> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">manager</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">neuron</span><span class="p">.</span><span class="nx">JobManager</span><span class="p">();</span>
<span class="nx">manager</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'empty'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">job</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">job</span><span class="p">.</span><span class="nx">name</span> <span class="o">===</span> <span class="s1">'finishRequest'</span> <span class="o">&&</span> <span class="nx">queriesInThisBundle</span> <span class="o">===</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">done</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="nx">_</span><span class="p">.</span><span class="nx">each</span><span class="p">(</span><span class="nx">manager</span><span class="p">.</span><span class="nx">job</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">job</span><span class="p">,</span> <span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">size</span><span class="p">(</span><span class="nx">job</span><span class="p">.</span><span class="nx">waiting</span><span class="p">)</span> <span class="o">!==</span> <span class="mi">0</span> <span class="o">||</span> <span class="nx">_</span><span class="p">.</span><span class="nx">size</span><span class="p">(</span><span class="nx">job</span><span class="p">.</span><span class="nx">running</span><span class="p">)</span> <span class="o">!==</span> <span class="mi">0</span> <span class="o">||</span> <span class="nx">job</span><span class="p">.</span><span class="nx">queue</span><span class="p">.</span><span class="nx">length</span> <span class="o">!==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">done</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">done</span><span class="p">)</span> <span class="nx">manager</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">(</span><span class="s1">'sendResponse'</span><span class="p">,</span> <span class="nx">bid</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="nx">manager</span><span class="p">.</span><span class="nx">addJob</span><span class="p">(</span><span class="s1">'fulfillPart'</span><span class="p">,</span> <span class="p">{</span>
<span class="nx">work</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">api</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">override</span><span class="p">,</span> <span class="nx">cachedPart</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span> <span class="nx">_</span><span class="p">.</span><span class="nx">isUndefined</span><span class="p">(</span> <span class="nx">override</span> <span class="p">)</span> <span class="p">)</span> <span class="p">{</span>
</pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">¶</a> </div> <p>Load the cached api response from Redis</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">client</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">bid</span><span class="o">+</span><span class="nx">key</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">doc</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span> <span class="o">||</span> <span class="nx">doc</span> <span class="o">===</span> <span class="kc">null</span><span class="p">){</span>
<span class="nx">self</span><span class="p">.</span><span class="nx">finished</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="nx">manager</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">(</span><span class="s1">'fulfillPart'</span><span class="p">,</span> <span class="nx">api</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="kc">true</span> <span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">doc</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span> <span class="nx">doc</span> <span class="p">);</span>
<span class="nx">doc</span><span class="p">.</span><span class="nx">expires</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="nx">doc</span><span class="p">.</span><span class="nx">expires</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span> <span class="p">(</span><span class="s1">'expires'</span> <span class="k">in</span> <span class="nx">doc</span><span class="p">)</span> <span class="o">&&</span> <span class="nx">_</span><span class="p">.</span><span class="nx">isDate</span><span class="p">(</span><span class="nx">doc</span><span class="p">.</span><span class="nx">expires</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">secleft</span> <span class="o">=</span> <span class="nx">doc</span><span class="p">.</span><span class="nx">expires</span><span class="p">.</span><span class="nx">getSecondsBetween</span><span class="p">(</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">()</span> <span class="p">)</span> <span class="o">*</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">secleft</span> <span class="o"><</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">self</span><span class="p">.</span><span class="nx">finished</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="nx">manager</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">(</span><span class="s1">'fulfillPart'</span><span class="p">,</span> <span class="nx">api</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">doc</span> <span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">doc</span><span class="p">.</span><span class="nx">fromcache</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="nx">manager</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">(</span><span class="s1">'finishRequest'</span><span class="p">,</span> <span class="nx">doc</span> <span class="p">);</span>
<span class="nx">self</span><span class="p">.</span><span class="nx">finished</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span> <span class="nx">api</span><span class="p">,</span> <span class="s1">'auth'</span><span class="p">))</span> <span class="p">{</span> </pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">¶</a> </div> <p>If the API request object has an auth scheme defined</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">api</span><span class="p">.</span><span class="nx">auth</span><span class="p">.</span><span class="nx">type</span><span class="p">.</span><span class="nx">authorize</span> <span class="p">(</span><span class="nx">api</span><span class="p">,</span> <span class="nx">bid</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span> <span class="nx">result</span> <span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">result</span> <span class="o">===</span> <span class="kc">true</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">manager</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">(</span><span class="s1">'startRequest'</span><span class="p">,</span> <span class="nx">api</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">cachedPart</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">manager</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">(</span><span class="s1">'finishRequest'</span><span class="p">,</span> <span class="nx">result</span> <span class="p">);</span>
<span class="p">}</span>
<span class="nx">self</span><span class="p">.</span><span class="nx">finished</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">});</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">¶</a> </div> <p>Authentication is not needed</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">self</span><span class="p">.</span><span class="nx">finished</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="nx">manager</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">(</span><span class="s1">'startRequest'</span><span class="p">,</span> <span class="nx">api</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">cachedPart</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="nx">manager</span><span class="p">.</span><span class="nx">addJob</span><span class="p">(</span><span class="s1">'startRequest'</span><span class="p">,</span> <span class="p">{</span>
<span class="nx">work</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span> <span class="nx">api</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">cachedPart</span> <span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span> <span class="nx">api</span><span class="p">,</span> <span class="s1">'timeout'</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">self</span><span class="p">.</span><span class="nx">timeout</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">self</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">manager</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">(</span><span class="s1">'finishRequest'</span><span class="p">,</span> <span class="nx">cachedPart</span> <span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">cachedPart</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">cachedPart</span><span class="p">.</span><span class="nx">timeout</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="nx">cachedPart</span><span class="p">.</span><span class="nx">fromcache</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">};</span>
<span class="nx">self</span><span class="p">.</span><span class="nx">finished</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">},</span> <span class="nx">api</span><span class="p">.</span><span class="nx">timeout</span><span class="p">,</span> <span class="nx">self</span><span class="p">)</span>
<span class="p">}</span>
<span class="nx">api</span><span class="p">.</span><span class="nx">resource</span><span class="p">(</span> <span class="nx">api</span><span class="p">.</span><span class="nx">params</span><span class="p">,</span> <span class="nx">api</span><span class="p">.</span><span class="nx">credentials</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span> <span class="nx">err</span><span class="p">,</span> <span class="nx">res</span> <span class="p">)</span> <span class="p">{</span>
<span class="nx">clearTimeout</span><span class="p">(</span><span class="nx">self</span><span class="p">.</span><span class="nx">timeout</span><span class="p">)</span>
<span class="k">delete</span> <span class="nx">self</span><span class="p">.</span><span class="nx">timeout</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span> <span class="nx">err</span> <span class="p">)</span> <span class="p">{</span>
<span class="nx">api</span><span class="p">.</span><span class="nx">expires</span> <span class="o">=</span> <span class="p">(</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">()</span> <span class="p">);</span>
<span class="nx">tout</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">isUndefined</span><span class="p">(</span><span class="nx">cachedPart</span><span class="p">)</span> <span class="o">?</span> <span class="p">{}</span> <span class="o">:</span> <span class="nx">cachedPart</span><span class="p">;</span>
<span class="nx">tout</span><span class="p">.</span><span class="nx">cname</span> <span class="o">=</span> <span class="nx">key</span><span class="p">;</span>
<span class="nx">tout</span><span class="p">.</span><span class="nx">expires</span> <span class="o">=</span> <span class="nx">api</span><span class="p">.</span><span class="nx">expires</span><span class="p">;</span>
<span class="nx">tout</span><span class="p">.</span><span class="nx">fromcache</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="nx">tout</span><span class="p">.</span><span class="nx">err</span> <span class="o">=</span> <span class="nx">err</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-31">¶</a> </div> <p>Filter the response</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">api</span><span class="p">,</span> <span class="s1">'filter'</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">filter</span> <span class="p">(</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">api</span><span class="p">.</span><span class="nx">filter</span> <span class="p">);</span>
<span class="p">}</span>
</pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-32">¶</a> </div> <p>Perform cleanup function on API response</p> </td> <td class="