Bluesky’s firehose – som at drikke af en brandhane?

At konsumere data fra Bluesky’s firehose kan bedst beskrives som at drikke af en brandhane – en konstant strøm af information, der kræver både skarp filtrering og effektiv behandling for at få mening ud af kaosset.

Kom med bag kulisserne og læs om de tekniske udfordringer et system til at filtrere indlæg fra hele Bluesky-netværket for over 10.000 danske Bluesky-konti – og hvilke løsninger, der virkede.

Hvad er Bluesky’s Firehose?

Bluesky’s firehose er en højhastigheds-datastream, der sender realtidsindhold fra netværket til forbrugere. Firehose er navnet på den konstante strøm af millioner af indlæg, kommentarer, opdateringer af brugeprofiler og andre datapunkter, der flyder gennem en enkelt forbindelse. For udviklere, der ønsker at analysere eller filtrere specifikt indhold, kan det være en monumental opgave at håndtere både datamængden og kompleksiteten.

Mission: Fokus på dansk indhold

Opgaven var konceptualt enkel, men kompleks i udførelse: At identificere og udvælge alle indlæg fra danske Bluesky-brugere i en strøm af global data. Med over 10.000 identificerede danske konti skulle der bygges en løsning, der hurtigt kunne matche hver eneste datapakke med vores liste af danske Decentralized Identifiers (DIDs).

Denne udfordring rejste flere tekniske spørgsmål:

1. Hvordan sikres, at vores system kan håndtere hastigheden og datamængden i firehose-streamen?

2. Hvordan filtreres data effektivt uden at flaskehalse opstår?

3. Hvordan bevares fleksibilitet til f.eks. at tilføje eller fjerne DIDs, uden at det påvirker ydeevnen?

De tekniske udfordringer

1. Hastighed: At følge med brandhanen

En af de største udfordringer er firehose’ens hastighed. Strømmen af data er kontinuerligt høj og kræver, at løsningen kan processere hver enkelt datapakke i realtid. Hvis vi ikke følger med, risikerer vi at miste værdifulde datapunkter.

Valget faldt på en løsning baseret på Go (Golang), kendt for sin høje ydeevne og evne til at håndtere samtidige processer effektivt. Ved hjælp af Go’s goroutines og kanaler blev det muligt at opsætte en pipeline, der samtidig kunne læse, dekode og filtrere data uden flaskehalse.

Bluesky Indigo er navnet på platformens adgang fra programmeringssproget GO, og den samt en implementering af samme findes tilgængeligt på github.

2. Filtrering: Hvor hurtigt kan vi finde 10.000 DIDs?

At matche indlæg med vores liste af danske DIDs var en nøgleudfordring. Oprindeligt brugte vi et simpelt Go-map (map[string]bool), som giver O(1)-opslagstid. Det betyder at opslagstiden, der bruges til at afgøre om en besked er relevant eller ej, er den samme for 10 eller 10.000 værdier. Og dette fungerer faktisk fint. DID’erne findes i en fil, som loades ind i Go-map’et når processen starter. Indlæsningen tager godt og vel et sekund.

Firehose’n leverer gerne flere hundrede – måske op imod tusinder af beskeder pr. sekund. Hver besked skal udpakkes (for den er modtaget i en såkaldt CBOR-encoding). Udpakningen går stærkt, og så snart afsenderens DID kan uddrages fra beskeden, kan vi undersøge om den findes i vores map.

For Twitter’s vedkommende kunne man (ihvertfald i “gamle dage”) – sende en liste af filtre af bruger id’er, som ville være de eneste konti man ville modtage indlæg fra via Twitters firehose. Med Bluesky og AT protokollen, er firehosen ens (og omfangsrig) for alle, og man må selv foretage filtrering af relevant indhold. Man skal altså ikke bare have adgang til en hurtig maskine på en hurtig forbindelse, men man skal også sikre at man ikke støder mod en eller anden begrænsning i mængden af trafik fra serverhosten.

Skulle vi støde på en begrænsning i performance, hvis vi f.eks. oplever at der pludselig er 100.000 danskere på Bluesky, vil det måske blive relevant at se på den såkaldte Bloom-filtrering. Ved at loade brugernes DID ind i et map, bruger vi hukommelse, og bliver hukommelsesforbruget problematisk, kan Bloomfiltrering måske gøre en forskel i performance.

2. Skalerbarhed og fleksibilitet

At vedligeholde en liste på 10.000+ DIDs kræver en dynamisk og skalerbar løsning. Vi designede et API, der gør det muligt at opdatere listen i realtid uden at stoppe dataflowet. Dette sikrer, at vores system altid er up-to-date, selv hvis nye danske brugere tilslutter sig Bluesky.

Endelig skal indholdet fra de relevante brugeres posts på Bluesky gemmes i en fil. Database nedetid er sjældent, man at miste adgangen til et filsystem er sjældnere. Derfor skrives nye indlæg ikke direkte til databasen, men via filer, der senere kan samles op af andre processer og gemmes i databasen. Går databasen offline, mister vi ikke data, men har i værste fald en forsinkelse der kan indhentes når databasen er online igen.

Diskadgang er, i dag, typisk et spørgsmål om at gemme noget på en Solid State disk, men selv denne kan være belastet på et system, der måske får travlt. Opgaven med at styre adgang til filen der skal skrives til, og selve skrivningen blev derfor flyttet ud i en goroutine, så denne del ikke ville kunne stå i vejen for indlæsning og behandling af den næste besked fra Bluesky’s firehose.

Strategien er altså hurtigst muligt at afgøre om en besked er irrelevant (ikke på vores DID-liste), og hurtigt springe videre til næste besked hvis det er tilfældet. Er beskeden relevant, skal vi så tidligt som muligt overlade det videre administrative arbejde til en goroutine, så hovedprocessen hurtigst muligt kan undersøge den næste besked fra firehosen. Jo tidligere vores kode kan afgøre irrelevans eller det modsatte, jo højere beskedfrekvens må vi forventes at kunne håndtere – og det er nødvendigt fordi den globale Bluesky-trafik må ventes at stige.

At Go, som kompileret sprog, er yderst velegnet til højtydende opgaver som denne er virkelig en gevinst.

Resultater

Efter nogle iterationer lykkedes det at skabe et robust system, der kan håndtere Bluesky’s firehose og filtrere danske indlæg uden forsinkelse. Vores løsning:

• Kan processere flere tusinde datapakker i sekundet.

• Har en ekstremt lav fejlrate takket være kombinationen af datastrukturer.

• Giver os mulighed for hurtigt at justere filtreringslogikken uden nedetid.

Hvad vi lærte

At arbejde med Bluesky’s firehose har kastet vigtige lektioner af sig om, hvordan man håndterer højhastighedsdatastreams. Effektiv filtrering og skalerbarhed er nøglen, når man arbejder med store datastrømme i realtid. Og ved at kombinere værktøjer som Go og optimerede datastrukturer kan man opnå en imponerende ydeevne.

Perspektiver for fremtiden

Bluesky’s firehose åbner dørene for en lang række innovative applikationer – fra sentimentanalyse til netværkskortlægning.

Har du lyst til at vide mere om arbejdet med Bluesky’s protokol og firehose, så tøv ikke med at tage kontakt.