16 000 meldinger over 4 måneder kom ikke frem

I mars i år kunne vi lese at helsepersonell på St. Olavs hospital hadde sendt ut brev til pasienter i over 4 måneder uten at de faktisk hadde nådd pasientene. Over 16 000 meldinger om folk sin helse kom ikke frem. Brukergrensesnittet til legene indikerte at meldingene hadde blitt sendt, så de trodde alt var i orden.

(Som om ikke det er ille nok, har de meldingene som kom frem ofte vært helt uleselige for mottaker)

Senere på året fikk vi tilsvarende nyheter om bekymringsmeldinger til barnevernet. Politiet hadde sendt meldinger, men ingen i barnevernet hadde fått dem.

Hva har skjedd her? Hvor vanskelig kan det være å sende meldinger i IT-systemer? Det er en ganske grunnleggende ting man gjør i software. Har vi ikke lært hvordan dette gjøres ennå?

Eller er det nettopp det vi har?

Robuste systemer

Det vi har lært, er at når ett system skal sende en melding til et annet system, så kan det være at dette andre systemet ikke er tilgjengelig! Og det er fryktelig slitsomt. Da får vi feilmeldinger som må håndteres og brukere som klager. Brukerne tror det er noe feil med vårt system. Masse styr. Hvorfor skal oppetiden og opplevelsen av systemet vi lager være affektert av andre systemer vi ikke har kontroll på i det hele tatt?

Vi ser samme trend i vår egen kommunikasjon også. Før i tiden stakk folk innom hverandre for å slå av en prat. (😱) Var ikke folk hjemme, så… ja, måtte man gå slukøret hjem igjen. Da telefonen kom gikk vi over til å ringes. Ikke like forstyrrende som et besøk, men fortsatt noe som krever oppmerksomhet og tilgjengelighet fra begge parter samtidig. Men idag snakker vi nesten ikke i telefonen. Det går stort sett i asynkrone meldinger. Det er mer praktisk sånn. Vi kan sende en melding når vi har tid, så kan mottakeren svare når de har tid.

Gjenbrukbar sort ridder

I større og større grad har vi laget systemer der det at en part går ned eller er utilgjengelig på ingen måte skal affektere noen andre deler av systemet. Som den sorte ridderen til Monty Python, kjemper systemene våre videre helt uavhengig av hvor mange fungerende kroppsdeler som er igjen for å ta kampen: “’Tis but a scratch”. (Eller “Eventual Consistency” som vi sier i IT-bransjen.)

I tillegg er dette med meldingsutveksling noe vi gjør igjen og igjen og igjen og igjen. Hvorfor lage nye løsninger for dette hver gang? Hvorfor ikke lage fellestjenester som tar seg av meldinger istedenfor?

Everything is awesome!

Det finnes etterhvert mange generiske fellestjenester for meldingsutveksling som lar systemer kommunisere med hverandre helt uavhengig av om noen av partene er tilkoblet og følger med. Altinn er bare ett av mange slike system. Altinn var sentralt i feilene rundt bekymringsmeldingene til barnevernet som ikke kom frem.

Altinn sender meldinger mellom tusenvis av forskjellige systemer. Hvor mye tid går det fra en melding kommer inn til den leses? Det varierer enormt. Det er ingen feilsituasjon i Altinn at meldinger står ulest.

Det fungerer strålende helt til det ikke gjør det. Og selv da virker alt å fungere helt strålende - for det er ingen feilmeldinger noe sted:

  • Avsender har sendt melding - ingen feil her.
  • Meldingssystemet har lagret melding - alt OK.
  • Mottaker vet ikke at det er noe å se etter, så merker ikke at noe er galt.

Everything is awesome!

Bruk “telefonen” hvis det er viktig

For chatte-løsninger og mindre kritisk informasjonsutveksling er det også helt greit. Det er ikke noen krise om det morsomme katte-bildet jeg akkurat fant ikke kommer frem til mannen min øyeblikkelig. Kommunikasjon der man uansett sitter og følger med selv på om mottaker har fått beskjeden kan også helt trygt gå gjennom slike generiske mellomledd. Men er det en viktig beskjed så bruker vi fortsatt telefonen. Vi velger eksplisitt å forstyrre mottaker for å gi en viktig beskjed. Er ikke mottaker tilgjengelig, så er det viktig for oss å vite dette også, slik at vi da kan ringe noen andre eller formidle informasjonen på andre måter.

Vi som lager IT-systemer må være mer bevisste på når meldingene vi håndterer er “telefonverdige”. Hvis de er det, må vi lage systemer som ikke legger opp til å feile i stillhet. Betalingsløsninger er sånn. Vi forlater ikke kassa før transaksjonen har blitt godkjent. Det holder ikke at ett system har sendt en betalingsforespørsel. Vi venter til vi har fått en indikasjon på om betalingen går gjennom.

Manglende overvåkning?

Det er nok mange som tenker at problemet med disse to systemene i media, var at de manglet overvåkning. Hadde vi bare hatt enda mer kode på plass, som automatisk sendte alarmer tilbake til avsender dersom mottaker ikke fikk meldingen innen en konfigurerbar tid, da hadde vi ikke hatt slike problemer.

Ja, det er en løsning.

En annen løsning er å ikke ha dette problemet overhodet.

Fjerne problemet > Løse problemet

Der man har valget mellom enten å fjerne kode for å løse et problem, eller å legge til mer kode, så vil jeg på det sterkeste anbefale å velge løsningen med minst mulig kode.
Av flere grunner:

  • Jo mer kode, jo mer bugs.
  • Jo mer kode, jo flere utviklere trengs.
  • Jo mer kode, jo mer koster det.
  • Jo mer kode, jo mer kompleksitet og jo færre som forstår hvordan alt henger sammen.

