Multi-User-Editor

Konfiguration

siehe: Multi-User-Editor

Persistenz von Sperren (Locks)

Tabelle CONTENT.CONTENTPARTLOCK

SpaltennameTypConstraintBemerkung
contentpartidUUIDNOT NULLPrimärschlüssel. ID des gesperrten ContentParts
articleidUUIDNOT NULLID des Artikels zu dem gesperrten ContentPart
uiidUUIDNOT NULLID der UI, wo der ContentPart editiert wird
versionIntegerNOT NULL
createdbyUUID
ID des Users, der die Sperre gesetzt hat
createtimeTimestamp(6)
Zeitpunkt der ersten Sperranforderung
changedbyUUID
ID des Users, der die Sperre aktualisiert hat
changetimeTimestamp(6)
Zeitpunkt der letzten Sperranforderung

UI-Container

  • An jeder Artikelkomponente ist eine Extension angefügt worden, über die alle vom Anwender stammenden Änderungen erkannt werden.
    Änderungen sind: 
    • Inhaltsänderungen (auch Optionen wie z.B. Textbereinigungen)
    • Einfügen und Löschen von Komponenten (auch Splitten und Mergen von Komponenten).
  • Bei einer solchen Änderung wird eine Sperranforderung an den Logic-Server abgesetzt.
  • Kann eine Sperre für ein Contentpart gespeichert werden,
    • erhält die Komponente in der sperrenden Artikel-View im Titel einen symbolisierten Stift.
    • erhält die gesperrte Komponente per Event in allen anderen Artikel-View ein Schloss und die Komponente wird schreibgeschützt gesetzt.
  • Konnte eine Contentpart nicht gesperrt werden, wird auf den aktuellen Speicherstand zurückgegangen.

  • Über die Symbole kann durch Anklicken Informationen zur Sperre angezeigt werden.

  • Durch Komponenten-Änderungen im Artikel werden die Locks für alle bereits gesperrten Contentparts des Anwenders und der UI "aktualisiert", so dass die Sperren für die anderen UIs beibehalten werden.
  • Beim Speichern werden die Locks wieder freigegeben, die anderen UIs werden durch Event notifiziert, um Änderungen entgegen zunehmen und die Sperren und den Schreibschutz wieder zurückzunehmen.
  • Die zu aktualisierenden UIs übernehmen alle Contentparts, deren Versionsnummer größer als die der eigenen Contentparts sind; zusätzlich alle neuen; entfernt werden alle gelöschten Contentparts.
  • Gibt es lokale Änderungen an einem Contentpart, der gerade aktualisiert wird, erscheint eine Konfliktmeldung an der Komponente. Eine Kopie der lokalen Änderungen bleibt erhalten.

  • Zwischen der aktuellen und lokalen Version kann über den Versionsbutton gewechselt werden. Aus der lokalen Version können Inhalte kopiert aber nicht mehr verändert werden. 

  • Der Konflikt muss über den Annehmen-Button aufgelöst werden. Andernfalls wird beim Speichern eines Artikels mit Konflikt eine Fehlermeldung angezeigt.

  • Über das Optionsmenü am Artikel steht für die Rolle Administrator der Menüpunkt "Sperren an Komponenten aufheben" zur Verfügung. Darüber lassen sich alle Sperren Benutzer- und UI-übergreifend für den Artikel wieder freigeben.

Sperrstatus-Automat

Im nachfolgenden Bild wird illustriert, wie sich der Sperrstatus eines Contentpart verändert, wenn eine Sperranforderung erfolgreich ist bzw. Events mit einer Sperre oder Sperrfreigabe verarbeitet werden.

Dabei gibt es folgende Sperrstatus:

  • NO_LOCK: Der Contentpart hat keine Sperre.
  • OWN_LOCK: Der Contentpart ist durch den Anwender gesperrt
  • FOREIGN_LOCK: Der Contentpart ist durch einen anderen Anwender gesperrt.
  • LOST_OWN_NO_LOCK: Der Contentpart wurde durch den Anwender gesperrt, hat die Sperre aber wieder verloren (z.B. durch Timeout der Sperre)
  • LOST_OWN_FOREIGN_LOCK: Der Contentpart wurde durch den Anwender gesperrt, hat die Sperre verloren, die nun von einem anderen Anwender gehalten wird.

Logic-Container

  • Beim Speichern eines Artikels werden alle Contentpart-Locks für den Anwender und die UI wieder zurückgesetzt. Über einen entspr. Unlock- und Save-Event werden die UIs informiert.
  • Über einen Scheduler-Prozess werden Locks, die ein konfiguriertes Alter haben, wieder freigegeben.
    • Ermittlung aller abgelaufenen Locks:
      SELECT * FROM content.contentpartlock WHERE changetime < getDate() - [hup.one.content.article.lock.unlock-timeout]
    • Transaktionales Löschen aller abgelaufenen Locks:
      DELETE FROM content.contentpartlock WHERE contentpartid = [id] AND changetime < getDate() - [hup.one.content.article.lock.unlock-timeout]
    • Auch hier werden Unlock-Events an die UIs versendet.