2015-10-01 17 views
5

Come gestire le richieste di aggiornamentoOrCreate con Waterline in Sails per un database Postgresql?Le chiamate ad alta frequenza portano a duplicati con findOrCreate in Waterline & Sails

Ho provato a utilizzare findOrCreate e quindi aggiornare l'elemento, ho provato findOne e quindi aggiornare o creare l'elemento, ho provato a mettere un beforeCreate, un metodo di hook beforeValidation per verificare se l'elemento esiste ma senza successo. Devo aggiungere un gestore errori per ottenere errori dall'indice univoco e riprovare?

Nel Waterline docs, è presente un avviso ma nessuna direzione per risolvere questo problema.

Grazie per eventuali suggerimenti.

+0

Creare una chiave univoca sul tavolo. – zerkms

+0

@zerkms Questo non è il problema; l'OP ha già una chiave univoca. Il problema è cosa fare quando il vincolo viene violato. – sgress454

risposta

4

Devo aggiungere un gestore errori per ottenere errori dall'indice univoco e riprovare?

Questa sarà l'unica opzione fino al momento in cui Waterline implementa le transazioni. Qualcosa di simile:

// This will hold the found or created user 
var user; 

// Keep repeating until we find or create a user, or get an error we dont expect 

async.doUntil(

    function findOrCreate(cb) { 

     // Try findOrCreate 
     User.findOrCreate(criteria, values).exec(function(err, _user) { 

      // If we get an error that is not a uniqueness error on the 
      // attribute we expect collisions on, bail out of the doUntil 
      if (err && 
       (
        !err.invalidAttributes["myUniqueAttribute"] || 
        !_.find(err.invalidAttributes["myUniqueAttribute"], {rule: 'unique'}) 
       ) 
       ) { 
       return cb(err); 
      } 

      // Otherwise set the user var 
      // It may still be undefined if a uniqueness error occurred; 
      // this will just cause doUntil to run this function again 
      else { 
       user = _user; 
       return cb(); 
      }     
     }, 

    // If we have a user, we are done. Otherwise go again. 
    function test() {return user}, 

    // We are done! 
    function done(err) { 
     if (err) {return res.serverError(err);} 
     // "user" now contains the found or created user 
    } 

}); 

Non è il più bello, ma dovrebbe fare il trucco.

+0

OK, grazie per lo snippet. Ho implementato qualcosa del genere con un massimo di tentativi per evitare potenziali loop infiniti. – SuperSkunk