Laden...

Offline App - Handling fehlgeschlagener / abgebrochener Datensynchronisation

Erstellt von UndercoverDeveloper vor 6 Jahren Letzter Beitrag vor 6 Jahren 1.970 Views
U
UndercoverDeveloper Themenstarter:in
16 Beiträge seit 2015
vor 6 Jahren
Offline App - Handling fehlgeschlagener / abgebrochener Datensynchronisation

Hallo zusammen,

ich habe mal eine Frage in die Runde. Wir arbeiten zurzeit in einem kleinen Team an einer iOs / Android App auf Basis von Xamarin.Froms. Einsatzzweck dieser App ist im Bereich des Vertriebs-Außendiensts. Das heißt, ein Außendienstmitarbeiter besucht Märkte / Standorte, macht dort verschiedene Dinge und reportet das ganze über die App. Dabei ist es extrem wichtig das die App immer funktioniert, also auch wenn keine Internetverbindung besteht.

Als Backend haben wir uns daher für Microsoft Azure App Services entschieden. Azure bietet eben genau diese Offline-Synchronisation. Alle Daten liegen lokal und werden bei bestehender Internetverbindung mit dem Server synchronisiert. Die Datenhaltung auf dem Server geschieht über einen SQL Server 2016 und auf dem Endgerät wird SQLLite verwendet. Der Datenabgleich muss explizit vom Anwender gestartet werden, hierfür gibt es einen Button in der App.

Die Problemstellung:

Jede Tabelle wird einzeln beim Server angefragt und heruntergeladen. In der Regel kann eine Tabelle auch nicht komplett auf einmal heruntergeladen werden weil es zu viele Daten sind. Pro Tabelle können auch mehrere Zugriffe auf den Server notwendig sein.

Azure App Services bietet keine Möglichkeit diese Anfragen in einer Transaktion zu bündeln und gegebenenfalls einen Rollback auszuführen. Bricht der Datenabgleich (wieso auch immer) mittendrin ab kann es passieren das der Datenbestand auf dem Endgerät inkonsistent ist und die App daher nicht verwendet werden kann. Die Datenbankstruktur ist recht komplex und der Normalisierungs-Grad der Datenbank recht hoch, was bedeutet das es viele Abhängigkeiten zwischen den Tabellen gibt und nicht einfach alle zusammengehörige Daten in einer Tabelle stehen. Wenn z.B Tabelle A erfolgreich heruntergeladen wird aber Tabelle B nicht, können Daten aus Tabelle A nicht verwendet werden weil eben unvollständig.

Unsere Lösungsansätze:

  1. Läuft die Datensynchronisation nicht erfolgreich bis zum Ende durch wird die App gesperrt und der Anwender wird dazu aufgefordert die Datensynchronisation zu wiederholen bis sie erfolgreich war.

Bewertung: Das ist eigentlich ein Nogo. Nehmen wir an, der Außendienstmitarbeiter steht vor dem Markt und raucht gerade noch eine und denkt sich das er in dieser Zeit doch kurz mal einen Datenabgleich ausführen könnte. Dieser bricht aber ständig aufgrund der schlechten Internetverbindung ab. Jetzt steht der Außendienstmitarbeiter im Markt und kann die App nicht verwenden weil diese gesperrt ist.

  1. Wir bauen eine Logik in die App ein welche prüft ob ein Datensatz verwendet werden kann. Soll z.B auf einen Datensatz in Tabelle A zugegriffen werden muss zu nächst geprüft werden ob die passenden Relations in Tabelle B, C, D, E, F und G vorhanden sind. Wahrscheinlich müssen hierzu auch "Checksums" in der Serverdatenbank hinterlegt werden. Es gibt z.B die Möglichkeit in der App einen Fragebogen auszufüllen. Das macht aber nur Sinn wenn dieser auch vollständig heruntergeladen wurde. Also muss auch irgendwo hinterlegt sein was der Fragebogen alles beinhaltet. Außerdem muss natürlich bei JEDEM Objektzugriff überprüft werden ob irgendetwas Null ist damit es zu keinem Fehler kommt.

