Leosztottam nullával… – Kalandjaim az utóbbi hónapokból

Az utóbbi időben nem nagyon tudtam blogolni, mivel az iskola indulásával radikálisan megnőtt teendőim száma, így nagyon kevés időt hagyva bármilyen írásos önkifejezésre (kivéve a programozást). Az alábbi cikk pár érdekes sztorit mesél el az utóbbi időből.

Szaporodnak a számítógépek

Alapvetően a munkámra szeretném fogni a homelab bővítését, de – mint oly sok vásárlásom mögött – itt is a felfedezés és kísérletezés vágya hajtott. Az új szerver szintén egy Fujitsu, még a modellszáma is ugyanaz (S920), konfigurációja pedig hasonló a “főgéphez”, csak kicsit kevesebb RAM van benne. A 2-es szerver node mindössze 18 ezer forintomba került, de megnyitotta előttem az elosztott, cluster alapú számítógépes rendszerekkel való kísérletezés lehetőségét.

Közben volt egy katasztrofális meghibásodás a főszerverben (elégett benne az mSATA SSD), amit csak két nap alatt sikerült javítani (ennyit a High Availability-ről), addig is minden állt, nem mentek a weboldalak (ami miatt kaptam is az iskolatársaimtól). Itt érdemes megjegyezni, hogy mindez elkerülhető lett volna, ha a használt SSD adott volna magáról bármilyen jellegű S.M.A.R.T. adatot (mint ahogy nem adott). Az új SSD-k már rendesen figyelik magukat, így mindenki megnyugodhat…

A Proxmox clusterezése

Minden felkészültebb Proxmox admin ezen a ponton valószínűleg már nagyon el szeretne küldeni melegebb éghajlatra, mivel egy Proxmox clusterhez a Corosync (állapotmenedzsment rendszer) és Quorum (alapvetően az esetleges kimaradások esetén a számítógépek állapotát megállapító program) miatt minimum három node-ra van szükség, de mivel a jelenlegi helyzet nem követeli meg a szuper High Availability-t, így egy egyszerű konfig fájl változtatással (adtam egy extra votetot a főszervernek) tettem félig-meddig quorate-té (szavazásra képessé) a hálózatot.

Így a terhelés már két gépen oszlik meg, lehet pakolgatni össze-vissza az összes VM-et és LXC-t (sajnos csak teljes leállítás után, mivel a tárolást nem clustereztem be [még]).

Íme a gyönyörű (már clusterezett) Proxmox telepítés

Összesen így van 8 CPU-magom, 23 GB RAM-om, és több mint 1.5 TB gyors elérésű tárhelyem.

Nem is rossz…

És a legszebb az egészben az, hogy mindez (tehát a két gép, switch és router, plusz a tárhelyet részben szolgáltató NAS) mindösszesen 25W-ot használ. Így nem is viszi csődbe a családot a villanyszámla… Nem úgy, mint egyesek.

Mivel:

25W = 0.025 kWh

ami éves szinten 8765 üzemóra,

ami 291 kWh fogyasztásnak felel meg (ami olyan 7800 forint).

Saját apcupsd dashboard.

Osztás nullával

És most jön a legjobb, várva várt rész, de mielőtt elmesélem a nullával osztás történetét, egy kis háttér. Munkám során informatikai támogatást nyújtok egy EU-s projektben, ami így magában foglalja a programozást is (mivel nem a következő Facebookot kell lefejleszteni, így gondoltuk, hogy még nekem is menni fog). A cél egy kérdőívező rendszer lefejlesztése volt, ami képes dinamikusan változtatni a mutatott contentet, akár a user válaszai alapján átrakosgatva azokat (ez utólag nem hangzik jól). A végén pedig (mivel ugye az egész teljesen anonim) a böngészőben legenerál egy PDF-dokumentumot, amit a kitöltő letölthet. A PDF-ben lévő szöveg dinamikus, amit egy háttéradatbázis alapján generál le a rendszer.

Tehát ez a specifikáció, de mi a megoldás? Nézzük a tech stacket:

Backend:

  1. Webszerver: Apache2, később NGINX
  2. DB: sqlite3 (tervezett a LiteStream alapú replikáció és a több zóna, ha elég user lesz)
  3. A backendet itt a Pocketbase adja, ami bár nem iparági sztenderd, de nagyon gyors és stabil, plusz lehet JS-ben szkriptelni, ami azt jelenti, hogy ugyanúgy programozhatom, mint az eddigi Express alapú backendjeimet (csak egy kicsit nehezebb, mert nem node.js a backend nyelve, hanem egy minimalista JSVM implementáció).

Frontend:

  1. ReactJS, React Routerrer és egy valag egyéb csomaggal (React-PDF, pocketbase sdk, stb…)
  2. Más itt nincsen, alapvetően minden a Reacton alapul

Nehézségek

Mik is voltak a főbb nehézségek? Először is: nem nagyon kéne 36 oldalas PDF-et generálni a böngészőben. De ez még csak a felszínt kapargatja, hiszen a terv számos egyéb sebből vérzett: Az oldalnak jól kellett kinéznie és ugyanakkor gyorsnak kellett lennie, egyszerűnek kellett lennie, ugyanakkor szofisztikáltnak. És akkor itt vagyok én, a magányos webdev, akinek mindenkivel harcolnia kell minden featurért.

A frontendet szétoptimalizáltam, minden, ami nem szöveg volt, az egy SVG-ből töltött be, amit előtte minifikáltam és összetömörítettem (plusz GZIP-et is rakott rá még e webszerver). Így nem is néz ki olyan rosszul az oldal.

Ő lenne az…

Pontozás

A kérdőívet összeállító szakmai csapat egy bonyolult pontozással állt elő: minden kérdést máshogyan osztályozunk, de a végén modulonként (tehát témánként) egy egységes 0 és 100 közötti százalékos értéket számítunk. Ezen értékek százalékos átlaga adja az össz-százalékot.

A kérdéseket a következő módokon lehet osztályozni:

  • Sima: 0 és n közötti pontok, ahol n pozitív valós szám
  • Tükrös: -n és n közötti pontok, ahol n valós szám (itt főleg a különféle veszélyekre kell gondolni [gazdasági, politikai helyzet, stb.)
  • Egyéb (ez lett az alapértelmezett): -k és n között, ahol mind n, mind k valós szám

Ezeket az alábbi összegző függvénnyel kezeltem:

    function handlePercentage(score, minScore, maxScore) {
        //No score available
        if (isNaN(score / minScore) === true && isNaN(score / maxScore) === true) {
          return 0
        }
        if (minScore === 0 && maxScore === 0 && score === 0) {
          return 0;
        }
        if (minScore !== 0 && maxScore === 0) {
          if (isNaN(score / minScore)) { return 100 }
          return 100 - Math.abs(score / minScore) * 100;
        }
        if (minScore === 0 && maxScore !== 0) {
              if (isNaN(score / maxScore)) { return 0 }
          return (score / maxScore * 100)
        }
        if (Math.abs(minScore) === Math.abs(maxScore)) {
          if (isNaN(score / maxScore)) { return 0 }
          var projectedMaxScore = maxScore * 2
          return ( (score + maxScore) / projectedMaxScore * 100)
        }
        var projectedMaxScore = maxScore + Math.abs(minScore)
        return ( (score + Math.abs(minScore)) / projectedMaxScore * 100)
      }

Itt volt gond a nullával, mivel az lehet 100%, 0% és 50% is, ugyanabban a kérdőívben. Több darab, félóránál hosszabb telefonbeszélgetésbe tellett, mire megértettem, hogy mit is kell csinálni. Végül a pontszámokat el is kellett rejteni a PDF-ben (nehogy megijedjen tőle valaki).

A pontszámok alapján ezután intervallumot keres a rendszer és legenerálja a személyre szabott gazdaságértékelést.

Logika

A program igazi ütőkártyája a programozhatóság: minden kérdés látja a többi kérdés (és a saját) válaszait, ami alapján át tudja programozni magát és a többi kérdést. Így lehet, hogy egy 36 kérdéses ívből lehet 34, de akár 45 darab kérdéses változat is (mindezt láthatatlanul teszi a rendszer). Ehhez a keretrendszer (SurveyJS) szkriptnyelvét hívtam sgítségül:

{
  "type": "radiogroup",
  "name": "g154",
  "scoringCategory": "Üzletvitel, foglalkoztatás és innováció",
  "title": "Részt vesznek-e 30 év alatti fiatalok (munkavállalók vagy családtagok) a gazdálkodásban, és mi a részvételük legmagasabb szintje?",
  "visibleIf": "{a9} anyof [ 'Családi munkaerő', 'Időszakos, fizetett munkaerő', 'Állandó, fizetett alkalmazottak' ] and {a9} notempty",
  "isRequired": true,
  "choices": [
      ....
  ]
}

Ez egy viszonylag egyszerűen megérthető logikai feltétel (a “visibleIf” sor a lényeg), de vannak viccesebbek is:

    {
      "value": "A munkavállalók fizetése, juttatásai",
      "text": "A munkavállalók fizetése, juttatásai",
      "visibleIf": "( {inheritedType} contains 'SZN' or {inheritedType} contains 'SZK' or {inheritedType} contains 'Ü' or {inheritedType} contains 'NH' or {inheritedType} contains 'IÁ' or {inheritedType} contains 'EÁ' ) and ({a9} anyof ['Időszakos, fizetett munkaerő', 'Állandó, fizetett alkalmazottak' ] and {a9} notempty)"
    },

És ilyenből van kb. 50 az adatbázisban…

Ilyen egy kész jelentés (kivettem a válaszokat, mivel az már személyes jellegű adat):

kerdoiv

Lényeg

Az utóbbi pár hónap meglehetősen kalandos volt: nagyon sokat dolgoztam az új szoftveren, megismertem az informatika (és a fáradtság) újabb mélységeit, emellett letoltam három OKTV-t is (fizika, német, angol), illetve megpróbáltam levizsgázni vezetésből, eddig sikertelenül. Tanulság: ne vállalj el teljesíthetetlen feladatot, de azért néha állítsd magad kihívások elé.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *