Datenbank synchronisieren
Moderator: LiMuBei
- LiMuBei
- J:I Chief
- Beiträge: 1415
- Registriert: Sonntag 23. Januar 2005, 18:44
- Wohnort: Karlsruhe
- Kontaktdaten:
Mein Gedanke war halt, dass man die Synchronisationsanfragen über den Chat-Kanal schickt. So nach dem Motto: "Ich habe Liste X mit Timestamp Y, hat jemand was neueres?" Falls jemand was neueres hat, postet er seinen Timestamp in den Chat. Der fragende such sich dann den mit dem neuesten Timestamp raus und fragt ihn per tell nach Aktualisierung, die der dann auch wieder per tell zurückschickt. Dadurch dass jeder seinen Timestamp in den Chat postet, sehen andere unter Umständen auch dass sie nicht mehr aktuell sind und können den neuesten nach Aktualisierung fragen.
Das würde meiner Meinung nach den Traffic reduzieren, weil eben nur noch kurze Anfragen über den Chat gehen und auch nur dann ne Liste verschickt wird wenn sie wirklich benötigt wird. Zusätzlich braucht man auch nur einen Timestamp pro Liste.
Ist jetzt nicht vollständig durchdacht, vielleicht gibt es gravierende Nachteile an dieser Idee...
Das würde meiner Meinung nach den Traffic reduzieren, weil eben nur noch kurze Anfragen über den Chat gehen und auch nur dann ne Liste verschickt wird wenn sie wirklich benötigt wird. Zusätzlich braucht man auch nur einen Timestamp pro Liste.
Ist jetzt nicht vollständig durchdacht, vielleicht gibt es gravierende Nachteile an dieser Idee...
Against logic there is no armor like ignorance.
- Behemoth
- Initiative Big Boss
- Beiträge: 1827
- Registriert: Donnerstag 10. Februar 2005, 14:48
- Wohnort: Karlsruhe
Problem wäre dann: du änderst lokal was an deiner Liste, und bekommst danach (in einer größeren Gilde) Dutzende von Anfragen, an die alle die gleichen Daten verschickt werden. Was Traffic zum Server angeht, ist das ja wesentlich schlechter, als Broadcast - ist ja kein Unterschied von meiner Seite aus, ob eine Nachricht im allgemeinen Channel oder im Whisper versendet wird.
Klar könnte man den Fall dann mit der alten Methode abfangen, aber hätte dann auch entsprechend zwei verschiedene Sync-Methoden, je nach dem, was sich ändert.
Klar könnte man den Fall dann mit der alten Methode abfangen, aber hätte dann auch entsprechend zwei verschiedene Sync-Methoden, je nach dem, was sich ändert.
Look at me, I'm invisible!
- Magic
- WoW Dictionary
- Beiträge: 1650
- Registriert: Donnerstag 10. Februar 2005, 15:35
- Wohnort: Tübingen
Hey, könntest du mir eine "Starthife" geben? Ich habe letztens mal geschaut, was für Dateien alles dazu gehören, und die kurz überflogen. Neben Code sind ja auch noch Spezifikationsdateien für z.B. frames dabei, wenn ich das richtig in Erinnerung habe. Wo fange ich am besten an zu gucken? Bei den events OnLoad und noch so eins?
Ilyrielle - Mage
- Magic
- WoW Dictionary
- Beiträge: 1650
- Registriert: Donnerstag 10. Februar 2005, 15:35
- Wohnort: Tübingen
Noch eine Frage, wo der Verdopplungsfehler eigentlich auftritt. Da gibt es ja mehrere Möglichkeiten:
- beim Ersteller: Besitzer hat bereits doppelte Infos und verschickt diese.
- beim Empfänger: Verdopplung entsteht durch die Übertragung.
- bei der Anzeige: Daten sind überall korrekt gespeichert.
Es ist sicher, dass es sich um Fall 2 handelt, ja?
- beim Ersteller: Besitzer hat bereits doppelte Infos und verschickt diese.
- beim Empfänger: Verdopplung entsteht durch die Übertragung.
- bei der Anzeige: Daten sind überall korrekt gespeichert.
Es ist sicher, dass es sich um Fall 2 handelt, ja?
Ilyrielle - Mage
- Behemoth
- Initiative Big Boss
- Beiträge: 1827
- Registriert: Donnerstag 10. Februar 2005, 14:48
- Wohnort: Karlsruhe
Fall 1 wird sich natürlich verbreitern, also wenn jemand schon neuere falsche Daten hat, dann wird er die natürlich auch weiter geben. Anzeige müsste stimmen.
Ich sehe den Schwerpunkt bei Fall 2. Ich vermute, dass es zumindest zum Teil daran liegt, dass nicht alle die Items in der gleichen Reihenfolge haben (sind auf deutschem und englischen Client unterschiedlich sortiert). Wenn da dann irgendwas beim Synchronisieren dazwischen kommt, könnte das eine Ursache sein. Wobei das aber eher eine Erklärung dafür wäre, dass Gegenstände sich "verdoppeln" in dem sie andere "überschreiben". Aber das ist ja nicht der Fall (so weit ich weiß), sondern auch wenn man nur einen Gegenstand drin hat, hat man den irgendwann mehrmals drin.
Hm, mir ist gerade eine mögliche Fehlerquelle aufgefallen... nacher mal kucken.
Ich sehe den Schwerpunkt bei Fall 2. Ich vermute, dass es zumindest zum Teil daran liegt, dass nicht alle die Items in der gleichen Reihenfolge haben (sind auf deutschem und englischen Client unterschiedlich sortiert). Wenn da dann irgendwas beim Synchronisieren dazwischen kommt, könnte das eine Ursache sein. Wobei das aber eher eine Erklärung dafür wäre, dass Gegenstände sich "verdoppeln" in dem sie andere "überschreiben". Aber das ist ja nicht der Fall (so weit ich weiß), sondern auch wenn man nur einen Gegenstand drin hat, hat man den irgendwann mehrmals drin.
Hm, mir ist gerade eine mögliche Fehlerquelle aufgefallen... nacher mal kucken.
Look at me, I'm invisible!
- Magic
- WoW Dictionary
- Beiträge: 1650
- Registriert: Donnerstag 10. Februar 2005, 15:35
- Wohnort: Tübingen
Was passiert eigentlich, wenn zwei Operationen zugleich angestoßen werden? Sollte zwar unwahrscheinlich sein, aber so prinzipiell taucht das Problem ja bei vielen Anwendungen auf. Z.B. wird die Liste gerade lokal sortiert, während eine Übertragung angestoßen wird.
Die Rekursionen in GGT_AddOffer() und GGT_AddNeed() würde ich übrigens auflösen. Sollte aber an sich auch keine Probleme machen, ok.
Die Rekursionen in GGT_AddOffer() und GGT_AddNeed() würde ich übrigens auflösen. Sollte aber an sich auch keine Probleme machen, ok.
Ilyrielle - Mage
- Magic
- WoW Dictionary
- Beiträge: 1650
- Registriert: Donnerstag 10. Februar 2005, 15:35
- Wohnort: Tübingen
GGT_ValidPlayers sind diejenigen Spieler, die sich per GGT_Send_DataVersion() bei mir registriert haben, gell? Wie wird sicher gestellt, dass das nur Gildies sind? (In einer anderen Datei, nehme ich an?) GGT_ValidPlayers werden nicht mehr entfernt, bis man selbst ausloggt, ja?
Sehe ich das richtig, dass Variablen zugleich als Array und Struct verwendet werden können? Also genau gesagt ist "[1]" wohl genau so ein Struct-Eintrag wie z.B. ".sorted", ja?
Sehe ich das richtig, dass Variablen zugleich als Array und Struct verwendet werden können? Also genau gesagt ist "[1]" wohl genau so ein Struct-Eintrag wie z.B. ".sorted", ja?
Ilyrielle - Mage
- Magic
- WoW Dictionary
- Beiträge: 1650
- Registriert: Donnerstag 10. Februar 2005, 15:35
- Wohnort: Tübingen
So, bin wieder da, aber inzwischen wurde mein Rechner hier fertig installiert, also könnte ich auch wieder was arbeiten.
GGT_Handle_PlayerTime() ...
Ok, ich empfange einen timestamp zu einem player, der neuer ist als meine eigene Info, timestamp > data.timestamp.
Ich fordere die Info an mit GGT_Send_PlayerTime(data) und erwarte die neue Info, data.desiredtimetamp (sp?) = timestamp.
Nun empfange ich den gleichen timestamp zum gleichen player von einem anderen sender.
Wegen not data.lastrequesttime fordere ich die Info nochmal an mit GGT_Send_PlayerTime(data), ja?
Nun empfange ich einen noch neueren timestamp zu dem player, timestamp > data.desiredtimestamp.
Dann fordere ich die Info gleich nochmal an, oder? ^^
Vielleicht besser so:
Was passiert eigentlich bei der for-Schleife
wenn tremove ausgeführt wird? Wird ein Eintrag übersprungen? Ist aber nicht schlimm, weil GGT_RequestHandler() eh wieder aufgerufen wird, gell? Wird es 1x pro Sekunde aufgerufen? In Bezug auf "tinsert(GG_UpdateFuncs, {delay = 1, func = GGT_RequestHandler})".
GGT_Handle_Item arbeitet ja direkt in der aktuellen Liste. Na wenn das mal gut geht.
Was passiert, wenn nur eine Nachricht empfangen wurde und dann die Verbindung abbricht?
table.setn(items, totalitems) setzt die Listengröße auf das Soll, ohne dass alle Einträge vorhanden sind. Sind das dann leere Einträge?
Deine items haben eigene timestamps. Diese sind gleich dem timestamp der Liste, wenn alles gut ging. Zu Inkonsistenzen kommt es während der Übertragung/Aktualisierung. Was geschieht, wenn die Inkonsistenz nicht aufgelöst wird? In GGT_Send_PlayerData() setzt du die item-timestamps auf die der Liste, falls es Abweichungen gab, ohne darauf einzugehen. Absicht? Falls ich eine unvollständige Liste empfangen hatte und mir derzeit niemand eine aktuellere geben kann - jetzt kommt eine Anfrage auf meine Liste - ist das der Zeitpunkt, an dem meine Liste zu einer gültigen Liste gemacht wird? Was passiert eigentlich bei der Übertragung einer unvollständigen Liste? Es wird getn(data.offers) betrachtet, aber die einzelnen items werden nicht mehr geprüft.
Wie gesagt hätte ich die Übertragung der Listen etwas anders gestaltet. Sicherer erscheint es mir, die übertragene Listen erst zu puffern und nur bei Vollständigkeit die alten zu ersetzen. Oder: Man kann es auch so sehen, dass wenn es eine neue Liste gibt, dann kann ich die alte eh verwerfen (wohl nur bei Needs sinnvoll). Also statt einzelne Einträge überschreiben, erst mal alte Liste komplett weg, dann auffüllen. Sollte ich unvollständige Liste haben und jemand will diese haben, so hat er zum Schluss auch nur eine als unvollständig markierte Liste.
Noch eine Idee, falls du in der bestehenden Liste aktualisieren willst: Sortiere die items stets sprachunabhängig nach ihrer ID. Alphabetische Anzeigelisten können nebenher erstellt/abgespeichert werden. Übertragen wird auch nach der ID sortiert. Wenn eine zweite ID empfangen wird, können alle bestehenden IDs zwischen erster und zweiter empfangener ID gelöscht werden. Dieses Vorgehen ist aber eigentlich nur zu empfehlen, wenn Listen oft nicht vollständig aktualisiert werden können.
Zu guter Letzt: Fremden, unkommentierten Code durchzuschauen ist doppelt nervig, weißt ja.
GGT_Handle_PlayerTime() ...
Ok, ich empfange einen timestamp zu einem player, der neuer ist als meine eigene Info, timestamp > data.timestamp.
Ich fordere die Info an mit GGT_Send_PlayerTime(data) und erwarte die neue Info, data.desiredtimetamp (sp?) = timestamp.
Nun empfange ich den gleichen timestamp zum gleichen player von einem anderen sender.
Wegen not data.lastrequesttime fordere ich die Info nochmal an mit GGT_Send_PlayerTime(data), ja?
Nun empfange ich einen noch neueren timestamp zu dem player, timestamp > data.desiredtimestamp.
Dann fordere ich die Info gleich nochmal an, oder? ^^
Vielleicht besser so:
Code: Alles auswählen
if not data.desiredtimetamp or data.desiredtimetamp < timestamp then
data.desiredtimetamp = timestamp
end
if not data.lastrequesttime or data.lastrequesttime + GGT_AnswerDelay < time() then
GGT_Send_PlayerTime(data)
data.lastrequesttime = time()
end
Code: Alles auswählen
for i = 1, getn(GGT_RequestQueue) do
if GGT_RequestQueue[i] and GGT_RequestQueue[i].sendtime <= curtime then
GGT_Send_PlayerDataByName(GGT_RequestQueue[i].name)
tremove(GGT_RequestQueue, i)
end
end
GGT_Handle_Item arbeitet ja direkt in der aktuellen Liste. Na wenn das mal gut geht.
Was passiert, wenn nur eine Nachricht empfangen wurde und dann die Verbindung abbricht?
table.setn(items, totalitems) setzt die Listengröße auf das Soll, ohne dass alle Einträge vorhanden sind. Sind das dann leere Einträge?
Deine items haben eigene timestamps. Diese sind gleich dem timestamp der Liste, wenn alles gut ging. Zu Inkonsistenzen kommt es während der Übertragung/Aktualisierung. Was geschieht, wenn die Inkonsistenz nicht aufgelöst wird? In GGT_Send_PlayerData() setzt du die item-timestamps auf die der Liste, falls es Abweichungen gab, ohne darauf einzugehen. Absicht? Falls ich eine unvollständige Liste empfangen hatte und mir derzeit niemand eine aktuellere geben kann - jetzt kommt eine Anfrage auf meine Liste - ist das der Zeitpunkt, an dem meine Liste zu einer gültigen Liste gemacht wird? Was passiert eigentlich bei der Übertragung einer unvollständigen Liste? Es wird getn(data.offers) betrachtet, aber die einzelnen items werden nicht mehr geprüft.
Wie gesagt hätte ich die Übertragung der Listen etwas anders gestaltet. Sicherer erscheint es mir, die übertragene Listen erst zu puffern und nur bei Vollständigkeit die alten zu ersetzen. Oder: Man kann es auch so sehen, dass wenn es eine neue Liste gibt, dann kann ich die alte eh verwerfen (wohl nur bei Needs sinnvoll). Also statt einzelne Einträge überschreiben, erst mal alte Liste komplett weg, dann auffüllen. Sollte ich unvollständige Liste haben und jemand will diese haben, so hat er zum Schluss auch nur eine als unvollständig markierte Liste.
Noch eine Idee, falls du in der bestehenden Liste aktualisieren willst: Sortiere die items stets sprachunabhängig nach ihrer ID. Alphabetische Anzeigelisten können nebenher erstellt/abgespeichert werden. Übertragen wird auch nach der ID sortiert. Wenn eine zweite ID empfangen wird, können alle bestehenden IDs zwischen erster und zweiter empfangener ID gelöscht werden. Dieses Vorgehen ist aber eigentlich nur zu empfehlen, wenn Listen oft nicht vollständig aktualisiert werden können.
Zu guter Letzt: Fremden, unkommentierten Code durchzuschauen ist doppelt nervig, weißt ja.
Ilyrielle - Mage
- Behemoth
- Initiative Big Boss
- Beiträge: 1827
- Registriert: Donnerstag 10. Februar 2005, 14:48
- Wohnort: Karlsruhe
Im Moment werden alle von Hand erstellten Offers beim automatischen Syncen gelöscht, weil ich mir noch nicht die Mühe machen wollte, die irgendwie anders zu verwalten.Magic hat geschrieben:Könnte es zu Unstimmigkeiten kommen, wenn man die Bank öffnet (mit Update-Modus an), dann /ggoffer verwendet und danach die Bank schließt? Wenn ich das richtig sehe, müsste dann /ggoffer verloren gehen.
Die Rekursion in GGT_UpdateSyncedOffers() ließe sich auch auflösen.
Look at me, I'm invisible!
- Behemoth
- Initiative Big Boss
- Beiträge: 1827
- Registriert: Donnerstag 10. Februar 2005, 14:48
- Wohnort: Karlsruhe
Es können nur Leute in der gleichen Gilde über den Gilden-Addon-Channel senden. Wird erst beim ausloggen oder UI-Reload gelöscht, ja.Magic hat geschrieben:GGT_ValidPlayers sind diejenigen Spieler, die sich per GGT_Send_DataVersion() bei mir registriert haben, gell? Wie wird sicher gestellt, dass das nur Gildies sind? (In einer anderen Datei, nehme ich an?) GGT_ValidPlayers werden nicht mehr entfernt, bis man selbst ausloggt, ja?
Sehe ich das richtig, dass Variablen zugleich als Array und Struct verwendet werden können? Also genau gesagt ist "[1]" wohl genau so ein Struct-Eintrag wie z.B. ".sorted", ja?
Es gibt keine Structs, es gibt nur assoziative Arrays. Ausserdem noch ein paar Convenience-Schreibweisen: data.sorted ist das gleiche wie data["sorted"]. Funktionen zum Iterieren durch das Array (wie z.B. getn) beziehen sich nur auf die Elemente, die eine natürliche Zahl, von 1 beginnend und dann aufsteigend als key haben.
Look at me, I'm invisible!