| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| // constructor for DB object - a thin, promise-loving wrapper around nano |
| module.exports = function(dbURL, dbName) { |
| var nano = require('nano')(dbURL); |
| this.db = nano.db.use(dbName); |
| |
| const designDoc = "filters"; |
| const assignmentView = "by-worker"; |
| |
| this.getTrigger = function(triggerFQN) { |
| return new Promise((resolve, reject) => { |
| this.db.get(triggerFQN, (err, result) => { |
| if(err) { |
| reject(err); |
| } else { |
| resolve(result); |
| } |
| }); |
| }); |
| }; |
| |
| this.ensureTriggerIsUnique = function(triggerFQN) { |
| return this.getTrigger(this.db, triggerFQN) |
| .then(result => { |
| return Promise.reject('Trigger already exists'); |
| }) |
| .catch(err => { |
| // turn that frown upside-down! |
| return true; |
| }); |
| }; |
| |
| this.recordTrigger = function(params) { |
| console.log('recording trigger'); |
| |
| params['_id'] = params.triggerName; |
| params['status'] = { |
| 'active': true, |
| 'dateChanged': Date.now() |
| }; |
| |
| return new Promise((resolve, reject) => { |
| this.db.insert(params, (err, result) => { |
| if(err) { |
| reject(err); |
| } else { |
| resolve(result); |
| } |
| }); |
| }); |
| }; |
| |
| this.deleteTrigger = function(triggerFQN) { |
| return this.getTrigger(triggerFQN) |
| .then(doc => { |
| return new Promise((resolve, reject) => { |
| this.db.destroy(doc._id, doc._rev, (err, result) => { |
| if(err) { |
| reject(err); |
| } else { |
| resolve(result); |
| } |
| }); |
| }); |
| }) |
| }; |
| |
| this.getTriggerAssignment = function(workers) { |
| |
| return new Promise((resolve, reject) => { |
| var assignment = workers[0] || 'worker0'; |
| |
| if (workers.length > 1) { |
| this.db.view(designDoc, assignmentView, {group: true}, (err, result) => { |
| if (err) { |
| reject(err); |
| } else { |
| // a map between available workers and their number of assigned triggers |
| // values will be populated with the results of the assignment view |
| var counter = {}; |
| workers.forEach(worker => { |
| counter[worker] = 0; |
| }); |
| |
| // update counter values with the number of assigned triggers |
| // for each worker |
| result.rows.forEach(row => { |
| if (row.key in counter) { |
| counter[row.key] = row.value; |
| } |
| }); |
| |
| // find which of the available workers has the least number of |
| // assigned triggers |
| for (availableWorker in counter) { |
| if (counter[availableWorker] < counter[assignment]) { |
| assignment = availableWorker; |
| } |
| } |
| resolve(assignment); |
| } |
| }); |
| } else { |
| resolve(assignment); |
| } |
| }); |
| }; |
| |
| this.updateTrigger = function(existing, params) { |
| return new Promise((resolve, reject) => { |
| var message = 'Automatically disabled trigger while updating'; |
| var status = { |
| 'active': false, |
| 'dateChanged': Date.now(), |
| 'reason': {'kind': 'AUTO', 'statusCode': undefined, 'message': message} |
| }; |
| existing.status = status; |
| this.db.insert(existing, (err, result) => { |
| if (err) { |
| reject(err); |
| } else { |
| resolve(result); |
| } |
| }); |
| }) |
| .then(() => this.getTrigger(existing.triggerName)) |
| .then(doc => { |
| for (var key in params) { |
| if (params[key] !== undefined) { |
| doc[key] = params[key]; |
| } |
| } |
| var status = { |
| 'active': true, |
| 'dateChanged': Date.now() |
| }; |
| doc.status = status; |
| |
| return new Promise((resolve, reject) => { |
| this.db.insert(doc, (err, result) => { |
| if(err) { |
| reject(err); |
| } else { |
| resolve(result); |
| } |
| }); |
| }); |
| }); |
| }; |
| }; |