2015-09-02 2 views
0

У меня есть следующий код:узел JS Монго дб зависимостей (документ не найден)

var method = PushLoop.prototype; 
var agent = require('./_header') 
var request = require('request'); 
var User = require('../models/user_model.js'); 
var Message = require('../models/message_model.js'); 
var async = require('async') 

function PushLoop() {}; 

    method.startPushLoop = function() { 

    getUserList() 

    function getUserList() {   

     User.find({}, function(err, users) {    
      if (err) throw err; 
      if (users.length > 0) {    
       getUserMessages(users) 
      } else {    
       setTimeout(getUserList, 3000) 
      }     
     }); 
    } 

    function getUserMessages(users) { 
     // console.log("getUserMessages") 
     async.eachSeries(users, function (user, callback) { 

       var params = { 
        email: user.email, 
       pwd: user.password, 
       token: user.device_token 
       }      
        messageRequest(params)        
       callback(); 
      }, function (err) { 
       if (err) { 
       console.log(err) 
        setTimeout(getUserList, 3000)     
       }    
      }); 
    } 

    function messageRequest(params) { 

      var url = "https://voip.ms/api/v1/rest.php?api_username="+ params.email +"&api_password="+ params.pwd +"&method=getSMS&type=1&limit=5"          
      request(url, function(err, response, body){ 

       if (!err) { 

        var responseObject = JSON.parse(body);           
       var messages = responseObject.sms 

        if (responseObject["status"] == "success") {                            
         async.eachSeries(messages, function(message, callback){  
          console.log(params.token)   
          saveMessage(message, params.token) 
          callback(); 

         }, function(err) { 
          if (err) { 
           console.log(err) 
          } 
          // setTimeout(getUserList, 3000)        
         }) 
        } else { 
         // setTimeout(getUserList, 3000)  
        } 
       } else { 
        console.log(err) 
        // setTimeout(getUserList, 3000) 
       }   

      }); 
      setTimeout(getUserList, 3000) 
    } 

    function saveMessage(message, token) { 
     // { $and: [ { price: { $ne: 1.99 } }, { price: { $exists: true } } 
     // Message.find({ $and: [{ message_id: message.id}, {device_token: token}]}, function (err, doc){    
      Message.findOne({message_id: message.id}, function (err, doc){ 

      if (!doc) {      
        console.log('emtpy today')     
        var m = new Message({ 
          message_id: message.id, 
          did: message.did, 
          contact: message.contact, 
          message: message.message, 
          date: message.date, 
          created_at: new Date().toLocaleString(), 
          updated_at: new Date().toLocaleString(), 
          device_token: token  
         });    
         m.save(function(e) { 
          if (e) {         
           console.log(e) 
          } else { 
           agent.createMessage()    
            .device(token) 
            .alert(message.message) 
            .set('contact', message.contact) 
            .set('did', message.did) 
            .set('id', message.id) 
            .set('date', message.date) 
            .set('message', message.message)      
            .send();         
          }          
         });  
      }              
     }) //.limit(1); 
    } 

}; 

module.exports = PushLoop; 

Что на самом деле работает прекрасно в моей среде разработки - Однако в производстве (я использую OpenShift) в Mongo документы сохраняйте в бесконечном цикле, чтобы он выглядел так: условие (if (! doc)) всегда возвращает true, поэтому документ создается каждый раз. Не уверен, что это может быть проблема мангуста - я также попробовал метод «find» вместо «findOne». Мой dev env имеет узел 0.12.7, а Openshift имеет значение 0.10.x - это может быть проблемой, и я все еще изучаю, но если кто-нибудь может обнаружить ошибку, которую я не вижу в своей логике/коде, то дайте мне знать

спасибо!

+0

Использование 'setTimeout' здесь довольно ужасно. Вы уже импортировали библиотеку 'async', поэтому используйте ее для управления потоком. Также использование '.findOne()' и '.save()' является ужасным образцом. Вместо этого вы должны применять '.update()' вместо атомных операторов. Но главное здесь, если вы «предположите», что вещи завершены через определенное время, тогда вы просто просите о неприятностях. Рефакторинг должен учитывать каждый обратный вызов. –

+0

