2010-08-20 9 views
5

Ich arbeite an etwas ähnlich einem Pastebin (ja, es ist dass generic), aber so dass für mehrere Benutzer bearbeiten. Das offensichtliche Problem besteht darin, dass mehrere Benutzer versuchen, dieselbe Datei zu bearbeiten. Ich denke an das Sperren der Datei, wenn ein Benutzer daran arbeitet (es ist nicht die beste Lösung, aber ich brauche nichts zu komplexes), aber um den Benutzer zu verhindern/warnen, würde ich offensichtlich eine benötigen System zur Überwachung der Editiersitzungen jedes Benutzers. Ich arbeite mit Datenbank und Ajax und denke dabei an zwei Lösungen.Überwachung von Benutzersitzungen verhindern Konflikt bearbeiten

Die erste wäre, die Bearbeitungsseite den Server in einem beliebigen Intervall pingen, sagen wir eine Minute, und es würde den Bearbeitungssitzung Eintrag in der Datenbank aktualisieren. Dann, wenn das nächste Mal eine Skriptanfrage bearbeitet wird, sucht es nach dem letzten Ping, und wenn das letzte eine andere willkürliche Zeit war, sagen wir fünf Minuten, dann nehmen wir an, dass der vorherige Benutzer aufgehört hat und die Datei erneut bearbeitet werden kann. Natürlich besteht das Problem bei dieser Methode darin, dass die Annahme, dass der vorherige Benutzer aufgehört hat, einfach eine Annahme ist. Er könnte flockige Wi-Fi-Verbindung haben und fiel einfach für zehn Minuten aus, die ganze Zeit mit dem Fenster noch offen.

Natürlich mit dieses Problem zu behandeln, müssten wir den Server auf neue Anfrage von zuvor geschlossenen Sitzungen mit einem Fehler reagieren müssen, die Clientseite sagen, um den Benutzer darauf hinweisen, dass seine Sitzung beendet wurde und dann behandeln Sie es, indem Sie es zum Beispiel als eine andere Datei auf dem Server speichern und den Benutzer auffordern, es manuell zusammenzuführen, usw. Es ist selbstverständlich, dass dies für den Endbenutzer ziemlich schrecklich ist.

So bin ich gekommen, um an eine andere Lösung zu denken. Es kann auch möglich sein, ein Ereignis unload auszulösen, wenn die Benutzersitzung beendet wird, aber ich kann nicht sicher sein, ob dies zuverlässig funktioniert.

Hat jemand eine andere, elegantere Lösung für dieses Problem?

Antwort

6

Wenn Sie erwarten, dass die Anzahl gleichzeitiger Bearbeitungen der Datei gering ist, können Sie nur eine Versionsnummer für die Datei in der Datenbank speichern, und wenn der Benutzer die Datei in ihren Browser lädt, erhält er auch die Versionsnummer. Sie dürfen ihre Änderungen nur hochladen, wenn die Versionsnummer übereinstimmt. Der erste, der hochgeladen wird, gewinnt. Wenn ein Konflikt erkannt wird, sollten Sie die letzte Datei und die Änderungen des Benutzers zurücksenden, damit der Benutzer die Änderungen manuell zusammenführen kann. Der Vorteil ist, dass dies auch dann funktioniert, wenn derselbe Benutzer zwei gleichzeitige Änderungen vornimmt. Wenn diese Funktion häufig verwendet wird, können Sie eine clientseitige Zusammenführung hinzufügen, ähnlich wie bei einem Diff-Tool (Sie müssen jedoch in diesem Fall möglicherweise die alten Revisionen beibehalten).

2

Sie sind wahrscheinlich besser dran für eine "Merge" -Lösung. Bei dieser Vorgehensweise müssen Sie nur nach Änderungen suchen, wenn der Benutzer sein Dokument auf dem Server veröffentlicht.

Der grundlegende Ansatz wäre: einige Änderungen 1. Benutzer A das Dokument zur Bearbeitung wird das Dokument in der Version 1 2. Benutzer B das Dokument zur Bearbeitung erhält, ist Dokument in der Version 1 3. Benutzer B Beiträge einschließlich der Basisversionsnummer von 1 4. Serveraktualisierungsdokument, Dokument jetzt bei Version 2 5. Benutzer B veröffentlicht einige Änderungen, einschließlich der Basisversionsnummer 1 6. Der Server antwortet, dass sich das Dokument geändert hat, seit der Benutzer mit der Bearbeitung beginnt und sendet Benutzer das neue Dokument und ihre Version - Benutzer muss dann alle ihre Änderungen in Dokumentversion 2 zusammenführen und zurück an den Server senden. Der Nutzer ist im Wesentlichen jetzt Bearbeitung Dokument Version 2 7. Benutzer A Beiträge einige Änderungen, einschließlich der Versionsnummer von 2 8. Server-Updates das Dokument, das nun in der Version 3