Bewertung: Ich denke es ist ersichtlich das sowas recht kompliziert ist und daher fehleranfällig. Für jeden Datentyp müssen individuelle Prüfroutinen geschrieben werden da sich diese nicht verallgemeinern lassen. Außerdem ist es sehr wahrscheinlich das hier schnell mal was übersehen wird und dann kommt es am Ende doch wieder zu einem Fehler in der App. Um hier keinen Fehler zu machen ist es sehr wichtig den Code gut zu kennen und vor allem die Datenbankstruktur, was die Einarbeitung neuer Programmierer in dieses Projekt zu einer sehr großen Herausforderung werden lässt.

Jetzt würde ich gerne euch fragen ob ihr eine Idee habt wie man so etwas handeln kann. Ich denke das die Problemstellung von der verwendeten Technik losgelöst ist und es sich mehr um eine generelle Softwaredesign - Frage handelt. Wie würdet ihr an dieses Problem heran gehen?

Wir freuen uns über jeden Input zu diesem Thema. Vielen Dank 😃

D
985 Beiträge seit 2014
vor 6 Jahren

Du kannst den Abgleich auf einer Kopie der sqlite Datenbank machen. Ist der Abgleich erfolgreich, dann das Original mit der Kopie austauschen.

Alternativ würde auch eine Transaction auf der sqlite Datenbank gehen, die vor dem Abgleich gestartet und beim Abschluss dann geschlossen wird.

D
7 Beiträge seit 2017
vor 6 Jahren

Wir verwenden eine Dokumenten-Basierte bzw. noSQL-Datenbank.

Die Dokumente ("Tabellen-Einträge") enthalten entsprechend Redundanzen um die Abhängigkeiten zu anderen Dokumenten zu minimieren.
Beispiel: Jedes Dokument "Standort" enthält die Region als Text (und nicht nur einen Verweis auf das Region-Dokument).

Die Bidirektionale Replikation/Synchronisierung wie auch das Konfliktmanagement sind dadurch viel einfacher.
Die App kann zudem mit "Teilweise Synchronisierten" Daten umgehen.

121 Beiträge seit 2016
vor 6 Jahren

Wir verwenden eine Dokumenten-Basierte bzw. noSQL-Datenbank.

