Use CouchDB view instead of retrieving all docs (#151)

* Use a view to retrieve trigger documents

This is a more robust solution than getting all documents and assuming that they are all triggers

* add an extra layer of protection when restoring triggers
diff --git a/provider/app.py b/provider/app.py
index e317d4b..2d8185f 100644
--- a/provider/app.py
+++ b/provider/app.py
@@ -177,7 +177,11 @@
     for triggerDoc in database.triggers():
         triggerFQN = triggerDoc['_id']
         logging.debug('Restoring trigger {}'.format(triggerFQN))
-        createAndRunConsumer(triggerFQN, triggerDoc, record=False)
+
+        try:
+            createAndRunConsumer(triggerFQN, triggerDoc, record=False)
+        except:
+            logging.warn('Skipping consumer due to caught exception: {}'.format(triggerDoc))
 
 
 def getMissingPostFields(fields):
diff --git a/provider/database.py b/provider/database.py
index 6b91254..e7063e0 100644
--- a/provider/database.py
+++ b/provider/database.py
@@ -30,6 +30,9 @@
     client = Cloudant(username, password, account=username)
     client.connect()
 
+    filters_design_doc_id = '_design/filters'
+    only_triggers_view_id = 'only-triggers'
+
     if dbname in client.all_dbs():
         logging.info('Database exists - connecting to it.')
         database = client[dbname]
@@ -70,28 +73,35 @@
     def triggers(self):
         allDocs = []
 
-        logging.info('Fetching all documents from DB')
-        for document in Result(self.database.all_docs, include_docs=True):
+        logging.info('Fetching all triggers from DB')
+        for document in self.database.get_view_result(self.filters_design_doc_id, self.only_triggers_view_id, include_docs=True):
             allDocs.append(document['doc'])
 
-        logging.info('Successfully retrieved {} documents'.format(len(allDocs)))
+        logging.info('Successfully retrieved {} triggers'.format(len(allDocs)))
         return allDocs
 
     def migrate(self):
         logging.info('Starting DB migration')
 
-        for trigger in Result(self.database.all_docs, include_docs=True):
-            if 'uuid' not in trigger['doc']:
-                logging.info('[{}] Does not have a UUID. Generating one...'.format(trigger['id']));
+        filtersDesignDoc = self.database.get_design_document(self.filters_design_doc_id)
 
-                # this little dance seems odd to me. trigger does not have a .save() method,
-                # so I am left to fetch the document this way:
-                doc = self.database[trigger['id']]
-                doc['uuid'] = str(uuid.uuid4())
-                doc.save()
+        if not filtersDesignDoc.exists():
+            logging.info('Creating the design doc')
 
-                logging.info('[{}] Now has UUID {}'.format(trigger['id'], doc['uuid']))
-            else:
-                logging.debug('[{}] Already has UUID'.format(trigger['id']));
+            # create only-triggers view
+            self.database.create_document({
+                '_id': self.filters_design_doc_id,
+                'views': {
+                    self.only_triggers_view_id: {
+                        'map': """function (doc) {
+                                    if(doc.triggerURL) {
+                                        emit(doc._id, 1);
+                                    }
+                                }"""
+                    }
+                }
+            });
+        else:
+            logging.info("design doc already exists")
 
         logging.info('Database migration complete')