Solari-Cloud-Browser-Sessions enden ungefähr zehn Minuten nach dem Start. Es gibt kein timeoutMs, keinen Keep-Alive-Aufruf, kein resume() und keine Option, die um ein längeres Leben bittet. Ich habe sechs Sessions gemessen: fünf starben zwischen 604 und 617 Sekunden nach der Erzeugung, eine nach 319. Es machte keinen Unterschied, ob die Session untätig war, alle 25 Sekunden angepingt wurde oder einen CDP-Screencast mit 14 Bildern pro Sekunde streamte. Die untätige lebte am längsten. expiresAt steht auf Erzeugung plus fünf Stunden und wird nie erreicht.
Ich habe einen Tag auf dieser Plattform verbracht und vier Pakete mitgenommen. Alle vier gibt es wegen dieser einen Zahl.
Was eine Zehn-Minuten-Decke mit Agenten-Code macht
Jede Aufgabe, die länger dauert, scheitert, und sie scheitert so, dass es nach deinem Fehler aussieht. Der Browser verschwindet mitten im Aufruf, und du bekommst goto: Browser closed aus einer Zeile, die mit der Ursache nichts zu tun hat.
Dafür ist outlive da. Es sichert Cookies, localStorage und die URL, bemerkt den Tod, startet einen neuen Browser und ruft deine Aufgabe erneut auf, mit attempt: 2.
- 5 von 5 Zwölf-Minuten-Aufgaben abgeschlossen. Baseline 0 von 5. Zehn Läufe, fünfzehn Browser-Sessions, beide Arme gleichzeitig und abwechselnd: mit echtem TOTP anmelden, dann alle 20 Sekunden eine Kontoseite abfragen, bis 36 Abfragen durch sind. Das sind 720 Sekunden Wartezeit gegen eine Session, die etwa 600 lebt. Jeder Baseline-Lauf kam bis Abfrage 29 oder 30 und flog raus.
- Fünf Neustarts, kein Fehlschlag. Im Median 4,9 Sekunden verlorene Arbeit pro Lauf, im schlimmsten Einzelfall 15,0 Sekunden, bei 30 Sekunden Checkpoint-Abstand.
- Der Aufwand taucht in der Laufzeit nicht auf. Der Median-Lauf mit outlive dauerte 756 Sekunden. Das eigene Tempo der Baseline, 29 Abfragen in 624 Sekunden, hochgerechnet auf 36 ergibt rund 774. Einen Session-Tod zu überleben kostete weniger als die Schwankung zwischen den Läufen.
- Einen Browser zu ersetzen dauert 2121 ms. Der Checkpoint selbst braucht 200 ms und 1640 Bytes.
Einen Neustart überleben Cookies samt der HttpOnly-Cookies, localStorage, die URL und eine angemeldete Anwendungssitzung, gemessen 3 von 3. Nicht überleben das DOM, JavaScript-Zustand in der Seite, die Scrollposition, ein halb ausgefülltes Formular, IndexedDB, Service Worker und sessionStorage. Lokale Variablen in deiner Aufgabenfunktion fangen von vorn an. Ein Checkpoint ist kein Abbild eines laufenden Programms.
Die andere Wand ist eine menschliche
Ein Agent, der einen Browser bedient, stößt auf Dinge, an denen er nicht vorbeikommt. Einen 2FA-Code, den er nicht wissen kann. Ein Captcha, das er gerade verloren hat. handraise lässt ihn die Hand heben: Im Terminal erscheint ein QR-Code, die laufende Session liegt auf deinem Handy, du erledigst die eine Sache, und der Agent macht in derselben Session weiter.
Wenn der Agent feststeckt, erzeugt handraise eine Solari-Sandbox, schreibt ein einziges abhängigkeitsfreies Node-Skript hinein und macht es über Port-Preview erreichbar. Screencast-Bilder gehen vom Agenten über das Relay ans Handy, Tipp- und Tasteneingaben kommen zurück und werden als CDP-Eingaben eingespeist. Die Sandbox fasst die Browser-Session nie an. Sie existiert, um eine öffentliche Adresse mit einem WebSocket darauf zu sein, und wird nach dem Handoff zerstört.
Gemessen an einer TOTP-Wand, mit einem geskripteten Menschen am Tippen:
- 19 von 20 gerettet. Baseline 0 von 20. Gemessen sind 20 Läufe eines Workflows gegen ein Anmeldeportal, das für den Benchmark gebaut wurde, nicht 20 verschiedene echte Workflows. Über eine gemischte Last sagt das nichts.
- Vom Feststecken bis live auf dem Handy: 3,53 Sekunden im p50 über 30 Läufe, davon 2,68 Kaltstart des Relays.
- Eingabe-Umlauf 186 ms im p50 über 150 Messungen. Das ist Handy zum Relay und zurück. Browser und CDP liegen nicht auf diesem Weg, ein echter Tipp kostet also das plus einen weiteren Umlauf. Es ist keine Tipp-zu-Pixel-Latenz, und ich werde es nicht als eine ausgeben.
- Der eine Fehlschlag ist wieder das erste Problem: Der Browser starb mitten im Handoff, bei 3,6 Minuten Session-Alter.
Der Median von 5,5 Sekunden für den Handoff, der in meinen eigenen Notizen auftaucht, ist ein geskripteter Mensch mit 60 ms pro Zeichen inklusive Kaltstart. Das ist die Maschinenuntergrenze des Handoffs, keine Messung, wie schnell ein Mensch ist.
Ein QR-Code ist ein schlechtes Interface, wenn du ohnehin in Slack bist
handraise-slack und handraise-telegram liefern denselben Unterbruch dorthin, wo die Person schon ist. Ein Screenshot mit zwei Knöpfen landet im Kanal, und der Klick ist die Antwort. Kein öffentlicher Endpunkt, kein Webhook zum Hosten.
Diese beiden sind Adapter, keine neuen Ideen. Der Unterbruch ist ein Primitiv, und wo er auftaucht, sollte austauschbar sein.
Was ich dir sagen würde, bevor du darauf baust
- Finde heraus, wie lange eine Session lebt, bevor du drumherum entwirfst.
timeoutMsist kein rollendes Untätigkeitsfenster, und ein Keep-Alive-Pinger verlängert nichts. - Einen Tod als Ergebnis zu modellieren, das man zurückgeben kann, hat den Rest des Codes einfacher gemacht als ihn als Ausnahme abzufangen.
- Führe dein veröffentlichtes Artefakt aus, nicht deinen Quelltext, und zwar in der Laufzeit, die deine Nutzer haben. Eine grüne Suite, die nur deinen Quelltext gesehen hat, ist ein Nachweis über die falsche Sache.
Next
outlive steht bei 0.1.0, und die Messungen stammen aus einer Region an einem Tag, nimm die Zahlen also als Momentaufnahme und nicht als Verteilung. Ich will den Überlebens-Benchmark aus einer zweiten Region laufen lassen und sehen, ob sich die zehn Minuten verschieben. Falls du auf einer Cloud-Browser-Plattform gebaut hast und eine Session-Lebensdauer kennst, die dokumentiert statt gemessen ist, würde ich gern wissen, welche, denn ich habe keine gefunden.
blog.articles.solariSessionLifetime.footnote
Baust du an etwas Ähnlichem?
Ich schreibe hier über Setups, die ich selbst benutze. Wenn du an etwas Vergleichbarem arbeitest, würde mich interessieren, wie dein Workflow aussieht.