Ich frage mich, wie das dem OP helfen soll. Die App (inkl. Backend) existiert ja schon und so weit ich das verstanden habe steht ein Wechsel der Datenbank nicht zur Diskussion ?(

U
UndercoverDeveloper Themenstarter:in
16 Beiträge seit 2015
vor 6 Jahren

Wir verwenden eine Dokumenten-Basierte bzw. noSQL-Datenbank.

Ich frage mich, wie das dem OP helfen soll. Die App (inkl. Backend) existiert ja schon und so weit ich das verstanden habe steht ein Wechsel der Datenbank nicht zur Diskussion ?(

Richtig. Wir haben eine bestehende SQL - Datenbank die wiederverwendet werden muss. Da jetzt noch irgendeine Middleware zu schreiben die zwischen einer App spezifischen NoSql Datenbank und der eigentlichen SQL-Datenbank übersetzt wäre zuviel des guten. Trotzdem ist das natürlich ein guter Hinweis für die Zukunft falls wir mal eine App auf einer komplett neuen Datenbank entwickeln.

@Sir Rufo:
Ich werde deinen ersten Vorschlag ausprobieren 😃 Das hatten wir gestern im Team schon einmal so ähnlich diskutiert aber zu schnell verworfen weil es zu "dirty" klang. Aber es könnte wirklich eine gute Lösung sein. Man hat natürlich immer etwas Performance Overhead für das erstellen einer neuen SqlLite Datenbank.

Der zweite ist glaube ist nicht so leicht umsetzbar. Das Azure SqlLite SDK (Microsoft.WindowsAzure.MobileServices.SQLiteStore.MobileServiceSQLiteStore) hat nicht so tiefgehende Funktionalitäten um eine Transaktion zu starten. Hier bräuchte ich wieder ein extra SQLLite Framework. Und ich weiß nicht ob sich das dann mit dem Azure SqlLite SDK streitet.

Danke 😃

16.841 Beiträge seit 2008
vor 6 Jahren

Ich bin ein sehr großer Freund von Azure, aber ich bin kein Freund der Azure Mobile Services.

Die Azure Mobile Services basieren aktuell auf einem veralteten ASP.NET 4 Stack und bislang gibts keine Ansage, wann sich das ändert - oder ob das überhaupt aktualisiert wird.
Zudem vergewaltigt in meinen Augen die Middleware der Azure Mobile Services den ASP.NET Stack / Pipeline sehr.
zB. funktioniert einfach das Routing in ASP.NET nicht mehr, weil die Middleware was eigenes mitbringt.
Wir haben hier ein eigenes Client-seitiges SDK geschrieben, das dann dann die REST-Fähigkeit überhaupt wieder herstellt.
AMS will zudem immer einen Custom Header, (ZUMO Header, Easy Auth) was das Testen unheimlich aufwendig macht.
Ich hatte jetzt leider erst ein Projekt mit AMS und habe es an vielen Stellen verflucht.
Wer es sich leisten kann, AMS nicht zu nutzen, der sollte das auch nicht tun..

Der Entwickler hinter dem "Easy Auth", das AMS auch nutzt, ist mittlerweile auch kein Microsoftie mehr. Er wurde seinen Tweets zufolge entlassen, was die Folge hatte, dass er auch alle GitHub Beispiele entfernt hatte.
Viel andere Beispiele gabs aber nicht und auch waren die meisten Stackoverflow Antworten nach genau diesem Thema großteils von ihm, was zumindest bei mir den Eindruck hinterließ, dass das ne ziemliche One Man Show war und es daher zumindest zu diesem Zeitpunkt fast keine Beispiele mehr gibt. Ich hatte jetzt Gott sei dank direkte MS Kontakte, die mir dann noch an der ein oder anderen unklaren Stelle geholfen haben, denn in meinen Augen ist die Doku einfach nicht gut.

AMS ist sicherlich toll, wenn man schnell was bauen will; ich halte es für ein Real World Szenario aber nicht für so dolle. Ich finde es behindert an vielen Stellen extrem und macht auch übliche Themen (Hypermedia, REST) sehr kompliziert bis unmöglich.
Auf GitHub gibts auch schon Nachfragen, ob das Environment überhaupt noch weiterentwickelt wird.

Im Prinzip ist das kein Mobil-exklusives Thema, sondern nur ein Thema, wie Du Daten an eine API senden kannst und dabei die Gültigkeit der Daten beachten kannst.
IM Prinzip verfolgt man bei APIs das Optimistic Currency Prinzip, das mir in Deinem Fall ebenfalls als geeignet erscheint.

Sprich jeder Deiner Datensätze hat einen Timestamp, wann der letzte Edit erfolgte.
Wenn Du Dir Daten holst, dann wird dieser Timestamp mit an den Client gegeben.
Der Client muss beim Submit an die API diesen Timestamp mitgeben.

Ändert sich der Timestamp zwischenzeitlich, dann wird die Abfrage abgelehnt und der Client muss ggfls. die Daten überprüfen und mit dem neuen Timestamp schicken.
Im Prinzip kannst Du vollständig auf diese Logik zurückgreifen, um das Gesamtproblem zu lösen.

Gegenüber der Logik, die Du beschreibst, gibt es keine pauschale Lösung.
Da musst Du tatsächlich einen entsprechenden Service (Business Logik Service) schreiben, der sich um solche Gegebenheiten kümmert.

D
7 Beiträge seit 2017
vor 6 Jahren

Ich frage mich, wie das dem OP helfen soll. (...)

Trotzdem ist das natürlich ein guter Hinweis für die Zukunft falls wir mal eine App auf einer komplett neuen Datenbank entwickeln.

Genau - war einfach als Input gedacht da es sich sehr gut bewährt hat.