2 Punkte von GN⁺ 5 시간 전 | 1 Kommentare | Auf WhatsApp teilen
  • Wenn man einen ActivityPub-Server direkt selbst baut, scheitert man leicht schon an der ersten Follow-Anfrage mit einem kommentarlosen 401 Unauthorized; Fedify ist ein TypeScript-Framework, das den Aufwand für Signaturen, JSON-LD, Zustellung und Sicherheit aus dem Anwendungscode herausverlagert
  • Für Authentifizierung im Fediverse werden sowohl der abgelaufene Entwurf draft-cavage-http-signatures-12 als auch der Standard RFC 9421 verwendet; bezieht man Dokumentsignaturen mit ein, muss man vier Signaturmechanismen sowie RSA- und Ed25519-Schlüssel handhaben
  • Selbst dieselbe ActivityPub-Aktivität kann in JSON-LD in verschiedenen Formen ankommen, etwa als String, Array, Inline-Objekt oder URI-Referenz; je mehr man selbst implementiert, desto weiter verbreitet sich defensiver Code über die gesamte Codebasis
  • Bei verteilter Zustellung entstehen Probleme wie „Zombie-Posts“, bei denen ein Delete vor einem Create eintrifft; dafür braucht man Queues, Retries, Idempotenz, Reihenfolgegarantien und Circuit Breaker
  • Fedify bietet Integrationen für 13 Web-Frameworks, Adapter für KV und Message Queues sowie CLI, Linter, Debugger und OpenTelemetry, sodass man auch ohne Detailwissen über ActivityPub mit der Entwicklung föderierter Apps beginnen kann

Probleme bei der direkten Implementierung von ActivityPub

  • Um die erste Follow-Aktivität an Mastodon zu senden, muss man JSON erstellen, die HTTP-Anfrage signieren und POST verarbeiten; bei einem Fehlschlag kann aber nur eine einzige Zeile 401 Unauthorized zurückkommen
    • Die Ursache kann in einer Zeitabweichung im Date-Header, einem Fehler im Digest-Hash, der Groß-/Kleinschreibung von (request-target) oder der Darstellung des öffentlichen Schlüssels liegen
    • Wenn der entfernte Server den Grund nicht nennt, muss man zum Debuggen den Code anderer Server lesen
  • Fedify entstand beim Bau von Hollo, einem Microblogging-Server für einen einzelnen Benutzer
    • Als der Aufwand für die ActivityPub-Implementierung die Produktentwicklung zu verschlingen begann, wurde daraus zuerst ein Framework, noch vor der eigentlichen App
  • Die Schwierigkeiten konzentrieren sich vor allem auf Signaturstandards, JSON-LD-Dokumentformen, verteilte Zustellung, implementierungsspezifische Gepflogenheiten und grundlegende Sicherheitseinstellungen

Es gibt nicht nur einen Signaturstandard

  • Für die Authentifizierung zwischen Servern werden HTTP-Signaturen verwendet, im tatsächlichen Fediverse existieren jedoch sowohl der abgelaufene Entwurf draft-cavage-http-signatures-12 als auch der Standard RFC 9421
  • Welcher Server welche Signatur akzeptiert, weiß man erst nach einem Versuch; wird eine Methode abgelehnt, muss man mit der anderen erneut signieren und sich pro Server merken, welche Variante funktioniert hat
  • HTTP-Signaturen beweisen nur den Absender einer Anfrage; in Fällen wie inbox forwarding, bei denen eine empfangene Aktivität an Dritte weitergeleitet wird, sind daher auch Signaturen erforderlich, die direkt am Dokument hängen

Die Form von JSON-LD-Dokumenten ändert sich ständig

  • Das Transportformat von ActivityPub ist JSON-LD, und selbst eine Create-Aktivität mit derselben Bedeutung kann in mehreren Formen dargestellt werden
    • actor kann ein URI-String oder ein eingebettetes Person-Objekt sein
    • to kann ein einzelner String oder ein Array sein
    • object kann sowohl ein eingebettetes Objekt als auch eine URI sein
  • Auch die Adresse für das öffentliche Ziel ist in drei Schreibweisen gültig: https://www.w3.org/ns/activitystreams#Public, as:Public und Public
  • Um spezifikationskonform damit umzugehen, muss man mit einem JSON-LD-Prozessor erst expandieren und dann durch compaction normalisieren
    • Viele Implementierungen behandeln das einfach als „normales JSON“ und brechen dann stillschweigend bei Formen, die ein bestimmter Server ausgibt
  • Bei einer Eigenimplementierung entsteht überall defensiver Code, der prüft, ob ein Wert ein String, ein Array, ein Objekt oder eine URI ist, die erst geholt werden muss

Verteilte Zustellung und „Zombie-Posts“

  • Wenn ein Benutzer direkt nach dem Veröffentlichen einen Tippfehler bemerkt und den Beitrag löscht, sendet der Server nach Create ein Delete; je nach Netzwerksituation kann der empfangende Server jedoch zuerst das Delete erhalten
    • Ignoriert er die Löschung eines noch nicht existierenden Beitrags und verarbeitet später Create, bleibt ein Beitrag auf diesem Server bestehen, von dem der Autor glaubt, dass er gelöscht wurde
  • Hat ein Konto 5.000 Follower, erzeugt ein einzelner Beitrag Tausende HTTP-Zustellungen; verarbeitet man das im Request-Handler, kann die Antwort auf den Publish-Button träge werden oder der Server zusammenbrechen
  • Selbst mit Queues muss man noch Retry-Zeitpläne für fehlgeschlagene Zustellungen, exponentielles Backoff, Retry-Zahlen, den Unterschied zwischen 500 Internal Server Error und 410 Gone, das Aufräumen von Followern verschwundener Server und den Umgang mit langfristig gestörten Hosts festlegen
  • Dieser Bereich ist weniger einfache Protokollimplementierung als vielmehr Engineering für verteilte Systeme

Mit der Spezifikation allein ist Interoperabilität nicht erledigt

  • Selbst wenn man die Spezifikation perfekt einhält, bleiben Interoperabilitätsprobleme mit realen Fediverse-Implementierungen bestehen
  • Der Secure Mode von Mastodon verwendet authorized fetch, das auch für GET-Anfragen HTTP-Signaturen verlangt
    • Wenn beide Server im Secure Mode laufen, entsteht ein Deadlock: Um den öffentlichen Schlüssel der Gegenseite zu holen, muss man signieren, aber zum Verifizieren der Signatur muss die Gegenseite zuerst den eigenen öffentlichen Schlüssel abrufen
    • Die Community umgeht das, indem sie mit einem instance actor signiert, der den Server selbst repräsentiert; das steht jedoch nicht in der Spezifikation
  • Threads kann Aktivitäten, bei denen actor als eingebettetes Objekt kommt, nicht parsen; beim Senden an Threads muss actor daher als URI gesendet werden
  • Lemmy lehnt stillschweigend ab, wenn bei einem Group-Actor Felder fehlen, die Mastodon nicht verlangt
    • Beispiele sind eine über attributedTo verknüpfte moderators collection und eine featured collection
  • Misskey hat eigene Vokabular-Erweiterungen, und allein für Quote-Posts werden je nach Implementierung drei verschiedene Property-Namen verwendet
  • Interoperabilität ist kein Thema, das man einmal abstimmt und dann abhakt, sondern ein Bereich, der kontinuierlich gepflegt werden muss

Der Grundzustand einer Eigenimplementierung ist unsicher

  • Wenn man die Verifikation eingehender Aktivitätssignaturen überspringt, kann jeder gefälschte Follow- oder Delete-Nachrichten einschleusen
  • Wenn man den Dokument-Loader nicht einschränkt, kann eine bösartige Aktivität auf http://169.254.169.254/ oder interne Netzwerke verweisen und den Server zu einem SSRF-Proxy machen
  • Lässt man die Herkunftsprüfung eingebetteter Objekte weg, kann jeder Server Dokumente ausliefern, die so wirken, als hätte eine bestimmte Person sie verfasst
  • Solche Fallstricke fallen nicht sofort auf, und bis zu ihrer Ausnutzung kann alles so aussehen, als funktioniere es korrekt

