2016-04-22 1 views
1

Dies ist eine ziemlich seltsame Sache, und es ist schwer zu reproduzieren. Nicht der beste Zustand eines Fehlerberichtes, entschuldige ich mich.Firebase-Transaktionen kehren viel später zurück?

Ich verwende .transaction(), um einen Wert an einen Speicherort in Firebase zu schreiben. Hier einige Pseudo-Code:

  • Shop ein Wert an einer Stelle über die Transaktion:

    var ref = firebase.child('/path/to/location'); 
    
    var storeSafely = function(val) { 
        ref.transaction(
        function updateFunc(currentData) { 
         console.log('Attempting update: ' + JSON.stringify(val)); 
    
         if (currentData) return; 
    
         return val; 
        }, 
        function onTransactionCompleteFunc(err, isCommitted, snap) { 
         if (err) { 
         console.log('Error in onTransactionCompleteFunc: ' + JSON.stringify(err)); 
         return; 
         } 
    
         if (! isCommitted) { 
         console.log('Not committed'); 
         return; 
         } 
    
         ref.onDisconnect().remove(); 
         doSomeStuff(); 
        }); 
    }; 
    
    var doSomeStuff = function() { 
        // Things get done, time passes. 
    
        console.log('Cleaning up'); 
        ref.onDisconnect().cancel(); 
        ref.set(
        null, 
        function onSetCompleteFunc(err) { 
         if (err) { 
         console.log('Error in onSetCompleteFunc: ' + JSON.stringify(err)); 
         } 
        }); 
    }; 
    
    storeSafely(1); 
    // later... 
    storeSafely(2); 
    // even later... 
    storeSafely(3); 
    

    ich effektiv Firebase Transaktionen als eine Art Mutex-Sperre verwenden.

  • Setzen Sie den OnDisconnect für den Standort, um den Wert zu entfernen, falls meine App während der Arbeit stirbt.

  • Tun Sie etwas.

  • Entfernen Sie die OnDisconnect für den Standort, weil ich mit dem Zeug fertig bin.

  • Entfernen Sie den Wert an der Stelle.

Ich mache das alle paar Minuten, und es funktioniert alles super. Dinge werden perfekt geschrieben und entfernt, und die Logs zeigen mir, wie ich das Schloss erstelle, Sachen mache und dann das Schloss loslasse.

Der seltsame Teil ist, was passiert Stunden später. Gelegentlich hat Firebase Wartung, und meine App erhält eine Reihe von Berechtigungen verweigert Fehler. Zur gleichen Zeit dies geschieht, beginne ich plötzlich ein paar diese Ausgabe in den Protokollen erhalten:

Attempting update 1 
Attempting update 2 
Attempting update 3 

... in anderen Worten, es sieht aus wie die Transaktionen nicht vollständig abgeschlossen, und sie versuchen, erneut zu versuchen Jetzt kann der Ort nicht mehr gelesen werden. Es ist fast so, als würde der transaction() - Code, der nie abgeschlossen wurde, geschlossen, und er wird jetzt aus irgendeinem Grund erneut ausgeführt.

Fehle mir hier etwas wirklich Wichtiges darüber, wie man eine Transaktion beendet?

(Anmerkung:.. Ich gepostet ursprünglich auf die Firebase Google-Gruppe, wurde aber daran erinnert, schließlich, dass Code Fragen sollen, Stack-Überlauf gehen ich entschuldige mich für die Cross-Posting)

Antwort

0

Nur eine Vermutung , aber ich frage mich, ob Ihre updateFunc() Funktion mit null aufgerufen wird, wenn Ihre App die Berechtigung verweigert Fehler von Firebase erhält. (Wenn ja, könnte ich glauben, dass das Teil ihrer "Offline Writes" Unterstützung ist.)

In jedem Fall sollten Sie null als möglichen Zustand behandeln. Saving Transactional Data sagt:

transaction() wird mehrmals aufgerufen werden und muss null Daten verarbeiten können. Auch wenn vorhandene Daten in Ihrer Datenbank vorhanden sind, kann es nicht lokal zwischengespeichert werden, wenn die Transaktionsfunktion ausgeführt wird.

Ich weiß nicht, die Feinheiten der Transaktion mechansim des Firebase, aber ich würde Ihre .set(null) auf den Wert auf 0 stattdessen versuchen, zu ändern, Ihre .remove() ändern auch den Wert mit .set(0) auf, und Ihre Linie in updateFunc() ändern zu:

if (currentData === null || currentData) return; 

Leider geht davon aus, dass die '/path/to/location' zunächst auf 0 an einem gewissen Punkt gesetzt wird. Wenn das ein Problem ist, können Sie vielleicht mit null gegenüber undefined herumspielen. Zum Beispiel wäre es schön, wenn Firebase einen dieser für nicht vorhandene Daten und einen anderen verwendet, wenn es offline ist.