For my startup project darticle, we have several "jobs" which need to be taken care of outside of standard web page serving, including e-mailing and web scraping. For scalability, these jobs are handled asynchronously and concurrently, with the goal of the job queue being able to scale across various servers. Here I will write about darticle's solution for implementing such a job management system with CouchDB.
Workers need to grab a job document from the database, but which document(s) should they grab? A simple CouchDB mapping view solves this easily. In darticle's case, job can be queued for some time in the future. For example, an e-mail can be queued to be sent the following day, and a scrape can be queued to be run as soon as a worker is available. The map function assigns the date as one of its keys so it can be queried (e.g. from 0 to "now").
In darticle's implementation, there are multiple types of work which can be performed. Workers can subscribe to look for one or several of these types of work. The type of work ("worker" field) is put in the key of the view in addition to the date so it can be filtered easily.
Below is a simplified version of darticle's _design/work/new view.
map: function (doc) { if (doc.type !== 'WorkItem' || doc.claimed) { return; } // null dates default to 0 var date = doc.date || 0; emit([ doc.worker, date ], null); }
(darticle's engine uses UNIX timestamps for dates (less semantic, but more practical for indexing).)
For a worker to look for e-mails which need to be sent, for example, it would query the view with { "startkey": [ "email", 0 ], "endkey": [ "email", now ] }, where now is e.g. 1296945062 (for Sat, 05 Feb 2011 22:31:02). The worker would then claim (see next section) as many documents as it could and send the e-mails.
CouchDB operates on documents. Unlike with Redis, we can't use a set and pull work items atomically from the set. And unlike some SQL databases, we can't exclusive-lock a row, delete the row, then perform the work. With CouchDB, we have to depend upon collision handling, else we will run into concurrency issues.
To make the problem more clear: if we have to worker servers running simultaneously, and we enqueue a work item (say, to send an e-mail), both worker servers will be informed of the new work item. If both are currently unbusy, they'll both grab the work item and see that it hasn't been processed. Both work servers will then send the e-mail, and mark the job as completed! Clearly, we need some type of atomic "give me a new work item" procedure in the database. CouchDB does not offer one directly, so we must implement it ourselves (or switch to something else).
One of the beauties of CouchDB is that document changes do not override each other; if two servers pull a document, update it, then push the changes, there will be a conflict for the last to push the document, and that push will fail. We can then implement locking as such:
true), the worker ignores the job, as someone else has already claimed it for their own.true and pushes the document.This procedure ensures a document is not claimed by multiple workers. Below is a JavaScript code example of the locking procedure (using promises).
claim: function (document, successCallback, failCallback /* both callbacks optional */) { if (document.claimed) { throw new Error('Work item already claimed'); } document = util.deepClone(document); document.claimed = true; return db.put(document._id, document) .then(function (response) { document._rev = response.rev; document._id = response.id; return document; }) .then(successCallback, failCallback) .then(undefined, function () { // Make sure conflict errors don't throw }); };
Depending upon the implementation of the work queue, the worker can delete the job document when it is done with the job, or as soon as it claims the job. It can also mark the job as completed and leave it in the database. In darticle's case, there is a "status" field which is set to "fail" or "retry" if the job couldn't successfully be completed, and the document is deleted upon success.
A work queue database should not be replicated as a live database (from which workers can ask for work). I have not found a solution where replication could work with the above locking model.
Sharing, however, should work, as job documents have their own locking state contained and jobs are independent of each other. (I have not tested this, though.)
Although CouchDB does not have atomic or locking operations out-of-the-box, they can be simulated using conflict resolution to create a distributed work queue system.
Comments
How a Chain Sling Can Be Used-spun1
How a Chain Sling May be used
So what exactly is a chain sling? It's a device which can be suited to or round the object itself and then fixed to some further lifting machine to attempt the actual lifting, so in reality a chain sling can be defined as a lifting aid.
Chain slings are a common occurence in lots of areas, especially where big objects are manoeuvred frequently, dockyards, steel industries, foundries and various other types of factories all employ chain slings. 2,3 or 4 leg slings, everybody can be utilized inside a mixture of differing hitch types and so there should usually be something ideal for the majority of objects which require to be lifted and transported. They can also be fitted having a number of hooks and master links, including open hooks or hook's keeping the vehicle safe catches etc. The kind of chain sling needed as well as the type of hitch utilised will always be dependent on the kind of load to be lifted.
Aside from the two,triple and quad leg slings, a never-ending chain sling can also be popular, this can be a unbroken loop of chain. The safe working load limits of any type of chain sling can be impacted by the sort of hitch utilised, hence always talk to the necessary documents/producers for exact reductions which will have to be put on the working load limit capacities.
The 3 most typical types of hitches are the straight hitch, basket hitch plus choke lift.
An upright hitch is where any chain sling category is attached to the lifting appliance via its upper master link and also the hook on the end of each and every leg is attached to an anchor point around the load in a straight line.
A basket hitch is how the chain will cover under the load then hooked into the master link.
The chain inside a choke hitch also goes all-around the load however it is going to be subsequently hooked into the chain itself instead of into the masterlink, this is perfect for smaller and cylindrical objects.
One of several most important aspects to think about when working with any type of chain sling will be the angle of the legs in the straight vertical position. This should not be more than sixty degrees and aside from straight lifts the angle should never in actual fact be lower than fifteen degrees because this could make the lift unstable. Chain slings should never ever be knotted, if they're overly lengthy a shortening hook may be used without affecting safety.
Just before each use the chain sling should be inspected for evidence of wear, cracks or distorted links, these could cause lethal accidents if utilised within this condition. It's recommended that all chain goods are carefully inspected and re-tested at 6 monthly intervals with a qualified person, an established lifting gear business can offer this examination and propose repairs if required to ensure that they're in a safe condition. Chain slings tend to be quite simple to fix for the expert and thus is much more cost efficient to get them regularly tested and repaired instead of just replace with a totally new chain if this is not necessary.
I Agree!
this was flawless, great job putting this together. Are you thinking of posting a follow-up?
Post new comment