Sie können immer noch tun, um eine „ping“ jede Minute, um die aktuelle Versionsnummer zu erhalten - Sie wissen bereits, welche Version sie bearbeiten. Wenn also eine neue Version verfügbar ist, können Sie sie informieren und sie die neueste Version herunterladen lassen, damit sie ihre Änderungen vornehmen können.

Der Hauptvorteil dieses Ansatzes besteht darin, dass Benutzer niemals Dateien sperren, so dass Sie keine willkürlichen "Time-Outs" benötigen.

+0

Es ist eine großartige Antwort, aber es ist wirklich nicht das, wonach ich suche: der kollaborative Bearbeitungsteil ist wirklich unbedeutend für die Freigabe, sorry wenn ich das nicht klar mache. Die Einführung dieser Lösung würde die Dinge sogar * komplexer * machen - zu komplex für eine einfache Text/Code-Sharing-App. Die Anzahl der Randfälle, die ich berücksichtigen müsste, wäre ... angesichts der Komplexität der Benutzerinteraktionen hier völlig unmöglich. Trotzdem, großartige Antwort, und gab mir etwas, worüber ich nachdenken konnte, während ich auf die nächste Antwort wartete ... –

0

Ich würde sagen, Sie sind auf dem richtigen Weg.Ich würde wahrscheinlich eine hybride Lösung implementieren:

Haben Sie eine einzelne Tabelle namens "active_edits" oder so ähnlich mit einer Spalte für die Document_id, den Benutzer und die Last_update_time. Nehmen wir an, Ihre Ping-Zeit beträgt 1 Minute und Ihr Timeout beträgt 5 Minuten. So würde ein Anwendungsfall wie folgt aussehen:

Bob öffnet ein Dokument. Es überprüft die last_update_time. Wenn es vor mehr als 5 Minuten war, aktualisieren Sie die Tabelle mit Bob und der aktuellen Uhrzeit. Wenn dies nicht der Fall ist, bearbeitet jemand anderes das Dokument. Geben Sie daher eine Fehlermeldung ein. Angenommen, es wird nicht bearbeitet, arbeitet Bob eine Weile an dem Dokument und der Client sendet jede Minute eine Aktualisierungszeit.

Ich würde sagen, do enthalten eine Schaltfläche "Bearbeitung beenden" und ein onunload-Handler. Onunload, von dem, was ich verstehe kann flockig sein, aber könnte es auch hinzufügen. Beide senden einen einzigen Sende-Post an den Server, der sagt, dass Bob fertig ist. Selbst wenn Bob nicht "fertig editieren" und "ausflippen" ausgibt, ist der schlimmste Fall, dass ein anderer Benutzer noch 5 Minuten warten muss, um zu bearbeiten. Der Vorteil ist, dass, wenn diese normalerweise funktionieren (eine faire Annahme), das System ein bisschen besser funktioniert.

Wenn Sie beschrieben haben, wo ein Bob eine schlechte Funkverbindung hat oder eine Pause macht: Ich würde sagen, das ist keine große Sache. Ihre Ping-Funktion sollte sicherstellen, dass das Dokument seit Bobs letztem Ping nicht von jemand anderem übernommen wurde. Wenn dies der Fall ist, geben Sie Bob einfach eine Nachricht, in der steht, "jemand anders hat angefangen, an dem Dokument zu arbeiten", und geben Sie ihm die Option zum Nachladen.

EDIT: Auch würde ich in window.onbeforeunload suchen, nicht onunload. Ich glaube, es wird früher ausgeführt. Ich glaube, das ist die Funktion Website (Slashdot enthalten) verwenden, um zu bestätigen, dass Sie die Seite tatsächlich verlassen möchten. Ich denke, es funktioniert in den wichtigsten Browsern außer Opera.

0

Wie bei dieser SO Frage How do you manage concurrent access to forms?, würde ich nicht versuchen, pessimistisches Sperren zu implementieren. Es ist einfach zu schwierig, in einer zustandslosen Umgebung zuverlässig arbeiten zu können. Stattdessen würde ich optimistisches Sperren verwenden. In diesem Fall habe ich jedoch einen SHA-Hash der Datei verwendet, um festzustellen, ob sich die Datei geändert hat, seit der Benutzer zuletzt aus der Datei gelesen hat. Bei jeder Anforderung zum Ändern der Datei würden Sie einen SHA-Hash der Dateibytes ausführen und ihn mit der Version vergleichen, die Sie beim ersten Lesen der Daten gezogen haben. Wenn sich die Änderung geändert hat, lehnen Sie die Änderung ab und erzwingen entweder die erneute Bearbeitung der Datei (durch Ziehen einer neuen Kopie des Dateiinhalts) oder Sie erhalten eine bessere Konfliktlösung.