То, что я пытаюсь сделать здесь, - опросить сторонний сервер обмена сообщениями каждые несколько секунд для новых сообщений. Обычно сервер возвращает последние 10 сообщений, и я храню их в экземпляре mongo. Таким образом, цель запроса на поиск заключается в том, чтобы узнать, сохранил ли я это сообщение, если нет, а затем сохраните его в mongo. Так вы говорите, что если я использую update() вместо save(), mongo сохранит новый документ? спасибо за ваш ответ btw – fredp613

+1

То, что я говорю, вы должны прочитать на ["upsert"] (http://docs.mongodb.org/manual/reference/method/db.collection.update/#upsert-option) вариант «найти или создать» - это в основном то, что он делает. Кроме того, даже если «опрос» вам не следует делать, пока вы не узнаете, что все обновления в цикле из ответа завершены. Если нет, вы рискуете, по крайней мере, создавать запросы в очереди и, возможно, даже переписывать данные. Но правильное исследование «.update()» и «upserts» и связанных с ними операторов должно помочь в этом. Ваш код нуждается в серьезном рефакторинге. –

ответ

0

Я решил эту проблему, используя шаблон типа «серия» и используя метод shift в массиве пользователей. Mongoose upsert findOneOrCreate хорош, однако, если есть найденный документ, документ возвращается, если он не найден и поэтому создан, он также возвращается. Поэтому я не мог отличить новый документ docs от найденного документа, поэтому использовал ту же функцию findOne, которая возвращает null, если не найден doc. Я просто создаю его и отправляю push-уведомление. Все еще abit уродливо, и я знаю, что я мог бы использовать обещания или async lib, может реорганизовать в будущем. Это работает на данный момент

function PushLoop() {}; 

    var results = []; 
    method.go = function() { 
     var userArr = []; 
     startLoop() 

     function startLoop() { 

     User.find({},function(err, users) {   
      if (err) throw err; 
      users.forEach(function(u) {    
       userArr.push(u)       
      })      
      function async(arg, callback) { 

       var url = "https://voip.ms/api/v1/rest.php?api_username="+ arg.email +"&api_password="+ arg.password +"&method=getSMS&type=1&limit=5"          

        request.get(url, {timeout: 30000}, function(err, response, body){ 
         if (!err) {           
          var responseObject = JSON.parse(body);           
         var messages = responseObject.sms 
         var status = responseObject.status 
         if (status === "success") { 


         messages.forEach(function(m) { 

          var message = new Message({ 
             message_id: m.id, 
             did: m.did, 
             contact: m.contact, 
             message: m.message, 
             date: m.date, 
             created_at: new Date().toLocaleString(), 
             updated_at: new Date().toLocaleString(), 
             device_token: arg.device_token  
            });        
            var query = { $and : [{message_id: m.id}, {device_token: arg.device_token}] } 
            var query1 = { message_id: m.id } 


            Message.findOne(query).lean().exec(function (err, doc){ 

              if (!doc || doc == null) {            
                  message.save(function(e) { 
                   console.log("message saved") 
                   if (e) { 
                    console.log("there is an error") 
                    console.log(e) 
                   } else { 

                    console.log(message.device_token) 
                     var messageStringCleaned = message.message.toString().replace(/\\/g,"");                                            

                     var payload = { 
                      "contact" : message.contact, 
                      "did" : message.did, 
                      "id" : message.message_id, 
                      "date" : message.date, 
                      "message" : messageStringCleaned 
                     }                  

                    var note = new apns.Notification(); 
                    var myDevice = new apns.Device(message.device_token); 
                    note.expiry = Math.floor(Date.now()/1000) + 3600; // Expires 1 hour from now. 
                    note.badge = 3;                 
                    note.alert = messageStringCleaned; 
                    note.payload = payload; 
                    apnsConnection.pushNotification(note, myDevice);                  
                  } 
                  })                                              
               }                                        
              }); 
            });      
         } 
          else { 
          console.log(err) 
          } 
         }     
        }); 

       setTimeout(function() {    
       callback(arg + "testing 12"); 
       }, 1000); 
      } 
      // Final task (same in all the examples)    
      function series(item) { 
        if(item) { 
        async(item, function(result) {            
         results.push(result);  
         return series(userArr.shift()); 
        }); 
        } else { 
        return final(); 
        } 
      } 
      function final() { 
       console.log('Done'); 
       startLoop(); 
      } 

      series(userArr.shift()) 
     }); 
    } 
} 


module.exports = PushLoop;