2016-10-24 4 views
0

Ich habe eine Meteor-App, die den Text eines Artikels nimmt und in Absätze, Sätze, Wörter und Zeichen aufteilt und diese dann in einem JSON speichert, das ich dann als Dokument in einer Sammlung speichern kann. Das Dokument, das ich gerade testet, endet jetzt als 15133 Bytes in mongodb.Was könnte dazu führen, dass eine Meteor App manchmal zwei Dokumente erstellt?

Wenn ich das Dokument einfüge, dauert es ungefähr 20 oder 30 Sekunden, um es einzufügen. Dann beginnt es manchmal meine Artikelerstellungsroutine erneut und fügt ein anderes Dokument ein. Manchmal werden 3 oder mehr Dokumente eingefügt. Manchmal verhält es sich wie es sollte und fügt nur 1 Dokument in die Sammlung ein.

Was sollte ich suchen, die dieses Verhalten verursachen könnte?

Hier ist mein Code, wie gewünscht:

Meteor.methods({ 
'createArticle': function (text, title) { 
    var article = {} 
    article.title = title 
    article.userID = "sdfgsdfg" 
    article.text = text 
    article.paragraphs = [] 
    var paragraphs = splitArticleIntoParagraphs(text) 
    console.log("paragraphs", paragraphs) 
    _.each(paragraphs, function (paragraph, p) { 
     if (paragraph !== "") { 
      console.log("paragraph", paragraph) 
      article.paragraphs[p] = {} 
      article.paragraphs[p].read = false 
      article.paragraphs[p].text = paragraph 
      console.log("paragraphs[p]", article.paragraphs[p]) 
      var sentences = splitParagraphIntoSentences(paragraph) 
      article.paragraphs[p].sentences = [] 
     } 
     _.each(sentences, function (sentence, s) { 
      if (sentence !== "") { 
       article.paragraphs[p].sentences[s] = {} 
       console.log("sentence", sentence) 
       article.paragraphs[p].sentences[s].text = sentence 
       article.paragraphs[p].sentences[s].read = false 
       console.log("paragraphs[p].sentences[s]", article.paragraphs[p].sentences[s]) 
       var wordsForward = splitSentenceIntoWordsForward(sentence) 
       console.log("wordsForward", JSON.stringify(wordsForward)) 
       article.paragraphs[p].sentences[s].forward = {} 
       article.paragraphs[p].sentences[s].forward.words = wordsForward 

       // var wordsReverse = splitSentenceIntoWordsReverse(sentence) 
       _.each(wordsForward, function (word, w) { 
        if (word) { 
         // console.log("word", JSON.stringify(word)) 
         // article.paragraphs[p].sentences[s] = {} 
         // article.paragraphs[p].sentences[s].forward = {} 
         // article.paragraphs[p].sentences[s].forward.words = [] 
         article.paragraphs[p].sentences[s].forward.words[w] = {} 
         article.paragraphs[p].sentences[s].forward.words[w].wordID = word._id 
         article.paragraphs[p].sentences[s].forward.words[w].simp = word.simp 
         article.paragraphs[p].sentences[s].forward.words[w].trad = word.trad 
         console.log("word.simp", word.simp) 
         var characters = word.simp.split('') 
         console.log("characters", characters) 
         article.paragraphs[p].sentences[s].forward.words[w].characters = [] 
         _.each(characters, function (character, c) { 
          if (character) { 
           console.log("character", character, p, s, w, c) 
           article.paragraphs[p].sentences[s].forward.words[w].characters[c] = {} 
           article.paragraphs[p].sentences[s].forward.words[w].characters[c].text = character 
           article.paragraphs[p].sentences[s].forward.words[w].characters[c].wordID = Words.findOne({simp: character})._id 
          } 
         }) 
        } 
       }) 
      } 
     }) 
    }) 
    // console.log("article", JSON.stringify(article)) 
    // console.log(JSON.stringify(article.paragraphs[10].sentences[1].forward))//.words[4].characters[0]) 
    console.log("done") 
    var id = Articles.insert(article) 
    console.log("id", id) 
    return id 
} 
}) 

Ich rufe die Methode hier:

Template.articleList.events({ 
"click #addArticle": function(event) { 
    event.preventDefault(); 
    var title = $('#title').val(); 
    var text = $('#text').val(); 
    $('#title').value = ''; 
    $('#text').value = ''; 
    $('#text').attr('rows', '3'); 
    Meteor.call('createArticle', text, title); 
} 
}) 
+0

Bitte bearbeiten Sie Ihre Frage und fügen Sie die entsprechenden Codes hinzu. – Luna

+0

können Sie prüfen, ob es _.each() (alle) wartet, bevor Sie den Artikel einfügen? Das ist wahrscheinlich der Schuldige hier. Fügen Sie auch hinzu, wo Sie die Methode aufrufen, nur für den Fall – Luna

+0

Hinzugefügt den Methodenaufruf. Also, sagst du, dass ich den Artikel einfügen und dann aktualisieren soll, wie es durch den _each geht? Es dauert ungefähr 20 bis 30 Sekunden nach dem 'console.log (" done ")' – webmagnets

Antwort

2

Eine wichtige Sache im Auge zu behalten ist, dass Meteor Methoden nicht funktionieren sehr gut, wenn es kommt zu CPU-intensiven Aufgaben. Da Ihr Meteorserver nur in einem einzigen Thread arbeitet, werden alle Arten von Blockierungsberechnungen - wie Ihres - alle Clientverbindungen beeinflussen, z. Verzögern von DDP-Takten. Dies wiederum kann dazu führen, dass Clients denken, dass die Verbindung unterbrochen wurde.

Wie @ghybs in einem der Kommentare vorgeschlagen, wird Ihre Methode wahrscheinlich mehrmals von einem ungeduldigen DDP-Client ausgelöst, der denkt, dass der Server die Verbindung getrennt hat. Der einfachste Weg, um dieses Verhalten zu verhindern, ist durch Zugabe von noRetry Flagge zu Meteor.apply wie hier erklärt:

https://docs.meteor.com/api/methods.html#Meteor-apply

Ich glaube Meteor.call diese Option nicht hat.

Eine andere Strategie wäre, zu versuchen, dass Ihre Methoden idempotent sind, d. H. Sie mehr als einmal aufzurufen, sollte keine zusätzlichen Effekte erzeugen. Dies ist normalerweise der Fall - zumindest wenn Sie die Methodensimulation verwenden - da das Wiederholen von DB-Einfüge das gleiche Dokument id wiederverwendet, das beim zweiten Versuch fehlschlägt. Aus irgendeinem Grund passiert dies in Ihrem Fall nicht.

Schließlich zeigt das von Ihnen beschriebene Problem, dass wahrscheinlich ein anderes Muster für eine rechenintensive Aufgabe wie Ihre verwendet werden sollte. Wenn ich Sie wäre, würde ich den Job in mehreren Schritten aufteilen:

  • Zuerst würde ich sicherstellen, dass das Dokument auf den Server mit einer POST-Anfrage statt über DDP hochgeladen wird.
  • Dann würde ich eine serverseitige Methode "Prozessdatei" implementieren, die die Datei ergreift, die sich bereits auf dem Server oder in der Datenbank befindet (falls Sie die Dateisammlung verwendet haben). Das erste, was die Methode tun sollte, würde this.unblock() aufrufen, aber das ist nicht alles.
  • Idealerweise sollte die Rechenaufgabe in einem getrennten Prozess ausgeführt werden. Nur wenn dieser Prozess abgeschlossen ist, gibt die Methode den tatsächlichen Aufrufer zurück, dass der Job erledigt ist. Aber seit wir this.unblock() angerufen haben, kann der Anrufer verschiedene Aufgaben ausführen, z.B. andere Methoden/Subskriptionen aufrufen, während auf das Ergebnis gewartet wird.
  • Manchmal ist ein separater Prozess nicht gut genug.Ich habe Situationen erlebt, in denen ich die Aufgabe an einen anderen Worker-Server delegieren musste.

    +0

    Es funktioniert auf der Client-Seite. Der Grund dafür, dass ich mehr als 20 Sekunden zum Einfügen benötigte, war, dass ich die Daten mit dem SimpleSchema-Paket validierte. Ich hörte damit auf und die Einführungszeit war fast augenblicklich. – webmagnets

    Verwandte Themen