rschmukler/agenda

View on GitHub
docs/agenda/6.x/index.html

Summary

Maintainability
Test Coverage
<!DOCTYPE html><html class="default"><head><meta charSet="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>@hokify/agenda</title><meta name="description" content="Documentation for @hokify/agenda"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="assets/style.css"/><link rel="stylesheet" href="assets/highlight.css"/><script async src="assets/search.js" id="search-script"></script></head><body><script>document.body.classList.add(localStorage.getItem("tsd-theme") || "os")</script><header><div class="tsd-page-toolbar"><div class="container"><div class="table-wrap"><div class="table-cell" id="tsd-search" data-base="."><div class="field"><label for="tsd-search-field" class="tsd-widget search no-caption">Search</label><input type="text" id="tsd-search-field"/></div><ul class="results"><li class="state loading">Preparing search index...</li><li class="state failure">The search index is not available</li></ul><a href="index.html" class="title">@hokify/agenda</a></div><div class="table-cell" id="tsd-widgets"><div id="tsd-filter"><a href="#" class="tsd-widget options no-caption" data-toggle="options">Options</a><div class="tsd-filter-group"><div class="tsd-select" id="tsd-filter-visibility"><span class="tsd-select-label">All</span><ul class="tsd-select-list"><li data-value="public">Public</li><li data-value="protected">Public/Protected</li><li data-value="private" class="selected">All</li></ul></div> <input type="checkbox" id="tsd-filter-inherited" checked/><label class="tsd-widget" for="tsd-filter-inherited">Inherited</label><input type="checkbox" id="tsd-filter-externals" checked/><label class="tsd-widget" for="tsd-filter-externals">Externals</label></div></div><a href="#" class="tsd-widget menu no-caption" data-toggle="menu">Menu</a></div></div></div></div><div class="tsd-page-title"><div class="container"><h1>@hokify/agenda</h1></div></div></header><div class="container container-main"><div class="row"><div class="col-8 col-content"><div class="tsd-panel tsd-typography">
<a href="#agendats" id="agendats" style="color: inherit; text-decoration: none;">
  <h1>AgendaTS</h1>
</a>
<p>(full typed version of agendaJS)</p>
<p align="center">
  <img src="https://cdn.jsdelivr.net/gh/hokify/agenda@master/agendats.png" alt="Agenda TS" width="100" height="100">
</p>
<p align="center">
  A light-weight job scheduling library for Node.js
</p>

<p>This was originally a fork of agenda.js,
it differs from the original version in following points:</p>
<ul>
<li>Complete rewrite in Typescript (fully typed!)</li>
<li>mongodb4 driver (supports mongodb 5.x)</li>
<li>Supports mongoDB sharding by name</li>
<li>touch() can have an optional progress parameter (0-100)</li>
<li>Bugfixes and improvements for locking &amp; job processing (concurrency, lockLimit,..)</li>
<li>Breaking change: define() config paramter moved from 2nd position to 3rd</li>
<li>getRunningStats()</li>
<li>automatically waits for agenda to be connected before calling any database operations</li>
<li>uses a database abstraction layer behind the scene</li>
<li>does not create a database index by default, you can set <code>ensureIndex: true</code> when initializing Agenda
or run manually:<pre><code><span class="hl-0">db</span><span class="hl-1">.</span><span class="hl-0">agendaJobs</span><span class="hl-1">.</span><span class="hl-2">ensureIndex</span><span class="hl-1">({</span><br/><span class="hl-1">  </span><span class="hl-3">&quot;name&quot;</span><span class="hl-0"> :</span><span class="hl-1"> </span><span class="hl-4">1</span><span class="hl-1">,</span><br/><span class="hl-1">  </span><span class="hl-3">&quot;nextRunAt&quot;</span><span class="hl-0"> :</span><span class="hl-1"> </span><span class="hl-4">1</span><span class="hl-1">,</span><br/><span class="hl-1">  </span><span class="hl-3">&quot;priority&quot;</span><span class="hl-0"> :</span><span class="hl-1"> -</span><span class="hl-4">1</span><span class="hl-1">,</span><br/><span class="hl-1">  </span><span class="hl-3">&quot;lockedAt&quot;</span><span class="hl-0"> :</span><span class="hl-1"> </span><span class="hl-4">1</span><span class="hl-1">,</span><br/><span class="hl-1">  </span><span class="hl-3">&quot;disabled&quot;</span><span class="hl-0"> :</span><span class="hl-1"> </span><span class="hl-4">1</span><br/><span class="hl-1">}, </span><span class="hl-3">&quot;findAndLockNextJobIndex&quot;</span><span class="hl-1">)</span>
</code></pre>
</li>
</ul>

<a href="#agenda-offers" id="agenda-offers" style="color: inherit; text-decoration: none;">
  <h1>Agenda offers</h1>
</a>
<ul>
<li>Minimal overhead. Agenda aims to keep its code base small.</li>
<li>Mongo backed persistence layer.</li>
<li>Promises based API.</li>
<li>Scheduling with configurable priority, concurrency, and repeating.</li>
<li>Scheduling via cron or human readable syntax.</li>
<li>Event backed job queue that you can hook into.</li>
<li><a href="https://github.com/agenda/agendash">Agendash</a>: optional standalone web-interface.</li>
<li><a href="https://github.com/agenda/agenda-rest">Agenda-rest</a>: optional standalone REST API.</li>
<li><a href="https://github.com/lautarobock/inversify-agenda">inversify-agenda</a> - Some utilities for the development of agenda workers with Inversify</li>
</ul>

<a href="#feature-comparison" id="feature-comparison" style="color: inherit; text-decoration: none;">
  <h3>Feature Comparison</h3>
</a>
<p>Since there are a few job queue solutions, here a table comparing them to help you use the one that
better suits your needs.</p>
<table>
<thead>
<tr>
<th align="left">Feature</th>
<th align="center">Bull</th>
<th align="center">Bee</th>
<th align="center">Agenda</th>
<th align="center">AgendaTS</th>
</tr>
</thead>
<tbody><tr>
<td align="left">Backend</td>
<td align="center">redis</td>
<td align="center">redis</td>
<td align="center">mongo</td>
<td align="center">mongo</td>
</tr>
<tr>
<td align="left">Priorities</td>
<td align="center">✓</td>
<td align="center"></td>
<td align="center">✓</td>
<td align="center">✓</td>
</tr>
<tr>
<td align="left">Concurrency</td>
<td align="center">✓</td>
<td align="center">✓</td>
<td align="center">✓</td>
<td align="center">✓</td>
</tr>
<tr>
<td align="left">Delayed jobs</td>
<td align="center">✓</td>
<td align="center"></td>
<td align="center">✓</td>
<td align="center">✓</td>
</tr>
<tr>
<td align="left">Global events</td>
<td align="center">✓</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left">Rate Limiter</td>
<td align="center">✓</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left">Pause/Resume</td>
<td align="center">✓</td>
<td align="center"></td>
<td align="center"></td>
<td align="center">~</td>
</tr>
<tr>
<td align="left">Sandboxed worker</td>
<td align="center">✓</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left">Repeatable jobs</td>
<td align="center">✓</td>
<td align="center"></td>
<td align="center">✓</td>
<td align="center">✓</td>
</tr>
<tr>
<td align="left">Atomic ops</td>
<td align="center">✓</td>
<td align="center">✓</td>
<td align="center"></td>
<td align="center">~</td>
</tr>
<tr>
<td align="left">Persistence</td>
<td align="center">✓</td>
<td align="center">✓</td>
<td align="center">✓</td>
<td align="center">✓</td>
</tr>
<tr>
<td align="left">UI</td>
<td align="center">✓</td>
<td align="center"></td>
<td align="center">✓</td>
<td align="center">✓</td>
</tr>
<tr>
<td align="left">REST API</td>
<td align="center"></td>
<td align="center"></td>
<td align="center">✓</td>
<td align="center">✓</td>
</tr>
<tr>
<td align="left">Optimized for</td>
<td align="center">Jobs / Messages</td>
<td align="center">Messages</td>
<td align="center">Jobs</td>
<td align="center">Jobs</td>
</tr>
</tbody></table>
<p><em>Kudos for making the comparison chart goes to <a href="https://www.npmjs.com/package/bull#feature-comparison">Bull</a> maintainers.</em></p>

<a href="#installation" id="installation" style="color: inherit; text-decoration: none;">
  <h1>Installation</h1>
</a>
<p>Install via NPM</p>
<pre><code><span class="hl-0">npm</span><span class="hl-1"> </span><span class="hl-0">install</span><span class="hl-1"> @</span><span class="hl-0">hokify</span><span class="hl-1">/</span><span class="hl-0">agenda</span>
</code></pre>
<p>You will also need a working <a href="https://www.mongodb.com/">Mongo</a> database (v4+) to point it to.</p>

<a href="#example-usage" id="example-usage" style="color: inherit; text-decoration: none;">
  <h1>Example Usage</h1>
</a>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">mongoConnectionString</span><span class="hl-1"> = </span><span class="hl-3">&#39;mongodb://127.0.0.1/agenda&#39;</span><span class="hl-1">;</span><br/><br/><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">agenda</span><span class="hl-1"> = </span><span class="hl-5">new</span><span class="hl-1"> </span><span class="hl-2">Agenda</span><span class="hl-1">({</span><span class="hl-0">db:</span><span class="hl-1"> {</span><span class="hl-0">address:</span><span class="hl-1"> </span><span class="hl-0">mongoConnectionString</span><span class="hl-1">}});</span><br/><br/><span class="hl-7">// Or override the default collection name:</span><br/><span class="hl-7">// const agenda = new Agenda({db: {address: mongoConnectionString, collection: &#39;jobCollectionName&#39;}});</span><br/><br/><span class="hl-7">// or pass additional connection options:</span><br/><span class="hl-7">// const agenda = new Agenda({db: {address: mongoConnectionString, collection: &#39;jobCollectionName&#39;, options: {ssl: true}}});</span><br/><br/><span class="hl-7">// or pass in an existing mongodb-native MongoClient instance</span><br/><span class="hl-7">// const agenda = new Agenda({mongo: myMongoClient});</span><br/><br/><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">define</span><span class="hl-1">(</span><span class="hl-3">&#39;delete old users&#39;</span><span class="hl-1">, </span><span class="hl-5">async</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1"> </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">User</span><span class="hl-1">.</span><span class="hl-2">remove</span><span class="hl-1">({</span><span class="hl-0">lastLogIn:</span><span class="hl-1"> {</span><span class="hl-0">$lt:</span><span class="hl-1"> </span><span class="hl-0">twoDaysAgo</span><span class="hl-1">}});</span><br/><span class="hl-1">});</span><br/><br/><span class="hl-1">(</span><span class="hl-5">async</span><span class="hl-1"> </span><span class="hl-5">function</span><span class="hl-1">() { </span><span class="hl-7">// IIFE to give access to async/await</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">start</span><span class="hl-1">();</span><br/><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">every</span><span class="hl-1">(</span><span class="hl-3">&#39;3 minutes&#39;</span><span class="hl-1">, </span><span class="hl-3">&#39;delete old users&#39;</span><span class="hl-1">);</span><br/><br/><span class="hl-1">  </span><span class="hl-7">// Alternatively, you could also do:</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">every</span><span class="hl-1">(</span><span class="hl-3">&#39;*/3 * * * *&#39;</span><span class="hl-1">, </span><span class="hl-3">&#39;delete old users&#39;</span><span class="hl-1">);</span><br/><span class="hl-1">})();</span>
</code></pre>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">define</span><span class="hl-1">(</span><span class="hl-3">&#39;send email report&#39;</span><span class="hl-1">, </span><span class="hl-5">async</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1"> </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-5">const</span><span class="hl-1"> {</span><span class="hl-6">to</span><span class="hl-1">} = </span><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-0">attrs</span><span class="hl-1">.</span><span class="hl-0">data</span><span class="hl-1">;</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">emailClient</span><span class="hl-1">.</span><span class="hl-2">send</span><span class="hl-1">({</span><br/><span class="hl-1">    </span><span class="hl-0">to</span><span class="hl-1">,</span><br/><span class="hl-1">    </span><span class="hl-0">from:</span><span class="hl-1"> </span><span class="hl-3">&#39;example@example.com&#39;</span><span class="hl-1">,</span><br/><span class="hl-1">    </span><span class="hl-0">subject:</span><span class="hl-1"> </span><span class="hl-3">&#39;Email Report&#39;</span><span class="hl-1">,</span><br/><span class="hl-1">    </span><span class="hl-0">body:</span><span class="hl-1"> </span><span class="hl-3">&#39;...&#39;</span><br/><span class="hl-1">  });</span><br/><span class="hl-1">}, {</span><span class="hl-0">priority:</span><span class="hl-1"> </span><span class="hl-3">&#39;high&#39;</span><span class="hl-1">, </span><span class="hl-0">concurrency:</span><span class="hl-1"> </span><span class="hl-4">10</span><span class="hl-1">}, );</span><br/><br/><span class="hl-1">(</span><span class="hl-5">async</span><span class="hl-1"> </span><span class="hl-5">function</span><span class="hl-1">() {</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">start</span><span class="hl-1">();</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">schedule</span><span class="hl-1">(</span><span class="hl-3">&#39;in 20 minutes&#39;</span><span class="hl-1">, </span><span class="hl-3">&#39;send email report&#39;</span><span class="hl-1">, {</span><span class="hl-0">to:</span><span class="hl-1"> </span><span class="hl-3">&#39;admin@example.com&#39;</span><span class="hl-1">});</span><br/><span class="hl-1">})();</span>
</code></pre>
<pre><code class="language-js"><span class="hl-1">(</span><span class="hl-5">async</span><span class="hl-1"> </span><span class="hl-5">function</span><span class="hl-1">() {</span><br/><span class="hl-1">  </span><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">weeklyReport</span><span class="hl-1"> = </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">create</span><span class="hl-1">(</span><span class="hl-3">&#39;send email report&#39;</span><span class="hl-1">, {</span><span class="hl-0">to:</span><span class="hl-1"> </span><span class="hl-3">&#39;example@example.com&#39;</span><span class="hl-1">});</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">start</span><span class="hl-1">();</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">weeklyReport</span><span class="hl-1">.</span><span class="hl-2">repeatEvery</span><span class="hl-1">(</span><span class="hl-3">&#39;1 week&#39;</span><span class="hl-1">).</span><span class="hl-2">save</span><span class="hl-1">();</span><br/><span class="hl-1">})();</span>
</code></pre>

<a href="#full-documentation" id="full-documentation" style="color: inherit; text-decoration: none;">
  <h1>Full documentation</h1>
</a>
<p>See also <a href="https://hokify.github.io/agenda/">https://hokify.github.io/agenda/</a></p>
<p>Agenda&#39;s basic control structure is an instance of an agenda. Agenda&#39;s are
mapped to a database collection and load the jobs from within.</p>

<a href="#table-of-contents" id="table-of-contents" style="color: inherit; text-decoration: none;">
  <h2>Table of Contents</h2>
</a>
<ul>
<li><a href="#configuring-an-agenda">Configuring an agenda</a></li>
<li><a href="#agenda-events">Agenda Events</a></li>
<li><a href="#defining-job-processors">Defining job processors</a></li>
<li><a href="#creating-jobs">Creating jobs</a></li>
<li><a href="#managing-jobs">Managing jobs</a></li>
<li><a href="#starting-the-job-processor">Starting the job processor</a></li>
<li><a href="#multiple-job-processors">Multiple job processors</a></li>
<li><a href="#manually-working-with-a-job">Manually working with jobs</a></li>
<li><a href="#job-queue-events">Job Queue Events</a></li>
<li><a href="#frequently-asked-questions">Frequently asked questions</a></li>
<li><a href="#example-project-structure">Example Project structure</a></li>
<li><a href="#known-issues">Known Issues</a></li>
<li><a href="#debugging-issues">Debugging Issues</a></li>
<li><a href="#acknowledgements">Acknowledgements</a></li>
</ul>

<a href="#configuring-an-agenda" id="configuring-an-agenda" style="color: inherit; text-decoration: none;">
  <h2>Configuring an agenda</h2>
</a>
<p>All configuration methods are chainable, meaning you can do something like:</p>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">agenda</span><span class="hl-1"> = </span><span class="hl-5">new</span><span class="hl-1"> </span><span class="hl-2">Agenda</span><span class="hl-1">();</span><br/><span class="hl-0">agenda</span><br/><span class="hl-1">  .</span><span class="hl-2">database</span><span class="hl-1">(...)</span><br/><span class="hl-1">  .</span><span class="hl-2">processEvery</span><span class="hl-1">(</span><span class="hl-3">&#39;3 minutes&#39;</span><span class="hl-1">)</span><br/><span class="hl-1">  ...;</span>
</code></pre>
<p>Possible agenda config options:</p>
<pre><code class="language-ts"><span class="hl-1">{</span><br/><span class="hl-1">    </span><span class="hl-9">name</span><span class="hl-1">: </span><span class="hl-0">string</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-9">defaultConcurrency</span><span class="hl-1">: </span><span class="hl-0">number</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-9">processEvery</span><span class="hl-1">: </span><span class="hl-0">number</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-9">maxConcurrency</span><span class="hl-1">: </span><span class="hl-0">number</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-9">defaultLockLimit</span><span class="hl-1">: </span><span class="hl-0">number</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-9">lockLimit</span><span class="hl-1">: </span><span class="hl-0">number</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-9">defaultLockLifetime</span><span class="hl-1">: </span><span class="hl-0">number</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-9">ensureIndex</span><span class="hl-1">: </span><span class="hl-0">boolean</span><span class="hl-1">;</span><br/><span class="hl-1">    </span><span class="hl-9">sort</span><span class="hl-1">: </span><span class="hl-0">SortOptionObject</span><span class="hl-1">&lt;</span><span class="hl-0">IJobParameters</span><span class="hl-1">&gt;;</span><br/><span class="hl-1">    </span><span class="hl-9">db</span><span class="hl-1">: {</span><br/><span class="hl-1">        </span><span class="hl-9">collection</span><span class="hl-1">: </span><span class="hl-0">string</span><span class="hl-1">;</span><br/><span class="hl-1">        </span><span class="hl-9">address</span><span class="hl-1">: </span><span class="hl-0">string</span><span class="hl-1">;</span><br/><span class="hl-1">        </span><span class="hl-9">options</span><span class="hl-1">: </span><span class="hl-0">MongoClientOptions</span><span class="hl-1">;</span><br/><span class="hl-1">    };</span><br/><span class="hl-1">    </span><span class="hl-9">mongo</span><span class="hl-1">: </span><span class="hl-0">Db</span><span class="hl-1">;</span><br/><span class="hl-1">}</span>
</code></pre>
<p>Agenda uses <a href="http://github.com/rschmukler/human-interval">Human Interval</a> for specifying the intervals. It supports the following units:</p>
<p><code>seconds</code>, <code>minutes</code>, <code>hours</code>, <code>days</code>,<code>weeks</code>, <code>months</code> -- assumes 30 days, <code>years</code> -- assumes 365 days</p>
<p>More sophisticated examples</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">processEvery</span><span class="hl-1">(</span><span class="hl-3">&#39;one minute&#39;</span><span class="hl-1">);</span><br/><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">processEvery</span><span class="hl-1">(</span><span class="hl-3">&#39;1.5 minutes&#39;</span><span class="hl-1">);</span><br/><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">processEvery</span><span class="hl-1">(</span><span class="hl-3">&#39;3 days and 4 hours&#39;</span><span class="hl-1">);</span><br/><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">processEvery</span><span class="hl-1">(</span><span class="hl-3">&#39;3 days, 4 hours and 36 seconds&#39;</span><span class="hl-1">);</span>
</code></pre>

<a href="#databaseurl-collectionname-mongoclientoptions" id="databaseurl-collectionname-mongoclientoptions" style="color: inherit; text-decoration: none;">
  <h3>database(url, [collectionName], [MongoClientOptions])</h3>
</a>
<p>Specifies the database at the <code>url</code> specified. If no collection name is given,
<code>agendaJobs</code> is used.</p>
<p>By default <code>useNewUrlParser</code> and <code>useUnifiedTopology</code> is set to <code>true</code>,</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">database</span><span class="hl-1">(</span><span class="hl-3">&#39;localhost:27017/agenda-test&#39;</span><span class="hl-1">, </span><span class="hl-3">&#39;agendaJobs&#39;</span><span class="hl-1">);</span>
</code></pre>
<p>You can also specify it during instantiation.</p>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">agenda</span><span class="hl-1"> = </span><span class="hl-5">new</span><span class="hl-1"> </span><span class="hl-2">Agenda</span><span class="hl-1">({</span><span class="hl-0">db:</span><span class="hl-1"> {</span><span class="hl-0">address:</span><span class="hl-1"> </span><span class="hl-3">&#39;localhost:27017/agenda-test&#39;</span><span class="hl-1">, </span><span class="hl-0">collection:</span><span class="hl-1"> </span><span class="hl-3">&#39;agendaJobs&#39;</span><span class="hl-1">}});</span>
</code></pre>
<p>Agenda will emit a <code>ready</code> event (see <a href="#agenda-events">Agenda Events</a>) when properly connected to the database.
It is safe to call <code>agenda.start()</code> without waiting for this event, as this is handled internally.
If you&#39;re using the <code>db</code> options, or call <code>database</code>, then you may still need to listen for <code>ready</code> before saving jobs.</p>

<a href="#mongodbinstance-collectionname" id="mongodbinstance-collectionname" style="color: inherit; text-decoration: none;">
  <h3>mongo(dbInstance, [collectionName])</h3>
</a>
<p>Use an existing mongodb-native MongoClient/Db instance. This can help consolidate connections to a
database. You can instead use <code>.database</code> to have agenda handle connecting for you.</p>
<p>You can also specify it during instantiation:</p>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">agenda</span><span class="hl-1"> = </span><span class="hl-5">new</span><span class="hl-1"> </span><span class="hl-2">Agenda</span><span class="hl-1">({</span><span class="hl-0">mongo:</span><span class="hl-1"> </span><span class="hl-0">mongoClientInstance</span><span class="hl-1">.</span><span class="hl-2">db</span><span class="hl-1">(</span><span class="hl-3">&#39;agenda-test&#39;</span><span class="hl-1">)});</span>
</code></pre>
<p>Note that MongoClient.connect() returns a mongoClientInstance since <a href="https://github.com/mongodb/node-mongodb-native/blob/master/CHANGES_3.0.0.md">node-mongodb-native 3.0.0</a>, while it used to return a dbInstance that could then be directly passed to agenda.</p>

<a href="#namename" id="namename" style="color: inherit; text-decoration: none;">
  <h3>name(name)</h3>
</a>
<p>Takes a string <code>name</code> and sets <code>lastModifiedBy</code> to it in the job database.
Useful for if you have multiple job processors (agendas) and want to see which
job queue last ran the job.</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">name</span><span class="hl-1">(</span><span class="hl-0">os</span><span class="hl-1">.</span><span class="hl-0">hostname</span><span class="hl-1"> + </span><span class="hl-3">&#39;-&#39;</span><span class="hl-1"> + </span><span class="hl-0">process</span><span class="hl-1">.</span><span class="hl-0">pid</span><span class="hl-1">);</span>
</code></pre>
<p>You can also specify it during instantiation</p>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">agenda</span><span class="hl-1"> = </span><span class="hl-5">new</span><span class="hl-1"> </span><span class="hl-2">Agenda</span><span class="hl-1">({</span><span class="hl-0">name:</span><span class="hl-1"> </span><span class="hl-3">&#39;test queue&#39;</span><span class="hl-1">});</span>
</code></pre>

<a href="#processeveryinterval" id="processeveryinterval" style="color: inherit; text-decoration: none;">
  <h3>processEvery(interval)</h3>
</a>
<p>Takes a string <code>interval</code> which can be either a traditional javascript number,
or a string such as <code>3 minutes</code></p>
<p>Specifies the frequency at which agenda will query the database looking for jobs
that need to be processed. Agenda internally uses <code>setTimeout</code> to guarantee that
jobs run at (close to ~3ms) the right time.</p>
<p>Decreasing the frequency will result in fewer database queries, but more jobs
being stored in memory.</p>
<p>Also worth noting is that if the job queue is shutdown, any jobs stored in memory
that haven&#39;t run will still be locked, meaning that you may have to wait for the
lock to expire. By default it is <code>&#39;5 seconds&#39;</code>.</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">processEvery</span><span class="hl-1">(</span><span class="hl-3">&#39;1 minute&#39;</span><span class="hl-1">);</span>
</code></pre>
<p>You can also specify it during instantiation</p>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">agenda</span><span class="hl-1"> = </span><span class="hl-5">new</span><span class="hl-1"> </span><span class="hl-2">Agenda</span><span class="hl-1">({</span><span class="hl-0">processEvery:</span><span class="hl-1"> </span><span class="hl-3">&#39;30 seconds&#39;</span><span class="hl-1">});</span>
</code></pre>

<a href="#maxconcurrencynumber" id="maxconcurrencynumber" style="color: inherit; text-decoration: none;">
  <h3>maxConcurrency(number)</h3>
</a>
<p>Takes a <code>number</code> which specifies the max number of jobs that can be running at
any given moment. By default it is <code>20</code>.</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">maxConcurrency</span><span class="hl-1">(</span><span class="hl-4">20</span><span class="hl-1">);</span>
</code></pre>
<p>You can also specify it during instantiation</p>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">agenda</span><span class="hl-1"> = </span><span class="hl-5">new</span><span class="hl-1"> </span><span class="hl-2">Agenda</span><span class="hl-1">({</span><span class="hl-0">maxConcurrency:</span><span class="hl-1"> </span><span class="hl-4">20</span><span class="hl-1">});</span>
</code></pre>

<a href="#defaultconcurrencynumber" id="defaultconcurrencynumber" style="color: inherit; text-decoration: none;">
  <h3>defaultConcurrency(number)</h3>
</a>
<p>Takes a <code>number</code> which specifies the default number of a specific job that can be running at
any given moment. By default it is <code>5</code>.</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">defaultConcurrency</span><span class="hl-1">(</span><span class="hl-4">5</span><span class="hl-1">);</span>
</code></pre>
<p>You can also specify it during instantiation</p>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">agenda</span><span class="hl-1"> = </span><span class="hl-5">new</span><span class="hl-1"> </span><span class="hl-2">Agenda</span><span class="hl-1">({</span><span class="hl-0">defaultConcurrency:</span><span class="hl-1"> </span><span class="hl-4">5</span><span class="hl-1">});</span>
</code></pre>

<a href="#locklimitnumber" id="locklimitnumber" style="color: inherit; text-decoration: none;">
  <h3>lockLimit(number)</h3>
</a>
<p>Takes a <code>number</code> which specifies the max number jobs that can be locked at any given moment. By default it is <code>0</code> for no max.</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">lockLimit</span><span class="hl-1">(</span><span class="hl-4">0</span><span class="hl-1">);</span>
</code></pre>
<p>You can also specify it during instantiation</p>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">agenda</span><span class="hl-1"> = </span><span class="hl-5">new</span><span class="hl-1"> </span><span class="hl-2">Agenda</span><span class="hl-1">({</span><span class="hl-0">lockLimit:</span><span class="hl-1"> </span><span class="hl-4">0</span><span class="hl-1">});</span>
</code></pre>

<a href="#defaultlocklimitnumber" id="defaultlocklimitnumber" style="color: inherit; text-decoration: none;">
  <h3>defaultLockLimit(number)</h3>
</a>
<p>Takes a <code>number</code> which specifies the default number of a specific job that can be locked at any given moment. By default it is <code>0</code> for no max.</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">defaultLockLimit</span><span class="hl-1">(</span><span class="hl-4">0</span><span class="hl-1">);</span>
</code></pre>
<p>You can also specify it during instantiation</p>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">agenda</span><span class="hl-1"> = </span><span class="hl-5">new</span><span class="hl-1"> </span><span class="hl-2">Agenda</span><span class="hl-1">({</span><span class="hl-0">defaultLockLimit:</span><span class="hl-1"> </span><span class="hl-4">0</span><span class="hl-1">});</span>
</code></pre>

<a href="#defaultlocklifetimenumber" id="defaultlocklifetimenumber" style="color: inherit; text-decoration: none;">
  <h3>defaultLockLifetime(number)</h3>
</a>
<p>Takes a <code>number</code> which specifies the default lock lifetime in milliseconds. By
default it is 10 minutes. This can be overridden by specifying the
<code>lockLifetime</code> option to a defined job.</p>
<p>A job will unlock if it is finished (ie. the returned Promise resolves/rejects
or <code>done</code> is specified in the params and <code>done()</code> is called) before the
<code>lockLifetime</code>. The lock is useful if the job crashes or times out.</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">defaultLockLifetime</span><span class="hl-1">(</span><span class="hl-4">10000</span><span class="hl-1">);</span>
</code></pre>
<p>You can also specify it during instantiation</p>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">agenda</span><span class="hl-1"> = </span><span class="hl-5">new</span><span class="hl-1"> </span><span class="hl-2">Agenda</span><span class="hl-1">({</span><span class="hl-0">defaultLockLifetime:</span><span class="hl-1"> </span><span class="hl-4">10000</span><span class="hl-1">});</span>
</code></pre>

<a href="#sortquery" id="sortquery" style="color: inherit; text-decoration: none;">
  <h3>sort(query)</h3>
</a>
<p>Takes a <code>query</code> which specifies the sort query to be used for finding and locking the next job.</p>
<p>By default it is <code>{ nextRunAt: 1, priority: -1 }</code>, which obeys a first in first out approach, with respect to priority.</p>

<a href="#agenda-events" id="agenda-events" style="color: inherit; text-decoration: none;">
  <h2>Agenda Events</h2>
</a>
<p>An instance of an agenda will emit the following events:</p>
<ul>
<li><code>ready</code> - called when Agenda mongo connection is successfully opened and indices created.
  If you&#39;re passing agenda an existing connection, you shouldn&#39;t need to listen for this, as <code>agenda.start()</code> will not resolve until indices have been created.
  If you&#39;re using the <code>db</code> options, or call <code>database</code>, then you may still need to listen for the <code>ready</code> event before saving jobs. <code>agenda.start()</code> will still wait for the connection to be opened.</li>
<li><code>error</code> - called when Agenda mongo connection process has thrown an error</li>
</ul>
<pre><code class="language-js"><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">start</span><span class="hl-1">();</span>
</code></pre>

<a href="#defining-job-processors" id="defining-job-processors" style="color: inherit; text-decoration: none;">
  <h2>Defining Job Processors</h2>
</a>
<p>Before you can use a job, you must define its processing behavior.</p>

<a href="#definejobname-fn-options" id="definejobname-fn-options" style="color: inherit; text-decoration: none;">
  <h3>define(jobName, fn, [options])</h3>
</a>
<p>Defines a job with the name of <code>jobName</code>. When a job of <code>jobName</code> gets run, it
will be passed to <code>fn(job, done)</code>. To maintain asynchronous behavior, you may
either provide a Promise-returning function in <code>fn</code> <em>or</em> provide <code>done</code> as a
second parameter to <code>fn</code>. If <code>done</code> is specified in the function signature, you
must call <code>done()</code> when you are processing the job. If your function is
synchronous or returns a Promise, you may omit <code>done</code> from the signature.</p>
<p><code>options</code> is an optional argument which can overwrite the defaults. It can take
the following:</p>
<ul>
<li><code>concurrency</code>: <code>number</code> maximum number of that job that can be running at once (per instance of agenda)</li>
<li><code>lockLimit</code>: <code>number</code> maximum number of that job that can be locked at once (per instance of agenda)</li>
<li><code>lockLifetime</code>: <code>number</code> interval in ms of how long the job stays locked for (see <a href="#multiple-job-processors">multiple job processors</a> for more info).
A job will automatically unlock once a returned promise resolves/rejects (or if <code>done</code> is specified in the signature and <code>done()</code> is called).</li>
<li><code>priority</code>: <code>(lowest|low|normal|high|highest|number)</code> specifies the priority
of the job. Higher priority jobs will run first. See the priority mapping
below</li>
</ul>
<p>Priority mapping:</p>
<pre><code><span class="hl-1">{</span><br/><span class="hl-1">  </span><span class="hl-9">highest</span><span class="hl-1">: </span><span class="hl-4">20</span><span class="hl-1">,</span><br/><span class="hl-1">  </span><span class="hl-9">high</span><span class="hl-1">: </span><span class="hl-4">10</span><span class="hl-1">,</span><br/><span class="hl-1">  </span><span class="hl-9">normal</span><span class="hl-1">: </span><span class="hl-4">0</span><span class="hl-1">,</span><br/><span class="hl-1">  </span><span class="hl-9">low</span><span class="hl-1">: -</span><span class="hl-4">10</span><span class="hl-1">,</span><br/><span class="hl-1">  </span><span class="hl-9">lowest</span><span class="hl-1">: -</span><span class="hl-4">20</span><br/><span class="hl-1">}</span>
</code></pre>
<p>Async Job:</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">define</span><span class="hl-1">(</span><span class="hl-3">&#39;some long running job&#39;</span><span class="hl-1">, </span><span class="hl-5">async</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1"> </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">data</span><span class="hl-1"> = </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-2">doSomelengthyTask</span><span class="hl-1">();</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-2">formatThatData</span><span class="hl-1">(</span><span class="hl-0">data</span><span class="hl-1">);</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-2">sendThatData</span><span class="hl-1">(</span><span class="hl-0">data</span><span class="hl-1">);</span><br/><span class="hl-1">});</span>
</code></pre>
<p>Async Job (using <code>done</code>):</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">define</span><span class="hl-1">(</span><span class="hl-3">&#39;some long running job&#39;</span><span class="hl-1">, (</span><span class="hl-0">job</span><span class="hl-1">, </span><span class="hl-0">done</span><span class="hl-1">) </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-2">doSomelengthyTask</span><span class="hl-1">(</span><span class="hl-0">data</span><span class="hl-1"> </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">    </span><span class="hl-2">formatThatData</span><span class="hl-1">(</span><span class="hl-0">data</span><span class="hl-1">);</span><br/><span class="hl-1">    </span><span class="hl-2">sendThatData</span><span class="hl-1">(</span><span class="hl-0">data</span><span class="hl-1">);</span><br/><span class="hl-1">    </span><span class="hl-2">done</span><span class="hl-1">();</span><br/><span class="hl-1">  });</span><br/><span class="hl-1">});</span>
</code></pre>
<p>Sync Job:</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">define</span><span class="hl-1">(</span><span class="hl-3">&#39;say hello&#39;</span><span class="hl-1">, </span><span class="hl-0">job</span><span class="hl-1"> </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-0">console</span><span class="hl-1">.</span><span class="hl-2">log</span><span class="hl-1">(</span><span class="hl-3">&#39;Hello!&#39;</span><span class="hl-1">);</span><br/><span class="hl-1">});</span>
</code></pre>
<p><code>define()</code> acts like an assignment: if <code>define(jobName, ...)</code> is called multiple times (e.g. every time your script starts), the definition in the last call will overwrite the previous one. Thus, if you <code>define</code> the <code>jobName</code> only once in your code, it&#39;s safe for that call to execute multiple times.</p>

<a href="#creating-jobs" id="creating-jobs" style="color: inherit; text-decoration: none;">
  <h2>Creating Jobs</h2>
</a>

<a href="#everyinterval-name-data-options" id="everyinterval-name-data-options" style="color: inherit; text-decoration: none;">
  <h3>every(interval, name, [data], [options])</h3>
</a>
<p>Runs job <code>name</code> at the given <code>interval</code>. Optionally, data and options can be passed in.
Every creates a job of type <code>single</code>, which means that it will only create one
job in the database, even if that line is run multiple times. This lets you put
it in a file that may get run multiple times, such as <code>webserver.js</code> which may
reboot from time to time.</p>
<p><code>interval</code> can be a human-readable format <code>String</code>, a <a href="https://www.npmjs.com/package/cron-parser">cron format</a> <code>String</code>, or a <code>Number</code>.</p>
<p><code>data</code> is an optional argument that will be passed to the processing function
under <code>job.attrs.data</code>.</p>
<p><code>options</code> is an optional argument that will be passed to <a href="#repeateveryinterval-options"><code>job.repeatEvery</code></a>.
In order to use this argument, <code>data</code> must also be specified.</p>
<p>Returns the <code>job</code>.</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">define</span><span class="hl-1">(</span><span class="hl-3">&#39;printAnalyticsReport&#39;</span><span class="hl-1">, </span><span class="hl-5">async</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1"> </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">users</span><span class="hl-1"> = </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">User</span><span class="hl-1">.</span><span class="hl-2">doSomethingReallyIntensive</span><span class="hl-1">();</span><br/><span class="hl-1">  </span><span class="hl-2">processUserData</span><span class="hl-1">(</span><span class="hl-0">users</span><span class="hl-1">);</span><br/><span class="hl-1">  </span><span class="hl-0">console</span><span class="hl-1">.</span><span class="hl-2">log</span><span class="hl-1">(</span><span class="hl-3">&#39;I print a report!&#39;</span><span class="hl-1">);</span><br/><span class="hl-1">});</span><br/><br/><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">every</span><span class="hl-1">(</span><span class="hl-3">&#39;15 minutes&#39;</span><span class="hl-1">, </span><span class="hl-3">&#39;printAnalyticsReport&#39;</span><span class="hl-1">);</span>
</code></pre>
<p>Optionally, <code>name</code> could be array of job names, which is convenient for scheduling
different jobs for same <code>interval</code>.</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">every</span><span class="hl-1">(</span><span class="hl-3">&#39;15 minutes&#39;</span><span class="hl-1">, [</span><span class="hl-3">&#39;printAnalyticsReport&#39;</span><span class="hl-1">, </span><span class="hl-3">&#39;sendNotifications&#39;</span><span class="hl-1">, </span><span class="hl-3">&#39;updateUserRecords&#39;</span><span class="hl-1">]);</span>
</code></pre>
<p>In this case, <code>every</code> returns array of <code>jobs</code>.</p>

<a href="#schedulewhen-name-data" id="schedulewhen-name-data" style="color: inherit; text-decoration: none;">
  <h3>schedule(when, name, [data])</h3>
</a>
<p>Schedules a job to run <code>name</code> once at a given time. <code>when</code> can be a <code>Date</code> or a
<code>String</code> such as <code>tomorrow at 5pm</code>.</p>
<p><code>data</code> is an optional argument that will be passed to the processing function
under <code>job.attrs.data</code>.</p>
<p>Returns the <code>job</code>.</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">schedule</span><span class="hl-1">(</span><span class="hl-3">&#39;tomorrow at noon&#39;</span><span class="hl-1">, </span><span class="hl-3">&#39;printAnalyticsReport&#39;</span><span class="hl-1">, {</span><span class="hl-0">userCount:</span><span class="hl-1"> </span><span class="hl-4">100</span><span class="hl-1">});</span>
</code></pre>
<p>Optionally, <code>name</code> could be array of job names, similar to the <code>every</code> method.</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">schedule</span><span class="hl-1">(</span><span class="hl-3">&#39;tomorrow at noon&#39;</span><span class="hl-1">, [</span><span class="hl-3">&#39;printAnalyticsReport&#39;</span><span class="hl-1">, </span><span class="hl-3">&#39;sendNotifications&#39;</span><span class="hl-1">, </span><span class="hl-3">&#39;updateUserRecords&#39;</span><span class="hl-1">]);</span>
</code></pre>
<p>In this case, <code>schedule</code> returns array of <code>jobs</code>.</p>

<a href="#nowname-data" id="nowname-data" style="color: inherit; text-decoration: none;">
  <h3>now(name, [data])</h3>
</a>
<p>Schedules a job to run <code>name</code> once immediately.</p>
<p><code>data</code> is an optional argument that will be passed to the processing function
under <code>job.attrs.data</code>.</p>
<p>Returns the <code>job</code>.</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">now</span><span class="hl-1">(</span><span class="hl-3">&#39;do the hokey pokey&#39;</span><span class="hl-1">);</span>
</code></pre>

<a href="#createjobname-data" id="createjobname-data" style="color: inherit; text-decoration: none;">
  <h3>create(jobName, data)</h3>
</a>
<p>Returns an instance of a <code>jobName</code> with <code>data</code>. This does <em>NOT</em> save the job in
the database. See below to learn how to manually work with jobs.</p>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">job</span><span class="hl-1"> = </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">create</span><span class="hl-1">(</span><span class="hl-3">&#39;printAnalyticsReport&#39;</span><span class="hl-1">, {</span><span class="hl-0">userCount:</span><span class="hl-1"> </span><span class="hl-4">100</span><span class="hl-1">});</span><br/><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">save</span><span class="hl-1">();</span><br/><span class="hl-0">console</span><span class="hl-1">.</span><span class="hl-2">log</span><span class="hl-1">(</span><span class="hl-3">&#39;Job successfully saved&#39;</span><span class="hl-1">);</span>
</code></pre>

<a href="#managing-jobs" id="managing-jobs" style="color: inherit; text-decoration: none;">
  <h2>Managing Jobs</h2>
</a>

<a href="#jobsmongodb-native-query-mongodb-native-sort-mongodb-native-limit-mongodb-native-skip" id="jobsmongodb-native-query-mongodb-native-sort-mongodb-native-limit-mongodb-native-skip" style="color: inherit; text-decoration: none;">
  <h3>jobs(mongodb-native query, mongodb-native sort, mongodb-native limit, mongodb-native skip)</h3>
</a>
<p>Lets you query (then sort, limit and skip the result) all of the jobs in the agenda job&#39;s database. These are full <a href="https://github.com/mongodb/node-mongodb-native">mongodb-native</a> <code>find</code>, <code>sort</code>, <code>limit</code> and <code>skip</code> commands. See mongodb-native&#39;s documentation for details.</p>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">jobs</span><span class="hl-1"> = </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">jobs</span><span class="hl-1">({</span><span class="hl-0">name:</span><span class="hl-1"> </span><span class="hl-3">&#39;printAnalyticsReport&#39;</span><span class="hl-1">}, {</span><span class="hl-0">data:</span><span class="hl-1">-</span><span class="hl-4">1</span><span class="hl-1">}, </span><span class="hl-4">3</span><span class="hl-1">, </span><span class="hl-4">1</span><span class="hl-1">);</span><br/><span class="hl-7">// Work with jobs (see below)</span>
</code></pre>

<a href="#cancelmongodb-native-query" id="cancelmongodb-native-query" style="color: inherit; text-decoration: none;">
  <h3>cancel(mongodb-native query)</h3>
</a>
<p>Cancels any jobs matching the passed mongodb-native query, and removes them from the database. Returns a Promise resolving to the number of cancelled jobs, or rejecting on error.</p>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">numRemoved</span><span class="hl-1"> = </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">cancel</span><span class="hl-1">({</span><span class="hl-0">name:</span><span class="hl-1"> </span><span class="hl-3">&#39;printAnalyticsReport&#39;</span><span class="hl-1">});</span>
</code></pre>
<p>This functionality can also be achieved by first retrieving all the jobs from the database using <code>agenda.jobs()</code>, looping through the resulting array and calling <code>job.remove()</code> on each. It is however preferable to use <code>agenda.cancel()</code> for this use case, as this ensures the operation is atomic.</p>

<a href="#purge" id="purge" style="color: inherit; text-decoration: none;">
  <h3>purge()</h3>
</a>
<p>Removes all jobs in the database without defined behaviors. Useful if you change a definition name and want to remove old jobs. Returns a Promise resolving to the number of removed jobs, or rejecting on error.</p>
<p><em>IMPORTANT:</em> Do not run this before you finish defining all of your jobs. If you do, you will nuke your database of jobs.</p>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">numRemoved</span><span class="hl-1"> = </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">purge</span><span class="hl-1">();</span>
</code></pre>

<a href="#starting-the-job-processor" id="starting-the-job-processor" style="color: inherit; text-decoration: none;">
  <h2>Starting the job processor</h2>
</a>
<p>To get agenda to start processing jobs from the database you must start it. This
will schedule an interval (based on <code>processEvery</code>) to check for new jobs and
run them. You can also stop the queue.</p>

<a href="#start" id="start" style="color: inherit; text-decoration: none;">
  <h3>start</h3>
</a>
<p>Starts the job queue processing, checking <a href="#processeveryinterval"><code>processEvery</code></a> time to see if there
are new jobs. Must be called <em>after</em> <code>processEvery</code>, and <em>before</em> any job scheduling (e.g. <code>every</code>).</p>

<a href="#stop" id="stop" style="color: inherit; text-decoration: none;">
  <h3>stop</h3>
</a>
<p>Stops the job queue processing. Unlocks currently running jobs.</p>
<p>This can be very useful for graceful shutdowns so that currently running/grabbed jobs are abandoned so that other
job queues can grab them / they are unlocked should the job queue start again. Here is an example of how to do a graceful
shutdown.</p>
<pre><code class="language-js"><span class="hl-5">async</span><span class="hl-1"> </span><span class="hl-5">function</span><span class="hl-1"> </span><span class="hl-2">graceful</span><span class="hl-1">() {</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">stop</span><span class="hl-1">();</span><br/><span class="hl-1">  </span><span class="hl-0">process</span><span class="hl-1">.</span><span class="hl-2">exit</span><span class="hl-1">(</span><span class="hl-4">0</span><span class="hl-1">);</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-0">process</span><span class="hl-1">.</span><span class="hl-2">on</span><span class="hl-1">(</span><span class="hl-3">&#39;SIGTERM&#39;</span><span class="hl-1">, </span><span class="hl-0">graceful</span><span class="hl-1">);</span><br/><span class="hl-0">process</span><span class="hl-1">.</span><span class="hl-2">on</span><span class="hl-1">(</span><span class="hl-3">&#39;SIGINT&#39;</span><span class="hl-1"> , </span><span class="hl-0">graceful</span><span class="hl-1">);</span>
</code></pre>

<a href="#multiple-job-processors" id="multiple-job-processors" style="color: inherit; text-decoration: none;">
  <h2>Multiple job processors</h2>
</a>
<p>Sometimes you may want to have multiple node instances / machines process from
the same queue. Agenda supports a locking mechanism to ensure that multiple
queues don&#39;t process the same job.</p>
<p>You can configure the locking mechanism by specifying <code>lockLifetime</code> as an
interval when defining the job.</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">define</span><span class="hl-1">(</span><span class="hl-3">&#39;someJob&#39;</span><span class="hl-1">, (</span><span class="hl-0">job</span><span class="hl-1">, </span><span class="hl-0">cb</span><span class="hl-1">) </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-7">// Do something in 10 seconds or less...</span><br/><span class="hl-1">}, {</span><span class="hl-0">lockLifetime:</span><span class="hl-1"> </span><span class="hl-4">10000</span><span class="hl-1">});</span>
</code></pre>
<p>This will ensure that no other job processor (this one included) attempts to run the job again
for the next 10 seconds. If you have a particularly long running job, you will want to
specify a longer lockLifetime.</p>
<p>By default it is 10 minutes. Typically you shouldn&#39;t have a job that runs for 10 minutes,
so this is really insurance should the job queue crash before the job is unlocked.</p>
<p>When a job is finished (i.e. the returned promise resolves/rejects or <code>done</code> is
specified in the signature and <code>done()</code> is called), it will automatically unlock.</p>

<a href="#manually-working-with-a-job" id="manually-working-with-a-job" style="color: inherit; text-decoration: none;">
  <h2>Manually working with a job</h2>
</a>
<p>A job instance has many instance methods. All mutating methods must be followed
with a call to <code>await job.save()</code> in order to persist the changes to the database.</p>

<a href="#repeateveryinterval-options" id="repeateveryinterval-options" style="color: inherit; text-decoration: none;">
  <h3>repeatEvery(interval, [options])</h3>
</a>
<p>Specifies an <code>interval</code> on which the job should repeat. The job runs at the time of defining as well in configured intervals, that is &quot;run <em>now</em> and in intervals&quot;.</p>
<p><code>interval</code> can be a human-readable format <code>String</code>, a <a href="https://www.npmjs.com/package/cron-parser">cron format</a> <code>String</code>, or a <code>Number</code>.</p>
<p><code>options</code> is an optional argument containing:</p>
<p><code>options.timezone</code>: should be a string as accepted by <a href="https://momentjs.com/timezone/">moment-timezone</a> and is considered when using an interval in the cron string format.</p>
<p><code>options.skipImmediate</code>: <code>true</code> | <code>false</code> (default) Setting this <code>true</code> will skip the immediate run. The first run will occur only in configured interval.</p>
<pre><code class="language-js"><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">repeatEvery</span><span class="hl-1">(</span><span class="hl-3">&#39;10 minutes&#39;</span><span class="hl-1">);</span><br/><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">save</span><span class="hl-1">();</span>
</code></pre>
<pre><code class="language-js"><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">repeatEvery</span><span class="hl-1">(</span><span class="hl-3">&#39;3 minutes&#39;</span><span class="hl-1">, {</span><br/><span class="hl-1">  </span><span class="hl-0">skipImmediate:</span><span class="hl-1"> </span><span class="hl-5">true</span><br/><span class="hl-1">});</span><br/><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">save</span><span class="hl-1">();</span>
</code></pre>
<pre><code class="language-js"><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">repeatEvery</span><span class="hl-1">(</span><span class="hl-3">&#39;0 6 * * *&#39;</span><span class="hl-1">, {</span><br/><span class="hl-1">  </span><span class="hl-0">timezone:</span><span class="hl-1"> </span><span class="hl-3">&#39;America/New_York&#39;</span><br/><span class="hl-1">});</span><br/><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">save</span><span class="hl-1">();</span>
</code></pre>

<a href="#repeatattime" id="repeatattime" style="color: inherit; text-decoration: none;">
  <h3>repeatAt(time)</h3>
</a>
<p>Specifies a <code>time</code> when the job should repeat. <a href="https://github.com/matthewmueller/date#examples">Possible values</a></p>
<pre><code class="language-js"><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">repeatAt</span><span class="hl-1">(</span><span class="hl-3">&#39;3:30pm&#39;</span><span class="hl-1">);</span><br/><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">save</span><span class="hl-1">();</span>
</code></pre>

<a href="#scheduletime" id="scheduletime" style="color: inherit; text-decoration: none;">
  <h3>schedule(time)</h3>
</a>
<p>Specifies the next <code>time</code> at which the job should run.</p>
<pre><code class="language-js"><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">schedule</span><span class="hl-1">(</span><span class="hl-3">&#39;tomorrow at 6pm&#39;</span><span class="hl-1">);</span><br/><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">save</span><span class="hl-1">();</span>
</code></pre>

<a href="#prioritypriority" id="prioritypriority" style="color: inherit; text-decoration: none;">
  <h3>priority(priority)</h3>
</a>
<p>Specifies the <code>priority</code> weighting of the job. Can be a number or a string from
the above priority table.</p>
<pre><code class="language-js"><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">priority</span><span class="hl-1">(</span><span class="hl-3">&#39;low&#39;</span><span class="hl-1">);</span><br/><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">save</span><span class="hl-1">();</span>
</code></pre>

<a href="#uniqueproperties-options" id="uniqueproperties-options" style="color: inherit; text-decoration: none;">
  <h3>unique(properties, [options])</h3>
</a>
<p>Ensure that only one instance of this job exists with the specified properties</p>
<p><code>options</code> is an optional argument which can overwrite the defaults. It can take
the following:</p>
<ul>
<li><code>insertOnly</code>: <code>boolean</code> will prevent any properties from persisting if the job already exists. Defaults to false.</li>
</ul>
<pre><code class="language-js"><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">unique</span><span class="hl-1">({</span><span class="hl-3">&#39;data.type&#39;</span><span class="hl-0">:</span><span class="hl-1"> </span><span class="hl-3">&#39;active&#39;</span><span class="hl-1">, </span><span class="hl-3">&#39;data.userId&#39;</span><span class="hl-0">:</span><span class="hl-1"> </span><span class="hl-3">&#39;123&#39;</span><span class="hl-1">, </span><span class="hl-0">nextRunAt:</span><span class="hl-1"> </span><span class="hl-0">date</span><span class="hl-1">});</span><br/><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">save</span><span class="hl-1">();</span>
</code></pre>
<p><em>IMPORTANT:</em> To avoid high CPU usage by MongoDB, make sure to create an index on the used fields, like <code>data.type</code> and <code>data.userId</code> for the example above.</p>

<a href="#failreason" id="failreason" style="color: inherit; text-decoration: none;">
  <h3>fail(reason)</h3>
</a>
<p>Sets <code>job.attrs.failedAt</code> to <code>now</code>, and sets <code>job.attrs.failReason</code> to <code>reason</code>.</p>
<p>Optionally, <code>reason</code> can be an error, in which case <code>job.attrs.failReason</code> will
be set to <code>error.message</code></p>
<pre><code class="language-js"><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">fail</span><span class="hl-1">(</span><span class="hl-3">&#39;insufficient disk space&#39;</span><span class="hl-1">);</span><br/><span class="hl-7">// or</span><br/><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">fail</span><span class="hl-1">(</span><span class="hl-5">new</span><span class="hl-1"> </span><span class="hl-10">Error</span><span class="hl-1">(</span><span class="hl-3">&#39;insufficient disk space&#39;</span><span class="hl-1">));</span><br/><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">save</span><span class="hl-1">();</span>
</code></pre>

<a href="#runcallback" id="runcallback" style="color: inherit; text-decoration: none;">
  <h3>run(callback)</h3>
</a>
<p>Runs the given <code>job</code> and calls <code>callback(err, job)</code> upon completion. Normally
you never need to call this manually.</p>
<pre><code class="language-js"><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">run</span><span class="hl-1">((</span><span class="hl-0">err</span><span class="hl-1">, </span><span class="hl-0">job</span><span class="hl-1">) </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-0">console</span><span class="hl-1">.</span><span class="hl-2">log</span><span class="hl-1">(</span><span class="hl-3">&#39;I don</span><span class="hl-11">\&#39;</span><span class="hl-3">t know why you would need to do this...&#39;</span><span class="hl-1">);</span><br/><span class="hl-1">});</span>
</code></pre>

<a href="#save" id="save" style="color: inherit; text-decoration: none;">
  <h3>save()</h3>
</a>
<p>Saves the <code>job.attrs</code> into the database. Returns a Promise resolving to a Job instance, or rejecting on error.</p>
<pre><code class="language-js"><span class="hl-8">try</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">save</span><span class="hl-1">();</span><br/><span class="hl-1">  </span><span class="hl-0">cosole</span><span class="hl-1">.</span><span class="hl-2">log</span><span class="hl-1">(</span><span class="hl-3">&#39;Successfully saved job to collection&#39;</span><span class="hl-1">);</span><br/><span class="hl-1">} </span><span class="hl-8">catch</span><span class="hl-1"> (</span><span class="hl-0">e</span><span class="hl-1">) {</span><br/><span class="hl-1">  </span><span class="hl-0">console</span><span class="hl-1">.</span><span class="hl-2">error</span><span class="hl-1">(</span><span class="hl-3">&#39;Error saving job to collection&#39;</span><span class="hl-1">);</span><br/><span class="hl-1">}</span>
</code></pre>

<a href="#remove" id="remove" style="color: inherit; text-decoration: none;">
  <h3>remove()</h3>
</a>
<p>Removes the <code>job</code> from the database. Returns a Promise resolving to the number of jobs removed, or rejecting on error.</p>
<pre><code class="language-js"><span class="hl-8">try</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">remove</span><span class="hl-1">();</span><br/><span class="hl-1">  </span><span class="hl-0">console</span><span class="hl-1">.</span><span class="hl-2">log</span><span class="hl-1">(</span><span class="hl-3">&#39;Successfully removed job from collection&#39;</span><span class="hl-1">);</span><br/><span class="hl-1">} </span><span class="hl-8">catch</span><span class="hl-1"> (</span><span class="hl-0">e</span><span class="hl-1">) {</span><br/><span class="hl-1">  </span><span class="hl-0">console</span><span class="hl-1">.</span><span class="hl-2">error</span><span class="hl-1">(</span><span class="hl-3">&#39;Error removing job from collection&#39;</span><span class="hl-1">);</span><br/><span class="hl-1">}</span>
</code></pre>

<a href="#disable" id="disable" style="color: inherit; text-decoration: none;">
  <h3>disable()</h3>
</a>
<p>Disables the <code>job</code>. Upcoming runs won&#39;t execute.</p>

<a href="#enable" id="enable" style="color: inherit; text-decoration: none;">
  <h3>enable()</h3>
</a>
<p>Enables the <code>job</code> if it got disabled before. Upcoming runs will execute.</p>

<a href="#touch" id="touch" style="color: inherit; text-decoration: none;">
  <h3>touch()</h3>
</a>
<p>Resets the lock on the job. Useful to indicate that the job hasn&#39;t timed out
when you have very long running jobs. The call returns a promise that resolves
when the job&#39;s lock has been renewed.</p>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">define</span><span class="hl-1">(</span><span class="hl-3">&#39;super long job&#39;</span><span class="hl-1">, </span><span class="hl-5">async</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1"> </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-2">doSomeLongTask</span><span class="hl-1">();</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">touch</span><span class="hl-1">();</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-2">doAnotherLongTask</span><span class="hl-1">();</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-2">touch</span><span class="hl-1">();</span><br/><span class="hl-1">  </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-2">finishOurLongTasks</span><span class="hl-1">();</span><br/><span class="hl-1">});</span>
</code></pre>

<a href="#job-queue-events" id="job-queue-events" style="color: inherit; text-decoration: none;">
  <h2>Job Queue Events</h2>
</a>
<p>An instance of an agenda will emit the following events:</p>
<ul>
<li><code>start</code> - called just before a job starts</li>
<li><code>start:job name</code> - called just before the specified job starts</li>
</ul>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">on</span><span class="hl-1">(</span><span class="hl-3">&#39;start&#39;</span><span class="hl-1">, </span><span class="hl-0">job</span><span class="hl-1"> </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-0">console</span><span class="hl-1">.</span><span class="hl-2">log</span><span class="hl-1">(</span><span class="hl-3">&#39;Job %s starting&#39;</span><span class="hl-1">, </span><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-0">attrs</span><span class="hl-1">.</span><span class="hl-0">name</span><span class="hl-1">);</span><br/><span class="hl-1">});</span>
</code></pre>
<ul>
<li><code>complete</code> - called when a job finishes, regardless of if it succeeds or fails</li>
<li><code>complete:job name</code> - called when a job finishes, regardless of if it succeeds or fails</li>
</ul>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">on</span><span class="hl-1">(</span><span class="hl-3">&#39;complete&#39;</span><span class="hl-1">, </span><span class="hl-0">job</span><span class="hl-1"> </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-0">console</span><span class="hl-1">.</span><span class="hl-2">log</span><span class="hl-1">(</span><span class="hl-3">`Job </span><span class="hl-5">${</span><span class="hl-0">job</span><span class="hl-12">.</span><span class="hl-0">attrs</span><span class="hl-12">.</span><span class="hl-0">name</span><span class="hl-5">}</span><span class="hl-3"> finished`</span><span class="hl-1">);</span><br/><span class="hl-1">});</span>
</code></pre>
<ul>
<li><code>success</code> - called when a job finishes successfully</li>
<li><code>success:job name</code> - called when a job finishes successfully</li>
</ul>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">on</span><span class="hl-1">(</span><span class="hl-3">&#39;success:send email&#39;</span><span class="hl-1">, </span><span class="hl-0">job</span><span class="hl-1"> </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-0">console</span><span class="hl-1">.</span><span class="hl-2">log</span><span class="hl-1">(</span><span class="hl-3">`Sent Email Successfully to </span><span class="hl-5">${</span><span class="hl-0">job</span><span class="hl-12">.</span><span class="hl-0">attrs</span><span class="hl-12">.</span><span class="hl-0">data</span><span class="hl-12">.</span><span class="hl-0">to</span><span class="hl-5">}</span><span class="hl-3">`</span><span class="hl-1">);</span><br/><span class="hl-1">});</span>
</code></pre>
<ul>
<li><code>fail</code> - called when a job throws an error</li>
<li><code>fail:job name</code> - called when a job throws an error</li>
</ul>
<pre><code class="language-js"><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">on</span><span class="hl-1">(</span><span class="hl-3">&#39;fail:send email&#39;</span><span class="hl-1">, (</span><span class="hl-0">err</span><span class="hl-1">, </span><span class="hl-0">job</span><span class="hl-1">) </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-0">console</span><span class="hl-1">.</span><span class="hl-2">log</span><span class="hl-1">(</span><span class="hl-3">`Job failed with error: </span><span class="hl-5">${</span><span class="hl-0">err</span><span class="hl-12">.</span><span class="hl-0">message</span><span class="hl-5">}</span><span class="hl-3">`</span><span class="hl-1">);</span><br/><span class="hl-1">});</span>
</code></pre>

<a href="#frequently-asked-questions" id="frequently-asked-questions" style="color: inherit; text-decoration: none;">
  <h2>Frequently Asked Questions</h2>
</a>

<a href="#what-is-the-order-in-which-jobs-run" id="what-is-the-order-in-which-jobs-run" style="color: inherit; text-decoration: none;">
  <h3>What is the order in which jobs run?</h3>
</a>
<p>Jobs are run with priority in a first in first out order (so they will be run in the order they were scheduled AND with respect to highest priority).</p>
<p>For example, if we have two jobs named &quot;send-email&quot; queued (both with the same priority), and the first job is queued at 3:00 PM and second job is queued at 3:05 PM with the same <code>priority</code> value, then the first job will run first if we start to send &quot;send-email&quot; jobs at 3:10 PM. However if the first job has a priority of <code>5</code> and the second job has a priority of <code>10</code>, then the second will run first (priority takes precedence) at 3:10 PM.</p>
<p>The default <a href="https://docs.mongodb.com/manual/reference/method/cursor.sort/">MongoDB sort object</a> is <code>{ nextRunAt: 1, priority: -1 }</code> and can be changed through the option <code>sort</code> when configuring Agenda.</p>

<a href="#what-is-the-difference-between-locklimit-and-maxconcurrency" id="what-is-the-difference-between-locklimit-and-maxconcurrency" style="color: inherit; text-decoration: none;">
  <h3>What is the difference between <code>lockLimit</code> and <code>maxConcurrency</code>?</h3>
</a>
<p>Agenda will lock jobs 1 by one, setting the <code>lockedAt</code> property in mongoDB, and creating an instance of the <code>Job</code> class which it caches into the <code>_lockedJobs</code> array. This defaults to having no limit, but can be managed using lockLimit. If all jobs will need to be run before agenda&#39;s next interval (set via <code>agenda.processEvery</code>), then agenda will attempt to lock all jobs.</p>
<p>Agenda will also pull jobs from <code>_lockedJobs</code> and into <code>_runningJobs</code>. These jobs are actively being worked on by user code, and this is limited by <code>maxConcurrency</code> (defaults to 20).</p>
<p>If you have multiple instances of agenda processing the same job definition with a fast repeat time you may find they get unevenly loaded. This is because they will compete to lock as many jobs as possible, even if they don&#39;t have enough concurrency to process them. This can be resolved by tweaking the <code>maxConcurrency</code> and <code>lockLimit</code> properties.</p>

<a href="#sample-project-structure" id="sample-project-structure" style="color: inherit; text-decoration: none;">
  <h3>Sample Project Structure?</h3>
</a>
<p>Agenda doesn&#39;t have a preferred project structure and leaves it to the user to
choose how they would like to use it. That being said, you can check out the
<a href="#example-project-structure">example project structure</a> below.</p>

<a href="#can-i-donate" id="can-i-donate" style="color: inherit; text-decoration: none;">
  <h3>Can I Donate?</h3>
</a>
<p>Thanks! I&#39;m flattered, but it&#39;s really not necessary. If you really want to, you can find my <a href="https://www.gittip.com/rschmukler/">gittip here</a>.</p>

<a href="#web-interface" id="web-interface" style="color: inherit; text-decoration: none;">
  <h3>Web Interface?</h3>
</a>
<p>Agenda itself does not have a web interface built in but we do offer stand-alone web interface <a href="https://github.com/agenda/agendash">Agendash</a>:</p>
<p><a href="https://raw.githubusercontent.com/agenda/agendash/master/job-details.png"><img src="https://raw.githubusercontent.com/agenda/agendash/master/job-details.png" style="max-width:100%" alt="Agendash interface"></a></p>

<a href="#mongo-vs-redis" id="mongo-vs-redis" style="color: inherit; text-decoration: none;">
  <h3>Mongo vs Redis</h3>
</a>
<p>The decision to use Mongo instead of Redis is intentional. Redis is often used for
non-essential data (such as sessions) and without configuration doesn&#39;t
guarantee the same level of persistence as Mongo (should the server need to be
restarted/crash).</p>
<p>Agenda decides to focus on persistence without requiring special configuration
of Redis (thereby degrading the performance of the Redis server on non-critical
data, such as sessions).</p>
<p>Ultimately if enough people want a Redis driver instead of Mongo, I will write
one. (Please open an issue requesting it). For now, Agenda decided to focus on
guaranteed persistence.</p>

<a href="#spawning--forking-processes" id="spawning--forking-processes" style="color: inherit; text-decoration: none;">
  <h3>Spawning / forking processes</h3>
</a>
<p>Ultimately Agenda can work from a single job queue across multiple machines, node processes, or forks. If you are interested in having more than one worker, <a href="http://github.com/bars3s">Bars3s</a> has written up a fantastic example of how one might do it:</p>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">cluster</span><span class="hl-1"> = </span><span class="hl-2">require</span><span class="hl-1">(</span><span class="hl-3">&#39;cluster&#39;</span><span class="hl-1">);</span><br/><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">os</span><span class="hl-1"> = </span><span class="hl-2">require</span><span class="hl-1">(</span><span class="hl-3">&#39;os&#39;</span><span class="hl-1">);</span><br/><br/><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">httpServer</span><span class="hl-1"> = </span><span class="hl-2">require</span><span class="hl-1">(</span><span class="hl-3">&#39;./app/http-server&#39;</span><span class="hl-1">);</span><br/><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">jobWorker</span><span class="hl-1"> = </span><span class="hl-2">require</span><span class="hl-1">(</span><span class="hl-3">&#39;./app/job-worker&#39;</span><span class="hl-1">);</span><br/><br/><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">jobWorkers</span><span class="hl-1"> = [];</span><br/><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">webWorkers</span><span class="hl-1"> = [];</span><br/><br/><span class="hl-8">if</span><span class="hl-1"> (</span><span class="hl-0">cluster</span><span class="hl-1">.</span><span class="hl-0">isMaster</span><span class="hl-1">) {</span><br/><span class="hl-1">  </span><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">cpuCount</span><span class="hl-1"> = </span><span class="hl-0">os</span><span class="hl-1">.</span><span class="hl-2">cpus</span><span class="hl-1">().</span><span class="hl-0">length</span><span class="hl-1">;</span><br/><span class="hl-1">  </span><span class="hl-7">// Create a worker for each CPU</span><br/><span class="hl-1">  </span><span class="hl-8">for</span><span class="hl-1"> (</span><span class="hl-5">let</span><span class="hl-1"> </span><span class="hl-0">i</span><span class="hl-1"> = </span><span class="hl-4">0</span><span class="hl-1">; </span><span class="hl-0">i</span><span class="hl-1"> &lt; </span><span class="hl-0">cpuCount</span><span class="hl-1">; </span><span class="hl-0">i</span><span class="hl-1"> += </span><span class="hl-4">1</span><span class="hl-1">) {</span><br/><span class="hl-1">    </span><span class="hl-2">addJobWorker</span><span class="hl-1">();</span><br/><span class="hl-1">    </span><span class="hl-2">addWebWorker</span><span class="hl-1">();</span><br/><span class="hl-1">  }</span><br/><br/><span class="hl-1">  </span><span class="hl-0">cluster</span><span class="hl-1">.</span><span class="hl-2">on</span><span class="hl-1">(</span><span class="hl-3">&#39;exit&#39;</span><span class="hl-1">, (</span><span class="hl-0">worker</span><span class="hl-1">, </span><span class="hl-0">code</span><span class="hl-1">, </span><span class="hl-0">signal</span><span class="hl-1">) </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">    </span><span class="hl-8">if</span><span class="hl-1"> (</span><span class="hl-0">jobWorkers</span><span class="hl-1">.</span><span class="hl-2">indexOf</span><span class="hl-1">(</span><span class="hl-0">worker</span><span class="hl-1">.</span><span class="hl-0">id</span><span class="hl-1">) !== -</span><span class="hl-4">1</span><span class="hl-1">) {</span><br/><span class="hl-1">      </span><span class="hl-0">console</span><span class="hl-1">.</span><span class="hl-2">log</span><span class="hl-1">(</span><span class="hl-3">`job worker </span><span class="hl-5">${</span><span class="hl-0">worker</span><span class="hl-12">.</span><span class="hl-0">process</span><span class="hl-12">.</span><span class="hl-0">pid</span><span class="hl-5">}</span><span class="hl-3"> exited (signal: </span><span class="hl-5">${</span><span class="hl-0">signal</span><span class="hl-5">}</span><span class="hl-3">). Trying to respawn...`</span><span class="hl-1">);</span><br/><span class="hl-1">      </span><span class="hl-2">removeJobWorker</span><span class="hl-1">(</span><span class="hl-0">worker</span><span class="hl-1">.</span><span class="hl-0">id</span><span class="hl-1">);</span><br/><span class="hl-1">      </span><span class="hl-2">addJobWorker</span><span class="hl-1">();</span><br/><span class="hl-1">    }</span><br/><br/><span class="hl-1">    </span><span class="hl-8">if</span><span class="hl-1"> (</span><span class="hl-0">webWorkers</span><span class="hl-1">.</span><span class="hl-2">indexOf</span><span class="hl-1">(</span><span class="hl-0">worker</span><span class="hl-1">.</span><span class="hl-0">id</span><span class="hl-1">) !== -</span><span class="hl-4">1</span><span class="hl-1">) {</span><br/><span class="hl-1">      </span><span class="hl-0">console</span><span class="hl-1">.</span><span class="hl-2">log</span><span class="hl-1">(</span><span class="hl-3">`http worker </span><span class="hl-5">${</span><span class="hl-0">worker</span><span class="hl-12">.</span><span class="hl-0">process</span><span class="hl-12">.</span><span class="hl-0">pid</span><span class="hl-5">}</span><span class="hl-3"> exited (signal: </span><span class="hl-5">${</span><span class="hl-0">signal</span><span class="hl-5">}</span><span class="hl-3">). Trying to respawn...`</span><span class="hl-1">);</span><br/><span class="hl-1">      </span><span class="hl-2">removeWebWorker</span><span class="hl-1">(</span><span class="hl-0">worker</span><span class="hl-1">.</span><span class="hl-0">id</span><span class="hl-1">);</span><br/><span class="hl-1">      </span><span class="hl-2">addWebWorker</span><span class="hl-1">();</span><br/><span class="hl-1">    }</span><br/><span class="hl-1">  });</span><br/><span class="hl-1">} </span><span class="hl-8">else</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-8">if</span><span class="hl-1"> (</span><span class="hl-0">process</span><span class="hl-1">.</span><span class="hl-0">env</span><span class="hl-1">.</span><span class="hl-0">web</span><span class="hl-1">) {</span><br/><span class="hl-1">    </span><span class="hl-0">console</span><span class="hl-1">.</span><span class="hl-2">log</span><span class="hl-1">(</span><span class="hl-3">`start http server: </span><span class="hl-5">${</span><span class="hl-0">cluster</span><span class="hl-12">.</span><span class="hl-0">worker</span><span class="hl-12">.</span><span class="hl-0">id</span><span class="hl-5">}</span><span class="hl-3">`</span><span class="hl-1">);</span><br/><span class="hl-1">    </span><span class="hl-7">// Initialize the http server here</span><br/><span class="hl-1">    </span><span class="hl-0">httpServer</span><span class="hl-1">.</span><span class="hl-2">start</span><span class="hl-1">();</span><br/><span class="hl-1">  }</span><br/><br/><span class="hl-1">  </span><span class="hl-8">if</span><span class="hl-1"> (</span><span class="hl-0">process</span><span class="hl-1">.</span><span class="hl-0">env</span><span class="hl-1">.</span><span class="hl-0">job</span><span class="hl-1">) {</span><br/><span class="hl-1">    </span><span class="hl-0">console</span><span class="hl-1">.</span><span class="hl-2">log</span><span class="hl-1">(</span><span class="hl-3">`start job server: </span><span class="hl-5">${</span><span class="hl-0">cluster</span><span class="hl-12">.</span><span class="hl-0">worker</span><span class="hl-12">.</span><span class="hl-0">id</span><span class="hl-5">}</span><span class="hl-3">`</span><span class="hl-1">);</span><br/><span class="hl-1">    </span><span class="hl-7">// Initialize the Agenda here</span><br/><span class="hl-1">    </span><span class="hl-0">jobWorker</span><span class="hl-1">.</span><span class="hl-2">start</span><span class="hl-1">();</span><br/><span class="hl-1">  }</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-5">function</span><span class="hl-1"> </span><span class="hl-2">addWebWorker</span><span class="hl-1">() {</span><br/><span class="hl-1">  </span><span class="hl-0">webWorkers</span><span class="hl-1">.</span><span class="hl-2">push</span><span class="hl-1">(</span><span class="hl-0">cluster</span><span class="hl-1">.</span><span class="hl-2">fork</span><span class="hl-1">({</span><span class="hl-0">web:</span><span class="hl-1"> </span><span class="hl-4">1</span><span class="hl-1">}).</span><span class="hl-0">id</span><span class="hl-1">);</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-5">function</span><span class="hl-1"> </span><span class="hl-2">addJobWorker</span><span class="hl-1">() {</span><br/><span class="hl-1">  </span><span class="hl-0">jobWorkers</span><span class="hl-1">.</span><span class="hl-2">push</span><span class="hl-1">(</span><span class="hl-0">cluster</span><span class="hl-1">.</span><span class="hl-2">fork</span><span class="hl-1">({</span><span class="hl-0">job:</span><span class="hl-1"> </span><span class="hl-4">1</span><span class="hl-1">}).</span><span class="hl-0">id</span><span class="hl-1">);</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-5">function</span><span class="hl-1"> </span><span class="hl-2">removeWebWorker</span><span class="hl-1">(</span><span class="hl-0">id</span><span class="hl-1">) {</span><br/><span class="hl-1">  </span><span class="hl-0">webWorkers</span><span class="hl-1">.</span><span class="hl-2">splice</span><span class="hl-1">(</span><span class="hl-0">webWorkers</span><span class="hl-1">.</span><span class="hl-2">indexOf</span><span class="hl-1">(</span><span class="hl-0">id</span><span class="hl-1">), </span><span class="hl-4">1</span><span class="hl-1">);</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-5">function</span><span class="hl-1"> </span><span class="hl-2">removeJobWorker</span><span class="hl-1">(</span><span class="hl-0">id</span><span class="hl-1">) {</span><br/><span class="hl-1">  </span><span class="hl-0">jobWorkers</span><span class="hl-1">.</span><span class="hl-2">splice</span><span class="hl-1">(</span><span class="hl-0">jobWorkers</span><span class="hl-1">.</span><span class="hl-2">indexOf</span><span class="hl-1">(</span><span class="hl-0">id</span><span class="hl-1">), </span><span class="hl-4">1</span><span class="hl-1">);</span><br/><span class="hl-1">}</span>
</code></pre>

<a href="#recovering-lost-mongo-connections-quotauto_reconnectquot" id="recovering-lost-mongo-connections-quotauto_reconnectquot" style="color: inherit; text-decoration: none;">
  <h3>Recovering lost Mongo connections (&quot;auto_reconnect&quot;)</h3>
</a>
<p>Agenda is configured by default to automatically reconnect indefinitely, emitting an <a href="#agenda-events">error event</a>
when no connection is available on each <a href="#processeveryinterval">process tick</a>, allowing you to restore the Mongo
instance without having to restart the application.</p>
<p>However, if you are using an <a href="#mongomongoclientinstance">existing Mongo client</a>
you&#39;ll need to configure the <code>reconnectTries</code> and <code>reconnectInterval</code> <a href="http://mongodb.github.io/node-mongodb-native/3.0/reference/connecting/connection-settings/">connection settings</a>
manually, otherwise you&#39;ll find that Agenda will throw an error with the message &quot;MongoDB connection is not recoverable,
application restart required&quot; if the connection cannot be recovered within 30 seconds.</p>

<a href="#example-project-structure" id="example-project-structure" style="color: inherit; text-decoration: none;">
  <h1>Example Project Structure</h1>
</a>
<p>Agenda will only process jobs that it has definitions for. This allows you to
selectively choose which jobs a given agenda will process.</p>
<p>Consider the following project structure, which allows us to share models with
the rest of our code base, and specify which jobs a worker processes, if any at
all.</p>
<pre><code><span class="hl-1">- </span><span class="hl-0">server</span><span class="hl-1">.</span><span class="hl-0">js</span><br/><span class="hl-1">- </span><span class="hl-0">worker</span><span class="hl-1">.</span><span class="hl-0">js</span><br/><span class="hl-0">lib</span><span class="hl-1">/</span><br/><span class="hl-1">  - </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-0">js</span><br/><span class="hl-1">  </span><span class="hl-0">controllers</span><span class="hl-1">/</span><br/><span class="hl-1">    - </span><span class="hl-0">user</span><span class="hl-1">-</span><span class="hl-0">controller</span><span class="hl-1">.</span><span class="hl-0">js</span><br/><span class="hl-1">  </span><span class="hl-0">jobs</span><span class="hl-1">/</span><br/><span class="hl-1">    - </span><span class="hl-0">email</span><span class="hl-1">.</span><span class="hl-0">js</span><br/><span class="hl-1">    - </span><span class="hl-0">video</span><span class="hl-1">-</span><span class="hl-0">processing</span><span class="hl-1">.</span><span class="hl-0">js</span><br/><span class="hl-1">    - </span><span class="hl-0">image</span><span class="hl-1">-</span><span class="hl-0">processing</span><span class="hl-1">.</span><span class="hl-0">js</span><br/><span class="hl-1">   </span><span class="hl-0">models</span><span class="hl-1">/</span><br/><span class="hl-1">     - </span><span class="hl-0">user</span><span class="hl-1">-</span><span class="hl-0">model</span><span class="hl-1">.</span><span class="hl-0">js</span><br/><span class="hl-1">     - </span><span class="hl-0">blog</span><span class="hl-1">-</span><span class="hl-0">post</span><span class="hl-1">.</span><span class="hl-0">model</span><span class="hl-1">.</span><span class="hl-0">js</span>
</code></pre>
<p>Sample job processor (eg. <code>jobs/email.js</code>)</p>
<pre><code class="language-js"><span class="hl-5">let</span><span class="hl-1"> </span><span class="hl-0">email</span><span class="hl-1"> = </span><span class="hl-2">require</span><span class="hl-1">(</span><span class="hl-3">&#39;some-email-lib&#39;</span><span class="hl-1">),</span><br/><span class="hl-1">  </span><span class="hl-0">User</span><span class="hl-1"> = </span><span class="hl-2">require</span><span class="hl-1">(</span><span class="hl-3">&#39;../models/user-model.js&#39;</span><span class="hl-1">);</span><br/><br/><span class="hl-10">module</span><span class="hl-1">.</span><span class="hl-10">exports</span><span class="hl-1"> = </span><span class="hl-5">function</span><span class="hl-1">(</span><span class="hl-0">agenda</span><span class="hl-1">) {</span><br/><span class="hl-1">  </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">define</span><span class="hl-1">(</span><span class="hl-3">&#39;registration email&#39;</span><span class="hl-1">, </span><span class="hl-5">async</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1"> </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">    </span><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">user</span><span class="hl-1"> = </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-0">User</span><span class="hl-1">.</span><span class="hl-2">get</span><span class="hl-1">(</span><span class="hl-0">job</span><span class="hl-1">.</span><span class="hl-0">attrs</span><span class="hl-1">.</span><span class="hl-0">data</span><span class="hl-1">.</span><span class="hl-0">userId</span><span class="hl-1">);</span><br/><span class="hl-1">    </span><span class="hl-8">await</span><span class="hl-1"> </span><span class="hl-2">email</span><span class="hl-1">(</span><span class="hl-0">user</span><span class="hl-1">.</span><span class="hl-2">email</span><span class="hl-1">(), </span><span class="hl-3">&#39;Thanks for registering&#39;</span><span class="hl-1">, </span><span class="hl-3">&#39;Thanks for registering &#39;</span><span class="hl-1"> + </span><span class="hl-0">user</span><span class="hl-1">.</span><span class="hl-2">name</span><span class="hl-1">());</span><br/><span class="hl-1">  });</span><br/><br/><span class="hl-1">  </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">define</span><span class="hl-1">(</span><span class="hl-3">&#39;reset password&#39;</span><span class="hl-1">, </span><span class="hl-5">async</span><span class="hl-1"> </span><span class="hl-0">job</span><span class="hl-1"> </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">    </span><span class="hl-7">// Etc</span><br/><span class="hl-1">  });</span><br/><br/><span class="hl-1">  </span><span class="hl-7">// More email related jobs</span><br/><span class="hl-1">};</span>
</code></pre>
<p>lib/agenda.js</p>
<pre><code class="language-js"><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">Agenda</span><span class="hl-1"> = </span><span class="hl-2">require</span><span class="hl-1">(</span><span class="hl-3">&#39;agenda&#39;</span><span class="hl-1">);</span><br/><br/><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">connectionOpts</span><span class="hl-1"> = {</span><span class="hl-0">db:</span><span class="hl-1"> {</span><span class="hl-0">address:</span><span class="hl-1"> </span><span class="hl-3">&#39;localhost:27017/agenda-test&#39;</span><span class="hl-1">, </span><span class="hl-0">collection:</span><span class="hl-1"> </span><span class="hl-3">&#39;agendaJobs&#39;</span><span class="hl-1">}};</span><br/><br/><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">agenda</span><span class="hl-1"> = </span><span class="hl-5">new</span><span class="hl-1"> </span><span class="hl-2">Agenda</span><span class="hl-1">(</span><span class="hl-0">connectionOpts</span><span class="hl-1">);</span><br/><br/><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">jobTypes</span><span class="hl-1"> = </span><span class="hl-0">process</span><span class="hl-1">.</span><span class="hl-0">env</span><span class="hl-1">.</span><span class="hl-6">JOB_TYPES</span><span class="hl-1"> ? </span><span class="hl-0">process</span><span class="hl-1">.</span><span class="hl-0">env</span><span class="hl-1">.</span><span class="hl-6">JOB_TYPES</span><span class="hl-1">.</span><span class="hl-2">split</span><span class="hl-1">(</span><span class="hl-3">&#39;,&#39;</span><span class="hl-1">) : [];</span><br/><br/><span class="hl-0">jobTypes</span><span class="hl-1">.</span><span class="hl-2">forEach</span><span class="hl-1">(</span><span class="hl-0">type</span><span class="hl-1"> </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-2">require</span><span class="hl-1">(</span><span class="hl-3">&#39;./jobs/&#39;</span><span class="hl-1"> + </span><span class="hl-0">type</span><span class="hl-1">)(</span><span class="hl-0">agenda</span><span class="hl-1">);</span><br/><span class="hl-1">});</span><br/><br/><span class="hl-8">if</span><span class="hl-1"> (</span><span class="hl-0">jobTypes</span><span class="hl-1">.</span><span class="hl-0">length</span><span class="hl-1">) {</span><br/><span class="hl-1">  </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">start</span><span class="hl-1">(); </span><span class="hl-7">// Returns a promise, which should be handled appropriately</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-10">module</span><span class="hl-1">.</span><span class="hl-10">exports</span><span class="hl-1"> = </span><span class="hl-0">agenda</span><span class="hl-1">;</span>
</code></pre>
<p>lib/controllers/user-controller.js</p>
<pre><code class="language-js"><span class="hl-5">let</span><span class="hl-1"> </span><span class="hl-0">app</span><span class="hl-1"> = </span><span class="hl-2">express</span><span class="hl-1">(),</span><br/><span class="hl-1">  </span><span class="hl-0">User</span><span class="hl-1"> = </span><span class="hl-2">require</span><span class="hl-1">(</span><span class="hl-3">&#39;../models/user-model&#39;</span><span class="hl-1">),</span><br/><span class="hl-1">  </span><span class="hl-0">agenda</span><span class="hl-1"> = </span><span class="hl-2">require</span><span class="hl-1">(</span><span class="hl-3">&#39;../worker.js&#39;</span><span class="hl-1">);</span><br/><br/><span class="hl-0">app</span><span class="hl-1">.</span><span class="hl-2">post</span><span class="hl-1">(</span><span class="hl-3">&#39;/users&#39;</span><span class="hl-1">, (</span><span class="hl-0">req</span><span class="hl-1">, </span><span class="hl-0">res</span><span class="hl-1">, </span><span class="hl-0">next</span><span class="hl-1">) </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">  </span><span class="hl-5">const</span><span class="hl-1"> </span><span class="hl-6">user</span><span class="hl-1"> = </span><span class="hl-5">new</span><span class="hl-1"> </span><span class="hl-2">User</span><span class="hl-1">(</span><span class="hl-0">req</span><span class="hl-1">.</span><span class="hl-0">body</span><span class="hl-1">);</span><br/><span class="hl-1">  </span><span class="hl-0">user</span><span class="hl-1">.</span><span class="hl-2">save</span><span class="hl-1">(</span><span class="hl-0">err</span><span class="hl-1"> </span><span class="hl-5">=&gt;</span><span class="hl-1"> {</span><br/><span class="hl-1">    </span><span class="hl-8">if</span><span class="hl-1"> (</span><span class="hl-0">err</span><span class="hl-1">) {</span><br/><span class="hl-1">      </span><span class="hl-8">return</span><span class="hl-1"> </span><span class="hl-2">next</span><span class="hl-1">(</span><span class="hl-0">err</span><span class="hl-1">);</span><br/><span class="hl-1">    }</span><br/><span class="hl-1">    </span><span class="hl-0">agenda</span><span class="hl-1">.</span><span class="hl-2">now</span><span class="hl-1">(</span><span class="hl-3">&#39;registration email&#39;</span><span class="hl-1">, {</span><span class="hl-0">userId:</span><span class="hl-1"> </span><span class="hl-0">user</span><span class="hl-1">.</span><span class="hl-2">primary</span><span class="hl-1">()});</span><br/><span class="hl-1">    </span><span class="hl-0">res</span><span class="hl-1">.</span><span class="hl-2">send</span><span class="hl-1">(</span><span class="hl-4">201</span><span class="hl-1">, </span><span class="hl-0">user</span><span class="hl-1">.</span><span class="hl-2">toJson</span><span class="hl-1">());</span><br/><span class="hl-1">  });</span><br/><span class="hl-1">});</span>
</code></pre>
<p>worker.js</p>
<pre><code class="language-js"><span class="hl-2">require</span><span class="hl-1">(</span><span class="hl-3">&#39;./lib/agenda.js&#39;</span><span class="hl-1">);</span>
</code></pre>
<p>Now you can do the following in your project:</p>
<pre><code class="language-bash"><span class="hl-1">node server.js</span>
</code></pre>
<p>Fire up an instance with no <code>JOB_TYPES</code>, giving you the ability to process jobs,
but not wasting resources processing jobs.</p>
<pre><code class="language-bash"><span class="hl-1">JOB_TYPES=email node server.js</span>
</code></pre>
<p>Allow your http server to process email jobs.</p>
<pre><code class="language-bash"><span class="hl-1">JOB_TYPES=email node worker.js</span>
</code></pre>
<p>Fire up an instance that processes email jobs.</p>
<pre><code class="language-bash"><span class="hl-1">JOB_TYPES=video-processing,image-processing node worker.js</span>
</code></pre>
<p>Fire up an instance that processes video-processing/image-processing jobs. Good for a heavy hitting server.</p>

<a href="#debugging-issues" id="debugging-issues" style="color: inherit; text-decoration: none;">
  <h1>Debugging Issues</h1>
</a>
<p>If you think you have encountered a bug, please feel free to report it here:</p>
<p><a href="https://github.com/hokify/agenda/issues/new">Submit Issue</a></p>
<p>Please provide us with as much details as possible such as:</p>
<ul>
<li>Agenda version</li>
<li>Environment (OSX, Linux, Windows, etc)</li>
<li>Small description of what happened</li>
<li>Any relevant stack track</li>
<li>Agenda logs (see below)</li>
</ul>

<a href="#to-turn-on-logging-please-set-your-debug-env-variable-like-so" id="to-turn-on-logging-please-set-your-debug-env-variable-like-so" style="color: inherit; text-decoration: none;">
  <h4>To turn on logging, please set your DEBUG env variable like so:</h4>
</a>
<ul>
<li>OSX: <code>DEBUG=&quot;agenda:*&quot; ts-node src/index.ts</code></li>
<li>Linux: <code>DEBUG=&quot;agenda:*&quot; ts-node src/index.ts</code></li>
<li>Windows CMD: <code>set DEBUG=agenda:*</code></li>
<li>Windows PowerShell: <code>$env:DEBUG = &quot;agenda:*&quot;</code></li>
</ul>
<p>While not necessary, attaching a text file with this debug information would
be extremely useful in debugging certain issues and is encouraged.</p>

<a href="#known-issues" id="known-issues" style="color: inherit; text-decoration: none;">
  <h1>Known Issues</h1>
</a>

<a href="#quotmultiple-order-by-items-are-not-supported-please-specify-a-single-order-by-itemquot" id="quotmultiple-order-by-items-are-not-supported-please-specify-a-single-order-by-itemquot" style="color: inherit; text-decoration: none;">
  <h4>&quot;Multiple order-by items are not supported. Please specify a single order-by item.&quot;</h4>
</a>
<p>When running Agenda on Azure cosmosDB, you might run into this issue caused by Agenda&#39;s sort query used for finding and locking the next job. To fix this, you can pass <a href="#sortquery">custom sort option</a>: <code>sort: { nextRunAt: 1 }</code></p>

<a href="#performance" id="performance" style="color: inherit; text-decoration: none;">
  <h1>Performance</h1>
</a>
<p>It is recommended to set this index if you use agendash:</p>
<pre><code><span class="hl-0">db</span><span class="hl-1">.</span><span class="hl-0">agendaJobs</span><span class="hl-1">.</span><span class="hl-2">ensureIndex</span><span class="hl-1">({</span><br/><span class="hl-1">    </span><span class="hl-3">&quot;nextRunAt&quot;</span><span class="hl-0"> :</span><span class="hl-1"> -</span><span class="hl-4">1</span><span class="hl-1">,</span><br/><span class="hl-1">    </span><span class="hl-3">&quot;lastRunAt&quot;</span><span class="hl-0"> :</span><span class="hl-1"> -</span><span class="hl-4">1</span><span class="hl-1">,</span><br/><span class="hl-1">    </span><span class="hl-3">&quot;lastFinishedAt&quot;</span><span class="hl-0"> :</span><span class="hl-1"> -</span><span class="hl-4">1</span><br/><span class="hl-1">}, </span><span class="hl-3">&quot;agendash2&quot;</span><span class="hl-1">)</span>
</code></pre>
<p>If you have one job definition with thousand of instances, you can add this index to improve internal sorting query
for faster sortings</p>
<pre><code><span class="hl-0">db</span><span class="hl-1">.</span><span class="hl-0">agendaJobs</span><span class="hl-1">.</span><span class="hl-2">ensureIndex</span><span class="hl-1">({</span><br/><span class="hl-1">    </span><span class="hl-3">&quot;name&quot;</span><span class="hl-0"> :</span><span class="hl-1"> </span><span class="hl-4">1</span><span class="hl-1">,</span><br/><span class="hl-1">    </span><span class="hl-3">&quot;disabled&quot;</span><span class="hl-0"> :</span><span class="hl-1"> </span><span class="hl-4">1</span><span class="hl-1">,</span><br/><span class="hl-1">    </span><span class="hl-3">&quot;lockedAt&quot;</span><span class="hl-0"> :</span><span class="hl-1"> </span><span class="hl-4">1</span><br/><span class="hl-1">}, </span><span class="hl-3">&quot;findAndLockDeadJobs&quot;</span><span class="hl-1">)</span>
</code></pre>

<a href="#acknowledgements" id="acknowledgements" style="color: inherit; text-decoration: none;">
  <h1>Acknowledgements</h1>
</a>
<ul>
<li>Agenda was originally created by <a href="https://github.com/rschmukler">@rschmukler</a>.</li>
<li><a href="https://github.com/agenda/agendash">Agendash</a> was originally created by <a href="https://github.com/joeframbach">@joeframbach</a>.</li>
<li>These days Agenda has a great community of <a href="https://github.com/hokify/agenda/graphs/contributors">contributors</a> around it. Join us!</li>
</ul>

<a href="#license" id="license" style="color: inherit; text-decoration: none;">
  <h1>License</h1>
</a>
<p><a href="LICENSE.md">The MIT License</a></p>
</div></div><div class="col-4 col-menu menu-sticky-wrap menu-highlight"><nav class="tsd-navigation primary"><ul><li class="current"><a href="modules.html">Exports</a></li></ul></nav><nav class="tsd-navigation secondary menu-sticky"><ul><li class="tsd-kind-class"><a href="classes/Agenda.html" class="tsd-kind-icon">Agenda</a></li><li class="tsd-kind-class tsd-has-type-parameter"><a href="classes/Job.html" class="tsd-kind-icon">Job</a></li><li class="tsd-kind-interface"><a href="interfaces/IAgendaConfig.html" class="tsd-kind-icon">IAgenda<wbr/>Config</a></li><li class="tsd-kind-interface"><a href="interfaces/IDatabaseOptions.html" class="tsd-kind-icon">IDatabase<wbr/>Options</a></li><li class="tsd-kind-interface"><a href="interfaces/IDbConfig.html" class="tsd-kind-icon">IDb<wbr/>Config</a></li><li class="tsd-kind-interface tsd-has-type-parameter"><a href="interfaces/IJobDefinition.html" class="tsd-kind-icon">IJob<wbr/>Definition</a></li><li class="tsd-kind-interface tsd-has-type-parameter"><a href="interfaces/IJobParameters.html" class="tsd-kind-icon">IJob<wbr/>Parameters</a></li><li class="tsd-kind-interface"><a href="interfaces/IMongoOptions.html" class="tsd-kind-icon">IMongo<wbr/>Options</a></li><li class="tsd-kind-type-alias tsd-has-type-parameter"><a href="modules.html#DefinitionProcessor" class="tsd-kind-icon">Definition<wbr/>Processor</a></li><li class="tsd-kind-type-alias"><a href="modules.html#JobWithId" class="tsd-kind-icon">Job<wbr/>With<wbr/>Id</a></li><li class="tsd-kind-type-alias"><a href="modules.html#TJobDatefield" class="tsd-kind-icon">TJob<wbr/>Datefield</a></li><li class="tsd-kind-variable"><a href="modules.html#datefields" class="tsd-kind-icon">datefields</a></li></ul></nav></div></div></div><footer class="with-border-bottom"><div class="container"><h2>Legend</h2><div class="tsd-legend-group"><ul class="tsd-legend"><li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li><li class="tsd-kind-property tsd-parent-kind-class"><span class="tsd-kind-icon">Property</span></li><li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li></ul><ul class="tsd-legend"><li class="tsd-kind-property tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private property</span></li><li class="tsd-kind-method tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private method</span></li></ul><ul class="tsd-legend"><li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li></ul></div><h2>Settings</h2><p>Theme <select id="theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></p></div></footer><div class="container tsd-generator"><p>Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></div><div class="overlay"></div><script src="assets/main.js"></script></body></html>