Hvis du er ansvarlig for et IT-system som sender meldinger som det er helt kritisk at kommer frem så fort som mulig, så vil jeg anbefale at du sender meldingene dit de skal, heller enn å være avhengig av generisk mellomvare du så må lage masse overvåkning på toppen av.

Send meldingen dit den skal

Send meldingen dit den skal. Det er ikke verre enn det. Point to point synkron kommunikasjon. Akkurat sånn vi gjorde det i gamledager. Hvis det er et problem at mottaker-systemet går ned hele tiden, så burde man først og fremst fikse det problemet. Men hvis det av en eller annen grunn ikke lar seg gjøre er det bedre å legge retry-mekanismer hos avsender, eller kø-løsninger hos mottaker enn å la alt gå via en generisk tredjepart. Disse retry-mekanismene og mottaks-mekanismene kan implementeres med standard kodebiblioteker. Det er en tryggere måte å få til gjenbruk på. Da kan tjenestene bruke felles-kode på sin måte, og de er selv ansvarlige for å følge med på loggene og feilene som evt oppstår i bruk.

Når vi sender meldinger til systemene som er ansvarlige for å motta dem, så merker både avsender og mottaker at en meldingsutveksling har skjedd. Eller ikke. Det er bra.

Ikke si OK hvis du ikke vet

Legene i Helseplattformen fikk en “OK” melding etter å ha trykket send. Da trodde de alt var ok. De har ikke tid til å sitte og dobbeltsjekke om meldinger har blitt sendt dit de skal. De har en hektisk arbeidshverdag med massevis av pasienter. Når de sliter med å finne tid til lunsj, eller få tid til å gå på do, så kan vi ikke regne med at de sitter og følger med “har meldingen jeg sendte for 3 timer siden blitt sendt/mottatt ennå?” Da er det bedre å få en “Mottaker ikke tilgjengelig”-type feilmelding enn at systemet later som at alt er i skjønneste orden. Det er viktig for helsepersonell å vite om informasjonen har kommet frem, eller i det minste sendt til riktig sted. Hvis de vet at meldingen ikke kom frem digitalt, vil de kanskje være nødt til å ringe noen eller løpe ned i gangen for å snakke med noen. Men de gjør jo ikke det hvis IT-systemet sier “OK”.

Umulig å validere

Generiske mottakstjenester kan ikke annet enn å si “OK”. Hva ellers kan de gjøre? Hele formålet deres er å kunne si OK selv om mottaker ikke er der. Ikke kan de validere meldingene de får inn heller. Annet enn kanskje litt overfladisk syntaktisk validering. “Har avsender lov til å sende denne meldingen?” “Gir innholdet i denne meldingen mening i kontekst?” Dette kan den ikke svare på. Meldingstjenesten har hverken kontekst eller noe domene-spesifik logikk for å kunne validere om meldingen er gyldig. Det oppdages først når mottaker-systemet tar imot meldingen, men da har avsender kanskje forlatt kontoret for lengst i den tro at alt er i orden.

Jammen kan man ikke legge til domenespesifikk validering i den generiske meldingstjenesten da? Nei nei nei. Hele poenget med å ha en felles generisk meldingstjeneste er å skape løs kobling mellom mottaker og avsender. Poenget er å ha et en-til-mange-forhold. En enkel meldingstjeneste som betjener mange forskjellige systemer.
Det skalerer. Avsender og mottaker trenger bare å forholde seg til en eneste meldingstjeneste. Enkelt og greit. Det er ikke enkelt og greit om denne fellestjenesten skal vite om og aktivt bruke kompleks domenelogikk på vegne av hver eneste avsender og mottaker den hjelper. Da vokser kompleksiteten ut av kontroll og skaper veldig tette koblinger.

Ta brukerne på alvor og finn ut hvilke meldinger som må verifiseres

Altinn og generiske tjenester som mottar alt for alle kan funke fint der meldingene ikke er så kritiske eller hvis de sendes i en kontekst der avsender uansett sitter og følger med og sjekker opp om meldingen har blitt prosessert. Men er meldingen viktig nok trenger vi tryggere løsninger enn det en generisk felles asynkron meldingsløsning kan tilby.

Jeg vet ikke noe om hva rent teknisk som lå bak feilene med Helseplattformen tidligere i år, men jeg håper i alle fall at det kan bidra som en lærepenge til alle om hvor viktig det er å lage løsninger som ikke feiler i stillhet om viktige ting.

Spesielt innen helse burde vi være nøye på disse tingene. Det burde være åpenbart, men Helseplattformen er bevis på at man dessverre ikke kan ta noen ting for gitt. En melding er ikke bare en melding. Ikke for brukerne. Et prøvesvar er ikke det samme som en resept, og en sperring av innsyn i journaldokumenter er ikke det samme som en melding om at noen har byttet fastlege. Innenfor hver av disse kategoriene er det en hel haug med under-kategorier. Hver type melding og hver kategori har sine regler og det er viktig at de blir håndtert på en trygg måte i henhold til konteksten informasjonen sendes i.
Helsepersonell har mer enn nok å drive med enn å måtte sitte dobbeltsjekke alle meldinger de tror de har sendt sånn i tilfelle noe har gått galt.

“Eventual consistency” er behagelig for oss utviklere. Men det er ikke oss vi lager løsninger for. Vi må ta brukerne på alvor og lage løsninger som løser deres behov først og fremst.