Twee maanden geleden was onze collega Gerard Klijs op de GraphQL Summit in San Francisco om te spreken over GraphQL en Kafka. Tijdens dit evenement had de Expedia Group een mooi verhaal over hoe ze GraphQL zijn gaan gebruiken en het inmiddels grootschalig gebruiken. Hier wil Gerard het in deze blog over hebben.

Wat hierbij vooral interessant was, was dat de individuele services Kotlin gebruiken, maar er voor de GraphQL proxy voor Apollo Federation gekozen is, op Node. Het is niet vanzelfsprekend dat verschillende GraphQL oplossingen goed samen werken, omdat de specificatie van GraphQL expres niet volledig is. Zo staat er in de specificatie wel hoe data van de cliënt en de server er uit moet zien, maar er staat niet op welke manier the informatie verstuurd word. In de praktijk is dit vaak geen groot probleem, omdat als voorbeeld de implementatie van Apollo genomen wordt.

Iets anders wat interessant was, was dat de gebruikte open source library voor Kotlin, code first werkt. Normaal gesproken ontwerp je als je GraphQL gaat gebruiken eerst een schema en voeg je daarna de code toe om de data uit het schema op te vragen. Een simpel voorbeeld is om van een product de naam en voorraad op te vragen met behulp van een ID. Dit zou zich kunnen vertalen naar een simpele query naar de database. Met deze library hoefde dat niet, op basis van annotaties wordt vanuit de code het schema gegenereerd.

Het lijkt makkelijk als het schema gegenereerd wordt, maar er zitten ook nadelen aan. Eén van de grootste nadelen is dat een triviale aanpassing in de code tot een breuk in het schema kan leiden. Om dit te voorkomen heeft Expedia Group een controle hiervoor toegevoegd aan de CI. Een week na de GraphQL Summit was er een presentatie die meer op ontwikkelaars gericht was.

Zelf gebruik ik voor mijn demo/test project GraphQL subscriptions. Dit is een manier waarbij de cliënt een stream van events terug krijgt. Omdat subscriptions in de presentatie niet genoemd werden vroeg ik Guillaume of de genoemde library daar ook support voor had. Er zijn namelijk best wat GraphQL server libraries die geen subscriptions ondersteunen. Dit was gelukkig het geval, en dus zou het geen probleem moeten zijn om de huidige implementatie in Clojure om te schrijven naar Kotlin.
Inmiddels is de Kotlin implementatie op Github te vinden.

Daarbij kwam ik wel wat verrassingen tegen. Door de combinatie van code generatie, en hoe variabelen in Kotlin worden gebruikt was het schema veranderd. Dit heb ik opgelost door het in de frontend aan te passen. In Kotlin is het expliciet wanneer een waarde null kan zijn, en dat ook in het schema terug. Dit gaf geen problemen omdat Clojurescript al goed met mogelijke null waardes omgaat. De code zelf schrijven gaf ook wat problemen, vooral omdat voor subscriptions de Publisher interface wordt gebruikt. Voor de Java versie had ik project Reactor gebruikt, maar vanuit Kotlin wilde ik graag met coroutines werken. Er leek eerst niet echt iets te zijn om hetzelfde event met meerdere clients te delen. Na een tijd zoeken bleek het met ‘broadcast’ wel te kunnen.

Nadat de implementatie klaar was, en ik door middel van de frontend getest had dat hij werkte, was het tijd om mijn test framework erop los te laten. Tijdens de test worden subscriptions gebruikt om geld over te maken, waarbij de load in stapjes verhoogt wordt. Tegelijk wordt zowel de latency gemeten, en wordt ook om de 20 seconden het processors en geheugen gebruik van de verschillende componenten gemeten. Echter hield de test er na twee minuten al mee op.

Ik kon het probleem zelf niet zo snel vinden. Wel vind ik een van de maintainers op slack. In overleg heb ik toen een issue geopend. Het is echter lastig om het hele test framework te draaien, omdat je Clojure geïnstalleerd moet hebben. Uiteindelijk bleek het in de frontend te reproduceren te zijn door rond de 120 overschrijvingen te doen. Er kwam erachter geen fout, maar de websocket reageerde gewoon niet meer. In samenwerking werden er verschillende verbeteringen aangebracht. Maar nog altijd bleef het probleem bestaan. Uiteindelijk was het probleem een interpretatie van de spec voor GraphQL over websockets. Zie hier Github. Nu de laatste pr gemerged is, is het probleem op de master branch opgelost. In een productie setting zou je dan moeten wachten tot de nieuwe release voor je verder kan. Maar in dit geval kan ik mijn laptop weer een paar nachten aan het werk zetten, en de data daarna vergelijken met andere implementaties.

Origineel van Open Web.