Bereiche, die Fedify übernimmt

  • Fedify ist eine TypeScript-Bibliothek zum Erstellen föderierter Server-Apps mit ActivityPub und zugehörigen Standards
  • Läuft auf Deno, Node.js und Bun und unterstützt auch Edge-Runtimes wie Cloudflare Workers
  • Das Designziel ist, Signaturen, JSON-LD, Zustellung, Implementierungsunterschiede und Sicherheitsdetails aus dem Anwendungscode herauszuhalten
  • Signaturverarbeitung

    • Wenn man einen actor dispatcher und einen key pair dispatcher registriert, kann man einen Actor ins Fediverse bringen
    • Alle ausgehenden Requests werden signiert
    • Bei RSA-Schlüsseln werden HTTP Signatures und Linked Data Signatures erzeugt
    • Fügt man Ed25519-Schlüssel hinzu, werden auch Object Integrity Proofs angehängt
    • Diese vier Mechanismen können bei einer einzelnen Aktivität koexistieren, und Empfänger prüfen mit der stärksten Methode, die sie verstehen
    • Fedify verarbeitet double-knocking direkt selbst
      • Der erste Kontakt geht mit RFC 9421 raus, bei Ablehnung wird mit draft-cavage erneut versucht
      • Die erfolgreiche Methode wird pro Server gecacht
      • Wenn die Ablehnungsantwort eine Accept-Signature-Challenge enthält, wird mit den vom Server angeforderten Komponenten erneut signiert
    • Eingehende Signaturen werden validiert, bevor der Anwendungscode sie überhaupt sieht; Aktivitäten mit fehlgeschlagener Validierung erreichen den Listener nicht
    • Schon allein durch die Registrierung eines actor dispatcher entsteht auch ein WebFinger-RFC 7033-Server, sodass man im Mastodon-Suchfeld einen Actor in der Form @alice@example.com finden kann
  • Typen statt JSON-LD behandeln

    • Fedify bietet rund 80 Klassen, die den gesamten Activity Vocabulary und wichtige Vendor-Erweiterungen abdecken
    • Die Klassen sind typisiert und unveränderlich, und Accessors fangen die Unterschiede in den von JSON-LD erlaubten Dokumentformen ab
    • lookupObject() nimmt ein Handle entgegen und führt den gesamten Lookup-Prozess inklusive WebFinger-Discovery aus
    • Accessors wie getFollowers() funktionieren gleich, egal ob der Wert eine URI-Referenz oder ein Inline-Objekt ist, und geholte Werte werden gecacht
    • Auch Unterschiede zwischen einzelnen Anbietern werden hinter der API verborgen
      • Die drei Quote-Eigenschaften quoteUri, _misskey_quote und quoteUrl werden zusammen mit quote aus dem neu aufkommenden FEP-044f hinter einer einzigen API zusammengeführt
      • Auch die Eigenschaft isCat von Misskey existiert als Typ und kann typsicher verarbeitet werden
  • Zustellinfrastruktur und Reihenfolgegarantie

    • Wenn man an createFederation() eine Message Queue anschließt, wandert die Zustellung in den Hintergrund und wird bei Fehlern standardmäßig mit exponentiellem Backoff bis zu zehnmal automatisch wiederholt
    • Wenn ein einzelner Beitrag an Tausende Follower zugestellt wird, greift two-stage fan-out
      • Eine einzige zusammengefasste Nachricht wird in die Queue gestellt
      • Ein Background-Worker teilt sie in Zustelljobs pro Server auf
      • Der Publish-Button reagiert sofort
    • Durch Retries kann dieselbe Aktivität zweimal ankommen, deshalb überspringt Fedify Duplikate vor dem Handler mithilfe eines Idempotenz-Caches, der verarbeitete Aktivitäten 24 Stunden lang speichert
    • Gibt man beim Aufruf von sendActivity() { orderingKey: post.id } an, werden Aktivitäten mit demselben orderingKey an jeden empfangenden Server in der Reihenfolge zugestellt, in der sie gesendet wurden
      • Ein Delete kann ein Create nicht überholen
      • Aktivitäten mit unterschiedlichen Schlüsseln gehen parallel raus und erhalten so den Durchsatz
    • Bei 404 Not Found oder 410 Gone werden Retries gestoppt und der registrierte Handler für permanente Zustellfehler aufgerufen
    • Wenn an eine Shared Inbox zugestellt wurde, kann man auch die dahinterstehende Follower-Liste abrufen, um verschwundene Accounts zu bereinigen
    • Bei Hosts mit wiederholten Fehlern setzt der standardmäßig aktivierte Circuit Breaker die Zustellung aus und prüft periodisch, ob die Gegenstelle sich erholt hat

Implementierungsspezifische Praktiken und sichere Standardeinstellungen

  • Bei Authorized Fetch verbindet Fedify .authorize() mit dem Dispatcher und übergibt die verifizierte Identität des Requesters per Callback
    • Dinge wie Blocklisten oder private Collections lassen sich als Anwendungslogik schreiben
    • Auch für das Deadlock-Problem beim Instance Actor gibt es unterstützte Muster
  • Das Inline-Actor-Problem von Threads wird dadurch behandelt, dass der standardmäßig aktivierte activity transformer Inline-Actors in ausgehenden Aktivitäten in URIs umwandelt
  • Die von Lemmy verlangte Moderators-Collection lässt sich mit der Custom-Collection-API in wenigen Zeilen bereitstellen, und der JSON-LD-Context von Lemmy ist bereits enthalten
  • Wenn neue Interoperabilitätsprobleme entdeckt werden, fließt die Korrektur in Fedify ein statt in jede einzelne Anwendung
  • Die sicheren Standardeinstellungen sind auf die sichere Seite ausgelegt
    • Die Signaturprüfung ist keine Funktion, die man erst aktivieren muss, sondern eine, die man für Tests deaktivieren kann
    • Der Document Loader blockiert standardmäßig private Adressbereiche und Loopback und berücksichtigt auch DNS-Rebinding
    • Um SSRF ausgesetzt zu sein, muss man ausdrücklich eine Option aktivieren, deren Name klar macht, dass sie nur für Tests gedacht ist
    • Wenn bei eingebetteten Objekten die Herkunft von der des übergeordneten Dokuments abweicht, vertraut der Accessor ihnen nicht und lädt sie vom Ursprung erneut
    • Dieses herkunftsbasierte Sicherheitsmodell basiert auf FEP-fe34

Bestehende Stacks und Entwicklungstools

  • Fedify wurde so konzipiert, dass es zu bestehenden Web-Stacks passt, und bietet Integrationen für 13 Web-Frameworks
    • Express, Hono, Fastify, Koa, NestJS, Elysia
    • Next.js, Nuxt, SvelteKit, Astro, SolidStart, Fresh
  • Middleware übernimmt die Content-Negotiation, sodass dieselbe URL dem Browser HTML und dem Fediverse JSON-LD liefern kann
  • Das eigene Storage von Fedify verlangt nur eine einzige Key-Value-Schnittstelle
    • Es gibt Adapter für Redis, PostgreSQL, MySQL/MariaDB, SQLite, Deno KV, Cloudflare Workers KV und In-Memory
  • Für Message Queues werden 8 Varianten bereitgestellt, darunter PostgreSQL, Redis und AMQP/RabbitMQ; falls nichts passt, kann man die Schnittstelle selbst implementieren
  • Domänendaten können unverändert in der bestehenden Datenbank und dem vorhandenen ORM bleiben
  • Wer Federation bereits mit einer anderen Bibliothek betreibt, kann mit dem Migrationsleitfaden und Datenmigrationsskripten von activitypub-express und anderen Lösungen wechseln, ohne bestehende Follower zu verlieren
  • Es werden auch Higher-Level-Pakete angeboten
    • @fedify/relay stellt mit einem einzigen Funktionsaufruf einen vollständigen ActivityPub-Relay-Server bereit
    • @fedify/backfill folgt dem Fediverse und rekonstruiert unvollständige Gesprächs-Threads
  • Tools für die Entwicklungsschleife

    • fedify init scaffoldet ein Projekt mit einer einzigen Zeile
    • fedify tunnel macht einen lokalen Server per HTTPS erreichbar, damit er sich mit echtem Mastodon testen lässt
    • fedify inbox startet einen temporären Inbox-Server, der Aktivitäten empfängt, die der Server sendet
    • fedify lookup ermöglicht die Inspektion von Objekten, die von anderen Servern veröffentlicht wurden
    • fedify lookup --authorized-fetch erzeugt ein temporäres Schlüsselpaar und startet einen temporären ActivityPub-Server, um signierte Anfragen an Objekte hinter Secure Mode zu senden
    • @fedify/lint ist ein ActivityPub-spezifischer Linter, der 20 Arten von Interoperabilitätsfehlern erkennt, etwa wenn einem Actor inbox fehlt
    • Mit den Mocks von @fedify/testing lassen sich Tests ohne Netzwerk ausführen
    • @fedify/debugger hängt mit einer Zeile ein Debug-Dashboard an, sodass sich Aktivitäten und Ergebnisse der Signaturprüfung im Browser in Echtzeit ansehen lassen
    • Für Produktionsumgebungen ist OpenTelemetry-Instrumentierung eingebaut und liefert 28 Span-Typen sowie 37 Metriken
    • Es gibt außerdem einen Monitoring-Leitfaden und das Lasttest-Tool fedify bench für ActivityPub
    • Die offizielle Dokumentation besteht aus 30 Handbuchkapiteln und 5 Tutorials und behandelt reale Praktiken wie PromQL-Abfragen und Alert-Regeln zum Anzeigen von Queue-Backlogs sowie Eigenschaften, damit Avatare in Mastodon sichtbar werden

Bereits im Einsatz und Einstieg

  • Fedify wird bereits in realen Diensten eingesetzt
    • Ghosts ActivityPub-Dienst
    • Encyclia, das ORCID-Forschungsprofile mit dem Fediverse verbindet
    • SiliconBeest, das serverless auf Cloudflare Workers läuft
    • die koreanische Blogging-Plattform Typo Blue
    • die Single-User-Microblogging-Plattform Hollo
    • das von der Community betriebene Hackers' Pub
  • Die Tutorials bieten Beispiele für verschiedene Größenordnungen
  • Das Ziel von Fedify ist nicht, mehr ActivityPub-Expertinnen und -Experten auszubilden, sondern Entwicklerinnen und Entwicklern zu ermöglichen, föderierte Apps zu bauen, ohne die Details von ActivityPub kennen zu müssen
  • Der Startbefehl lautet npm init @fedify
  • Wenn Hilfe benötigt wird, können der Matrix-Raum oder GitHub Discussions genutzt werden

1 Kommentare

 
GN⁺ 5 시간 전
Meinungen auf Lobste.rs
  • Das ist der Grund, warum es bei ActivityPub-Projekten so viele gegenseitige Forks gibt: Es ist einfacher, den Ansatz anderer nachzuvollziehen, als alles selbst zu implementieren.
    Was der Autor vorschlägt, wirkt tatsächlich nicht sehr anders als die häufig anzutreffenden Forks von Misskey oder Pleroma. Auch eine Library hat ihre eigene Sichtweise und ihren eigenen Ansatz und scheint nicht allzu viel Kontrolle abzugeben. Trotzdem hat sie den Vorteil, dass sie nicht wie beim Forken eines ganzen Servers sogar die UI vorgibt.
    Aus Sicht von jemandem, der AP implementiert, ist der schwierigste Teil, dass es keine gute Methode gibt, JSON-LD korrekt zu verwenden. Wenn man Objekte einfach in eine Standardrepräsentation umwandeln könnte, würde die Interaktion ganz natürlich folgen. Aber um es wirklich wie verlinkte Dokumente zu verwenden, ist es zu ineffizient, und wenn man es wie rohe JSON-Dokumente verwendet, wird man von unzähligen Edge Cases erschlagen. Bisher habe ich den zweiten Ansatz gewählt und bin daran zugrunde gegangen.

    • Gerade wenn man an Signaturen denkt, wird das Problem einer „Standardrepräsentation von Objekten“ noch wichtiger. Die frühere XML-Kanonisierung gab es genau wegen dieses Signaturproblems, also um sicherzustellen, dass die Byte-Serialisierung beim Empfänger mit der des Senders übereinstimmt.
      Das ist nicht exakt dasselbe Problem wie in der JSON-LD-Welt, aber auch nicht völlig unabhängig davon.
      Allerdings haben meiner Ansicht nach viele JSON-nahe Technologien ähnliche Probleme. Es gibt zu viele Arten, dasselbe logische Schema mit JSON Schema auszudrücken, und dadurch wird die Interaktion mit Technologien rund um JSON Schema geradezu absurd schrecklich. Besonders OpenAPI-Schemas sind ein ähnliches, aber nicht identisches Horrorkabinett, und selbst ohne die Zahl der Schema-Draft-Versionen zu berücksichtigen, ist es schon schlimm genug.
    • Ich habe über eine AP-Server-Implementierung nachgedacht, aber noch nicht damit begonnen, also sollte man das mit viel Vorsicht genießen. Ein hilfreicher Ansatz könnte sein, die Anwendung in kleinere Dienste aufzuteilen und stärker auf das Actor Model zu setzen, damit es wie ein „integriertes“ Interface wirkt. Man könnte sich zum Beispiel an der Trennung von MTA und MUA bei E-Mail-Servern orientieren.
      Der „MTA“-Dienst von AP wäre dafür zuständig, Nachrichten aus der Outbox zu versenden und Nachrichten in der Inbox zu empfangen. JSON-LD-Dokumente sind aus Sicht dieses Dienstes im Grunde fast Blob-Daten. Ein wenig Parsing ist nötig, um Absender und Empfänger zu ermitteln, aber viel mehr nicht. Auch der Speicher könnte dateibasiert sein; wenn ich mich richtig erinnere, nutzt go-ap so einen Ansatz.
      Der „MUA“ von AP ist die eigentliche Anwendung. Das ist die Seite, die die Bedeutung von JSON-LD verstehen muss. Man könnte etwas wie PostgreSQL nutzen, die Dokumente als jsonb speichern und über generierte Spalten und Views eine SQL-freundliche Form bereitstellen. Dann kann man je nach Objekttyp entscheiden, wie sich das Dokument am sinnvollsten darstellen lässt.
      Als weiteres Beispiel könnte man auch einen Suchdienst als Actor modellieren und die Ergebnisse über eine temporäre Outbox zurückgeben lassen.
  • Eine äußerst wertvolle Liste von eigenwilligem Verhalten verschiedener Implementierungen und möglichen Gegenmaßnahmen.
    Leider ist in GoActivityPub noch nicht einmal die Hälfte davon implementiert.

  • Ich war dankbar, dass der Artikel zunächst technisch begann, aber ab der Mitte schien er in Richtung Eigenwerbung für das Framework abzubiegen, was die Lektüre weniger angenehm machte.
    Es ist schön, dass manche Teile der TypeScript-Welt diese Implementierungsbesonderheiten vielleicht nicht noch einmal neu entdecken müssen. Aber als mentales Modell gilt: Wenn es Aufzeichnungen gibt wie „unter diesen Bedingungen und in diesen Situationen kommt dieses Ergebnis heraus, und diese Korrektur ist nötig“, dann können auch Nicht-TypeScript-Kontexte, etwa die Autoren des Schwesterprojekts GoActivityPub, von den Ergebnissen dieser Mühen profitieren. Einige dieser Dinge werden hier zwar behandelt, aber der Artikel ist eine Momentaufnahme, während das Projekt mit der Zeit offenbar alle Interoperabilitätsbugs ansammeln will.
    Die derzeitige Alternative besteht aus meiner Sicht nur darin, alle nicht von Menschen geschriebenen Commit-Messages durchzulesen und dabei Bugs von Fedify selbst von Interoperabilitätsbugs zu unterscheiden.
    Besonders ironisch ist, dass das Repository zwar so wirkt, als sei es bei AI „all in“, aber trotzdem keine solche Buchführung betreibt. Die Werbung, die ich über LLMs gehört habe, lautete doch, dass sie repetitive Fleißarbeit automatisieren. Dann könnte Claude GitHub-Issues erstellen oder, noch besser, in einer .md-Datei im Repository dokumentieren, was beobachtet wurde und wie Fedify es behebt. Es gibt sogar einen eigenen Debugger und irgendwelche „Best Practices“, deren Bedeutung mir unklar ist; das wäre also genau die passende Aufgabe.

    • Hier werden wirklich triviale Probleme aufgebauscht und wie ein Scheitern von ActivityPub dargestellt. Zum Beispiel: Wenn man 5.000 Follower hat, wird ein einzelner Beitrag zu Tausenden HTTP-Zustellungen, und wenn man das direkt im Request-Handler macht, dauert die Antwort auf den Posten-Button 30 Sekunden oder der Server kippt um, also solle man eine Queue verwenden.
      Warum führt man Requests an Drittanbieterdienste inline aus? Das ist Webanwendungs-Grundwissen. Wenn man mit Drittanbieterdiensten kommunizieren muss, schickt man das in einen Background Job. Wenn Informationen für die Antwort auf den Request nicht nötig sind, gehören sie in einen Background Job. Probleme, die entstehen, weil man solche Requests im Request-Handler ausführt, sind selbstverschuldet auf dem Niveau, auf einen Rechen zu treten und ihn ins Gesicht zu bekommen; mit ActivityPub hat das nichts zu tun.
      Wenn eine Zustellung fehlschlägt, muss man sie erneut versuchen, und Fragen wie der Zeitplan, ob man exponentielles Backoff nutzt, wie oft man es versucht oder ob man 500 Internal Server Error und 410 Gone als denselben Fehler betrachtet, sind einfach allgemeine Probleme der Webanwendungsentwicklung. Das sind Probleme, die auftreten, wenn eine Job Queue Requests an Drittanbieterdienste stellt, und sie haben nichts mit ActivityPub zu tun. Die meisten Web-Frameworks haben dafür vernünftige Defaults. Entscheiden muss man nur an der Stelle, an der abhängig vom konkreten Fehler bestimmt wird, ob ein Retry sinnvoll ist. Einen 410 zu wiederholen ist Verschwendung, aber kein Problem, das dringend gelöst werden muss. Es erhöht zwar den Speicherdruck auf die Job Queue, wird die Anwendung aber wahrscheinlich nicht innerhalb weniger Stunden zum Absturz bringen.
  • „Schau, ob es abgelehnt wird, signiere dann auf andere Weise erneut und merke dir pro Server, welche Methode funktioniert hat“ – was lese ich hier eigentlich? Ist das der Grund, warum die Mastodon-Entwicklung so langsam ist?
    „Ein einzelner Beitrag wird zu Tausenden HTTP-Zustellungen“ – und das in Ruby, einer Sprache, die für hervorragende Netzwerk-Systemprogrammierung und Queuing berühmt ist.
    Kaum zu glauben; gut, dass das in eine Library verpackt wurde, aber trotzdem.

  • Nachdem ich ActivityPub in Java implementiert hatte, kam ich zu dem Schluss, dass man solche Server-zu-Server-Protokolle einfach besser auf git aufbauen sollte.
    Ein großer Teil der Komplexität existiert, um Probleme erneut zu lösen, die git bereits besser löst. Wenn man das als JSON-Dokumente in einem git-Repository modelliert, muss man sich nicht mit Pagination beschäftigen. Das Protokoll garantiert bereits, dass nur noch nicht vorhandene Daten gesendet werden, man bekommt Commit-Signaturen, garantierte Ereignisreihenfolge, die im Artikel genannten Probleme werden gelöst, und die Historie gibt es gratis dazu. Man könnte daraus eine Art Greenspun’sche zehnte Regel formulieren: In solchen Protokollen steckt eine fehlerhafte, langsame halbe Implementierung von git.

    • git ist keine besonders gute Wahl, weil die Historie von Parent-Commits abhängt. Ein Merkle-Tree-Gossip-Protokoll, das mit einer ähnlichen Aushandlungsstrategie arbeitet, könnte dagegen gut passen.
  • Dieser Artikel liest sich wie ein von AI erzeugter Beitrag niedriger Qualität.
    Genauer gesagt verstehe ich nicht, warum er in Erzählform geschrieben wurde. Die hier vermittelten Fakten hätten viel knapper und weniger voreingenommen dargestellt werden können, und die Erzählung überzeugt nicht. Vor allem, weil es viele typisch AI-artige Formulierungen gibt.
    Angenehm zu lesen war es nicht. Trotzdem danke, dass die Probleme benannt wurden; ich hoffe, dass man sie auf andere Weise nachlesen und beheben kann.