Dessa fantastiska problem

Marcus Olsson,

Som jag tidigare har skrivit så är programmering verkligen mitt stora intresse – ofta är det själva problemlösningsaspekten jag gillar extra mycket.

De senaste två veckorna har jag för min nuvarande arbetsgivare där jag ställdes inför en rad intressanta problem som jag var tvungen att lösa.

För applikation jag byggde så skulle jag hämta data från en server (hade självklart tillåtelse att hämta och använda datan) som inte erbjöd ett API – så jag var tvungen att använda cURL för att posta data, hämta HTML:en och gå igenom DOM:en för att få hem den datan som är relevant.

SQL-frågan som körs vid varje cURL-anrop är dock ett väldigt tungt sådant, och jag behöver ny data var 10:e sekund – applikationen skulle dessutom kunna köras på oändligt många klienter samtidigt. Detta blir självfallet ett problem då om applikationen körs på exempelvis 50 klienter samtidigt, och postar samt hämtar data var 10:e sekund (300 anrop i minuten) – jag vill självklart inte sänka målservern, det gör ingen populär.

Hur man (eller i alla fall jag) vanligtvis skulle hämta datan: Klienter till målserver

Så för att inte sänka målservern fick jag köra på den här varianten: Klienter till egen server till målserver

Så långt är frid och fröjd. Men då kommer nästa problem. För att få vår egna servrar att hämta data var 10:e sekund så går det inte att använda sig av cron-jobb – de går endast att köra varje minut som lägsta interval (går visserligen att lägga det som ett bakgrundjobb med en "sleep"). Men dessutom tyckte jag att det vore smidigt om ingen data hämtades om inga klienter körde applikationen.

Så jag designade applikationen på det här viset: Main UML

Kort förklarat: på klientsidan genererar jag ett unikt ID (eller i alla fall strängkombination av siffror och bokstäver med ett par miljoner olika kombinationsmöjligheter), skickar det ID:t till servern – och om ID:t kommer från "huvudklienten", hämta datan från målservern och skriv datan till en JSON-fil. Som svar på anropet kommer också JSON-formaterad data som talar om status och en rad andra parametrar.

Om statuskoden exempelvis är 2 (som betyder sekundär klient), läses av JSON-filen av varje sekund (jag vill ju att alla klienter ska vara någorlunda synkade), eller om statuskoden är 1 (huvudklient) räcker det att läsa JSON-filen när anropet till den egna servern är slutförd.

I JSON-filen som datan skrivs till sätter jag också en tidsstämpel när den skrevs, och vilket ID klienten hade som huvudklient vid det tillfället. Då kan jag lätt se om jag behöver byta huvudklient (om den användare vars klient är huvudklient stänger sin webbläsare exempelvis), vilket i det här fallet görs om filen är äldre än 20 sekunder.

JSON-filen med data läses in på klienten via AJAX, och datan renderas med mustache.js – snabbt, snyggt och elegant.

Resultatet är en applikation (som endast används internt) som jag faktiskt är lite extra nöjd med – just för att det var en rad intressanta problem som var tvugna att lösas.

Har du någon idé på hur jag skulle kunna ha löst det här annorlunda, eller egna lösningar på andra problem som du är extra nöjd över? Hojta till på Twitter!