0

Ich versuche Echtzeit-Updates mit Cloud Firestore in C# unter Verwendung Google.Cloud.Firestore.V1Beta1 zu abonnieren. Ich verwende den folgenden Code, der für kurze Zeit Updates erhält, bis der Stream geschlossen wird. Hat jemand FirestoreClient.Listen zu arbeiten?Firestore Real-Time-Updates in C#

// Create client 
FirestoreClient firestoreClient = FirestoreClient.Create(); 

// Initialize streaming call, retrieving the stream object 
FirestoreClient.ListenStream duplexStream = firestoreClient.Listen(); 

// Create task to do something with responses from server 
Task responseHandlerTask = Task.Run(async() => 
{ 
    IAsyncEnumerator<ListenResponse> responseStream = duplexStream.ResponseStream; 
    while (await responseStream.MoveNext()) 
    { 
     ListenResponse response = responseStream.Current; 
     Console.WriteLine(response); 
    } 
}); 

// Send requests to the server 

var citiesPath = string.Format("projects/{0}/databases/{1}/documents/cities/CJThcwCipOtIEAm2tEMY", projectId, databaseId); 

// Initialize a request 
var dt = new DocumentsTarget { }; 
dt.Documents.Add(citiesPath); 

ListenRequest request = new ListenRequest 
{ 
    Database = new DatabaseRootName(projectId, databaseId).ToString(), 
    AddTarget = new Target 
    { 
     Documents = dt 
    } 
}; 
// Stream a request to the server 
await duplexStream.WriteAsync(request); 

// Await the response handler. 
// This will complete once all server responses have been processed. 
Console.WriteLine("Awaiting responseHandlerTask"); 
await responseHandlerTask; 

Edit 1: Ich habe versucht, explizit verfallen nie das Ablauf Einstellung, aber noch kein Glück, erhalte ich dann 5 Minuten in eine RST_STREAM erhalten.

//Setup no expiration for the listen 
CallSettings listenSettings = CallSettings.FromCallTiming(CallTiming.FromExpiration(Expiration.None)); 

// Initialize streaming call, retrieving the stream object 
FirestoreClient.ListenStream duplexStream = firestoreClient.Listen(listenSettings); 

Edit 2: Es scheint wie ein bisschen eine Flickschusterei, aber ich fand es den Überblick über die letzten resetToken zu halten arbeitet, die Ausnahme abfangen, dann starten Sie den Antrag mit den Anforderungs-Token. Ich habe den Code aktualisiert, der die ursprüngliche Anfrage auf ein optionales resumeToken stellt.

ListenRequest request = new ListenRequest 
{ 
    Database = new DatabaseRootName(projectId, databaseId).ToString(), 
    AddTarget = new Target 
    { 
     Documents = dt 
    } 
}; 

if (resumeToken != null) 
{ 
    Console.WriteLine(string.Format("Resuming a listen with token {0}", resumeToken.ToBase64())); 
    request.AddTarget.ResumeToken = resumeToken; 
} 

// Stream a request to the server 
await duplexStream.WriteAsync(request); 

Es ist nicht perfekt, aber ich denke, es ist die Art, wie Google es in Node.js implementiert hat. Es führt alle 5 Minuten zu einem API-Aufruf, so dass einige Kosten entstehen. Vielleicht ist das der Grund, warum es so funktioniert?

Dank

+0

Nur als Anmerkung, werde ich diese API in Google.Cloud.Firestore zu implementieren, hoffentlich in diesem Quartal. Achten Sie auf den Fortschritt: https://github.com/GoogleCloudPlatform/google-cloud-dotnet/issues/1618 –

Antwort

0

Bis Jon die offizielle Unterstützung abgeschlossen ist, können Sie etwas, das ich zusammen, wenn Sie es sofort benötigen. https://github.com/cleversolutions/FirebaseDotNetRamblings/blob/master/FirebaseDocumentListener.cs Sein eine Erweiterungsmethode Sie können in Ihr Projekt fallen lassen und wie diese verwenden:

//Create our database connection 
FirestoreDb db = FirestoreDb.Create(projectId); 

//Create a query 
CollectionReference collection = db.Collection("cities"); 
Query qref = collection.Where("Capital", QueryOperator.Equal, true); 

//Listen to realtime updates 
FirebaseDocumentListener listener = qref.AddSnapshotListener(); 

//Listen to document changes 
listener.DocumentChanged += (obj, e) => 
{ 
    var city = e.DocumentSnapshot.Deserialize<City>(); 
    Console.WriteLine(string.Format("City {0} Changed/Added with pop {1}", city.Name, city.Population)); 
};