kolmapäev, 29. september 2010

Progressist JavaScript põhise e-posti serveri kirjutamisel

Mõnda aega tagasi kirjutasin kuidas sain valmis POP3 protokolli implementatsiooni Javascriptis. Sain sellest katsetusest pisiku külge ja otsustasin proovida luua samas stiilis täiemahulist e-posti serveri tarkvara. Väga kaugele pole jõudnud, alustalade seadmine on palju aega ja mõtlemist nõudnud, aga tundub, et kõik on ületatav. Hetke progressi saab näha siit.

Kuna eri serverid (SMTP, POP3, IMAP) on üles ehitatud käsklus-vastus stiilis tekstipõhiste serveritena, lõin sarnaste situatsioonide jaoks serveri baasobjekti, mis sisaldab kõike toimimiseks vajalikku ning mida tuleb lihtsalt konkreetse serveri vajadustest lähtuvalt uute käsklustega täiendada. Näiteks POP3 server saab defineerida käskluse "STLS", aga SMTP hoopis "STARTTLS". Nimetasin selle serveri baasobjekti Request-Answer-Interface'ks ja selle source on nähtaval siin (faili lõpus on kommentaarina ka minimaalne implementatsioon). Täpsemat näiterakendust saab uurida failidest pop3.js ja smtp.js.

Hetke staatuseks on, et SMTP server suudab kirju vastu võtta ning töödelda täielikult läbi kirja päised. Järgmise sammuna on kavas siis kirja sisu töötlemine. Kuna kirja sisu võib olla väga suur (sõltuvalt manuste olemasolust ja suurusest) tuleb seda teha jupikaupa, mitte korraga ja see lisab ühe keerukusastme juurde. Kõige suurem probleem, Base64 dekodeerimine jupi kaupa on praeguseks lahendatud.

Süsteemist siis niipalju, et põhiosa on kirjutatud JavaScriptis (Node.JS), vähemalt üks moodul C's (node-iconv), kasutajate autoriseerimise andmed ja sessioonide andmed asuvad Redis andmebaasis, kirjade sisu ja meta-info läheb MongoDB andmebaasi ning manused MongoDB GridFS failihoidlasse. GridFS annab mugava võimaluse jagada faile suure hulga serverite vahel - selleks tuleb luua MongoDB klaster ning selles saab failide jupitamise ja kokkukogumisega GridFS juba kergelt hakkama. Samuti saab faili juurde salvestada suure hulga suvalist meta-infot. See on midagi, mida tavaline failisüsteem ei võimalda.

Kogu idee asjal on selles, et reeglina hoitakse e-posti originaalkujul (mime formaat) tekstifailides. Kas siis kogu postkast on ühes suures failis või siis on eri kirjad eraldi failides samas kataloogis. Selge on see, et taoline struktuur ei skaleeru ja on üldse ebaefektiivne (näiteks manused salvestatakse kettal Base64 kodeeringus, mis on kolmandiku võrra suurem, kui originaalmaht jne). Minu lahendus hoiaks süsteemselt siis kõiki andmeid neile sobivaimas hoidlas (Redis, MongoDB, GridFS) ning nende andmete põhjal pandaks alles vajadusel (klient üritab kirja alla laadida või tuleb see serverist välja saata) kokku standardne mime formaadis e-kirja dokument.

Selline struktuur annab ka meeletu eelise näiteks veebipõhise e-posti kliendi loomiseks - pole vaja keskenduda millelegi muule kui kasutajaliidesele, kogu info on programmi jaoks loetaval kujul andmebaasis juba olemas, midagi teisendada pole vaja.

Kommentaare ei ole: