NodeJS e Mongo – Comportamenti imprevisti quando più utenti inviano richieste simultaneamente

Abbiamo usato NodeJS e mongo (tramite mangusta) per fare un semplice save (). Abbiamo un modello chiamato “highlights” che contiene un array di oggetti che fanno riferimento a “risposte”.

Questo è il segmento rilevante della dichiarazione del modello di evidenziazione

var highlightSchema = Schema({ [...] , responses: [{type: ObjectId, ref: 'Response'}] [...] }); 

Inseriamo una risposta in una evidenziazione salvando prima un object risposta, quindi spostandolo in un object Evidenziazione, quindi salvando l’object Evidenzia. Molto semplice, come segue:

  Highlight.findOne({[...]}, function(err, highlight) { var response = new Response({[...]}); response.save(function(err) { if(!err) { highlight.responses.push(response) highlight.save(function(err) { [...] }) } }); }); 

Questo funziona circa il 99% + del tempo esattamente come previsto. (nota: si può tranquillamente presumere che la variabile “evidenziazione” nel codice precedente contenga un object di evidenziazione valido)

Tuttavia, stiamo sperimentando sempre più problemi isolati durante le ore di punta, poiché molte di queste esatte richieste vengono eseguite contemporaneamente. In un caso, una risposta è stata creata correttamente, ma una risposta DIVERSA è stata inserita nell’array highlight.responses.

I timestamp di queste due risposte hanno dimostrato che sono stati creati a una distanza di circa 30 millisecondi. Tutto è stato creato esattamente come previsto, ad eccezione del contenuto degli array all’interno degli oggetti di evidenziazione.

Dato che attualmente sto approfondendo molte cose dei sistemi operativi, il mio primo pensiero è che questo potrebbe essere un problema con la sincronizzazione di qualche tipo. Ma il nodo è single-threaded, e non mi sembra di avere una buona conoscenza di come funziona il ciclo degli eventi di nodejs, né sono assolutamente sicuro che questo sia il problema in primo luogo.

Per favore fatemi sapere se avete qualche idea, o se sto spiegando questo chiaramente abbastanza. Sono felice di elaborare.

Grazie!

Stai riscontrando un problema di concorrenza. Il modo in cui i tuoi schemi sono modellati non garantisce l’atomicità, quindi i problemi che stai riscontrando.

L’opzione migliore per evitare tali problemi e garantire l’atomicità, sarebbe quella di annidare il modello Responses nel modello Highlights.

In questo modo lavoreresti solo con il modello Highlights spingendo un elemento Response direttamente nella proprietà Responses del modello Highlight.

Questo è l’unico modo per garantire l’atomicità con MongoDB.

Quindi avresti qualcosa di simile a questo:

  +----------------------+ | Highlight model | +----------------------+ | _id 1 | | | | property 1: 'abc' | | property 2: 'bla' | | property 3: 123 | | responses:[ | | +----------------+ | | | Response _id 1 | | | +----------------+,| | | Response _id 2 | | | +----------------+,| | | Response _id 3 | | | +----------------+,| | | Response _id n | | | +----------------+]| +----------------------+ 

Non sei sicuro di come lo fai con Mongoose, ma nella shell di mongo se volessi aggiungere una risposta all’object Highlight con _id ObjectId (‘1234’) avresti fatto qualcosa di simile a questo:

  db.highlights.update({_id: ObjectId('1234')},{$push:{Responses: {"Your response object"}}}); 

$ spingere riferimento dalla documentazione MongoDB

Sono abbastanza sicuro che tu debba essere in grado di farlo con Mongoose in un modo più semplice, probabilmente solo una questione di sfogliare la sua documentazione.

Per annidare il modello potresti scrivere lo schema in questo modo

 const ResponseSchema = require('../where your schema file is') var highlightSchema = Schema({ [...] , responses: [ResponseSchema] [...] });