docs: Recherche zur automatischen Aktualisierung — Alternativen in den Plan
Wunsch: Ansicht aktualisiert sich selbst, höchstens ~2 s Verzögerung, möglichst über Etherpads Websockets. Recherchiert und gemessen, nicht geschätzt. Kernbeobachtung, die alles erklärt: Der einzige Endpunkt, den wir fremdstämmig lesen dürfen, ist genau der gedrosselte. `/export/txt` sendet `Access-Control-Allow-Origin: *` und ist auf 10 Abrufe je 90 s und IP begrenzt (Etherpad-Voreinstellung, in settings.json.template bestätigt); die Pad-Seite `/p/<pad>` enthält den vollen Text in `clientVars`, sendet aber KEINEN CORS-Header — der naheliegende Umweg ist also versperrt. Der vorgeschlagene Websocket-Weg ebenfalls, und das ist gemessen: Ein `wss://…/socket.io/?EIO=4&transport=websocket` scheitert mit Code 1006 ohne `open`, während ein fremder Echo-Server aus derselben Seite sauber öffnet — die Umgebung kann WebSockets, dieser Server nimmt uns nur nicht. Das eingebettete Pad verbindet sich dagegen problemlos; der Unterschied ist der Origin. Damit scheitert der Weg nicht an unserer Bereitschaft, eine Abhängigkeit aufzunehmen, sondern an der Gegenseite — die Easysync-Frage stellt sich gar nicht mehr. Fund der Suche: Etherpad-Plugins reden per postMessage mit der einbettenden Seite. `ep_iframeinsert` schickt periodisch den ganzen Pad-Text ans Elternfenster (und nimmt insert-Befehle an, könnte also sogar Schreiben erlauben). Das ist der einzige Weg, der live ist, kein Polling braucht, das Rate Limit nicht berührt und uns nur einen message-Zuhörer kostet — keine neue Laufzeit-Abhängigkeit. Preis: Installation auf der Instanz. Damit hängt alles an einer Frage: Kommt man an die Konfiguration der Pad-Instanz? Alle wirksamen Wege sind Server-Änderungen. Ohne Zugriff bleibt Polling im Budget — höchstens einmal je 9 s, geteilt über alle Betrachter hinter derselben IP. Im Plan steht das als any-of-Gruppe unter „Update by itself"; die beiden gemessenen Sackgassen als [-] mit dem Messergebnis im Kommentar, damit niemand sie erneut aufmacht. Der günstigste Pfad wählt dort von selbst die Rate-Limit-Anhebung. Geprüft: 107 Knoten, keine Warnungen.
This commit is contained in:
@@ -1329,3 +1329,63 @@ zwei Scheine nach außen gehen nicht, einer muss der Ring sein). Die Regel für
|
|||||||
`fresh.focusmark` steht **nach** der für `focusmark.current`: gleiche Spezifität,
|
`fresh.focusmark` steht **nach** der für `focusmark.current`: gleiche Spezifität,
|
||||||
und wenn alles drei zutrifft, sollen Zuruf und Neuheit gewinnen, nicht die eigene
|
und wenn alles drei zutrifft, sollen Zuruf und Neuheit gewinnen, nicht die eigene
|
||||||
Cursor-Zeile.
|
Cursor-Zeile.
|
||||||
|
|
||||||
|
**Nachtrag zu D31 — Recherche: Wie kann sich die Ansicht von selbst aktualisieren?**
|
||||||
|
Wunsch: automatisch, mit höchstens ~2 s Verzögerung, „dafür könnte man die
|
||||||
|
Websockets von Etherpad verwenden". Recherchiert und **gemessen** statt geschätzt;
|
||||||
|
die Zahlen stammen aus Etherpads `settings.json.template` und aus Versuchen gegen
|
||||||
|
`pad.hostsharing.net`:
|
||||||
|
|
||||||
|
| Befund | Messung |
|
||||||
|
|---|---|
|
||||||
|
| `importExportRateLimiting` | `{windowMs: 90000, max: 10}` — 10 Abrufe je 90 s **und IP** |
|
||||||
|
| `commitRateLimiting` | `{duration: 1, points: 10}` (betrifft Schreiben, nicht uns) |
|
||||||
|
| `cookie.sameSite` | Voreinstellung `"Lax"` — Ursache der Rahmen-Probleme |
|
||||||
|
| socket.io | Server v4; `/socket.io/?EIO=4` antwortet `0{"sid":…}`, `EIO=3` wird abgelehnt |
|
||||||
|
| Pad-**Seite** `/p/<pad>` | **kein** `Access-Control-Allow-Origin` |
|
||||||
|
| Pad-**Export** `/export/txt` | `Access-Control-Allow-Origin: *` |
|
||||||
|
|
||||||
|
Daraus folgt die Kernbeobachtung, die alles andere erklärt: **Der einzige
|
||||||
|
Endpunkt, den wir fremdstämmig lesen dürfen, ist genau der gedrosselte.**
|
||||||
|
|
||||||
|
**Zwei naheliegende Wege sind gemessen versperrt:**
|
||||||
|
|
||||||
|
- **Pad-HTML statt Export lesen.** Die Seite enthält den vollen Text in
|
||||||
|
`clientVars` und unterliegt dem Export-Limit nicht — aber sie sendet keinen
|
||||||
|
CORS-Header, der Browser blockt es. Sackgasse.
|
||||||
|
- **Eigener Socket zum Pad.** `wss://…/socket.io/?EIO=4&transport=websocket`
|
||||||
|
scheitert mit Code 1006 **ohne** `open`. Gegenprobe gegen einen fremden
|
||||||
|
Echo-Server aus derselben Seite: `OPEN`, saubere Schließung — die Umgebung kann
|
||||||
|
also WebSockets, dieser Server nimmt uns nur nicht. Zugleich verbindet sich das
|
||||||
|
**eingebettete** Pad problemlos (nachgewiesen: es übernahm eine von außen
|
||||||
|
eingespielte Änderung sofort) — der Unterschied ist der Origin. Warum genau,
|
||||||
|
sagt 1006 nicht (Origin-Prüfung, fehlendes Session-Cookie oder ein Proxy, der
|
||||||
|
nur gleichstämmig upgradet); alle drei liegen serverseitig, die Folgerung hält
|
||||||
|
also unabhängig davon. **Der vorgeschlagene Websocket-Weg scheitert damit nicht
|
||||||
|
an unserer Bereitschaft, eine Abhängigkeit aufzunehmen, sondern an der
|
||||||
|
Gegenseite** — und die Easysync-Frage (Changesets anwenden) stellt sich gar
|
||||||
|
nicht mehr.
|
||||||
|
|
||||||
|
**Der Fund, den die Suche gebracht hat:** Es gibt Etherpad-Plugins, die per
|
||||||
|
`postMessage` mit der einbettenden Seite reden — `ep_iframeinsert` schickt
|
||||||
|
periodisch `{func:"none", context:"ep_iframeinsert", data:<ganzer Pad-Text>}` ans
|
||||||
|
Elternfenster (und nimmt umgekehrt `insert`-Befehle an, könnte also sogar
|
||||||
|
Schreiben aus Werkbaum heraus erlauben); `ep_resize` belegt dasselbe Muster für
|
||||||
|
Größenänderungen. Das ist der einzige Weg, der **live** ist, **kein** Polling
|
||||||
|
braucht, das Rate Limit nicht berührt und auf unserer Seite nur einen
|
||||||
|
`message`-Zuhörer mit Origin-Prüfung kostet — also **keine** neue
|
||||||
|
Laufzeit-Abhängigkeit. Preis: Das Plugin muss auf der Instanz installiert sein.
|
||||||
|
|
||||||
|
**Damit hängt alles an einer einzigen Frage: Kommt man an die Konfiguration der
|
||||||
|
Pad-Instanz?** Jede der wirksamen Möglichkeiten ist eine Server-Änderung —
|
||||||
|
Rate Limit höher, Plugin installieren, `cookie.sameSite: "None"`, oder eine
|
||||||
|
socket.io-CORS-Freigabe. Ohne Zugriff bleibt nur, innerhalb des Budgets zu
|
||||||
|
pollen: höchstens **einmal je 9 s** (10 je 90 s), und das teilen sich alle
|
||||||
|
Betrachter hinter derselben IP. Das ist ehrlich machbar, aber es sind nicht die
|
||||||
|
gewünschten 2 s — und es ist schlechter als der Knopf, sobald mehrere zuschauen.
|
||||||
|
|
||||||
|
Die Alternativen stehen als any-of-Gruppe im mitgelieferten Plan
|
||||||
|
(`docs/examples/example-werkbaum.werkbaum`, unter „Update by itself"); die beiden
|
||||||
|
gemessenen Sackgassen als `[-]` mit dem Messergebnis im Kommentar, damit niemand
|
||||||
|
sie erneut aufmacht. Der günstigste Pfad wählt dort von selbst die
|
||||||
|
Rate-Limit-Anhebung — die billigste wirksame Änderung.
|
||||||
|
|||||||
@@ -68,7 +68,17 @@
|
|||||||
- [^] Embed the pad, keep the text mirror beside it (M)
|
- [^] Embed the pad, keep the text mirror beside it (M)
|
||||||
- [^] Three views: pad and text, pad only, text only (S)
|
- [^] Three views: pad and text, pad only, text only (S)
|
||||||
- [^] Splitter between pad and mirror (XS)
|
- [^] Splitter between pad and mirror (XS)
|
||||||
|
- [?] Editing in the frame stops after a while (S) %% SameSite=Lax, see D31
|
||||||
|
| [?] Ask the admin for cookie.sameSite = None (XS)
|
||||||
|
| [ ] Live with it: edit in the pad's own tab (XS)
|
||||||
- [^] A shared pointer: !!! focuses a node for everyone (XS)
|
- [^] A shared pointer: !!! focuses a node for everyone (XS)
|
||||||
|
- [?] Update by itself, within about 2 s (M)
|
||||||
|
| [?] Admin raises the export rate limit (XS) %% default is 10 per 90 s
|
||||||
|
| [?] Admin installs a plugin that pushes the text (S) %% postMessage to the page
|
||||||
|
| [?] Our own backend holds one socket and fans out (XXL)
|
||||||
|
| [ ] Poll inside the budget, at best every 9 s (S) %% legal, but not 2 s
|
||||||
|
| [-] Our own socket straight to the pad (L) %% measured: upgrade refused
|
||||||
|
| [-] Read the pad's HTML instead of the export (M) %% measured: no CORS header
|
||||||
- [ ] Git as the shared store (L)
|
- [ ] Git as the shared store (L)
|
||||||
| [ ] A file in a repository, changed by pull request (S) %% works today, no code
|
| [ ] A file in a repository, changed by pull request (S) %% works today, no code
|
||||||
| [?] The backend commits every change (L)
|
| [?] The backend commits every change (L)
|
||||||
|
|||||||
Reference in New Issue
Block a user