Steven
Steven5 min lugemist

Turvakontroll, mis muutis meie rakenduse võimatuks sulgeda

Automaatne uuendus oli raskeim funktsioon, mille oleme kunagi välja lasknud — kuus väljalaset nelja päevaga, et takistada sel rakendust nurjata. Halvim viga oli see, mille tõime sisse ettevaatlikkusest: 500-millisekundiline "turva"-kontroll, mis muutis ebaõnnestunud uuenduse protsessiks, mida sa sõna otseses mõttes ei saanud sulgeda.

Inseneeria
Electron
Töökindlus
GeekBye väljalasked
Turvakontroll, mis muutis meie rakenduse võimatuks sulgeda

Iga töölauarakenduse arendaja alahindab automaatset uuendust täpselt üks kord. See tundub lahendatud probleemina — teek laadib alla uue versiooni ja taaskäivitab su rakenduse. Siis lased selle välja ja saad teada, et "taaskäivita oma rakendus" on üks ohtlikumaid asju, mida programmilt saab paluda, sest see juhtub täpselt hetkel, mil su rakendus lammutab iseennast ja tal on kõige väiksem veamarginaal.

GeekBye automaatne uuendus vajas stabiliseerumiseks kuut väljalaset nelja päevaga — v1.5.14 kuni v1.5.19. See on lugu selle lõigu halvimast veast, mille põhjustasime ise, üritades olla ettevaatlikud.

Kuus väljalaset ja see üks, millel oli tähtsust

Kaar algas argiselt. v1.5.14 parandas piinliku trükiviga-tüüpi vea: uuendusvoog osutas GitHubi repositooriumi nimele, mida polnud olemas, nii et uuendaja kontrollis 404-t. v1.5.15 lisas käsitsi nupu "Check for Updates" ja päris veateate. Siis algasid quitAndInstalli vead ja väljalasked tulid kiiresti — sest kui su uuendusmehhanism on katki, ei saa sa selle parandust välja lasta läbi uuendusmehhanismi. Iga iteratsioon on käsitsi taasinstallimise hasartmäng.

See, millel on tähtsust, on v1.5.18. Selle kogu sisu oli üks commit pealkirjaga, mille peale ma siiani võpatan: restore original quitAndInstall behavior to prevent unkillable app.

Kuidas "ettevaatlik olemine" rakenduse nurjas

Siin on olukord. Kui uuendus on alla laaditud, peaks Electroni quitAndInstall sulgema rakenduse ja vahetama sisse uue versiooni. Ühes varasemas väljalaskes muretses keegi — põhjendatult —, et tingimusteta sulgemine on riskantne. Mis siis, kui installimine annab vea? Kas poleks turvalisem sulgeda ainult siis, kui kõik näeb terve välja?

Nii kasvatas kood vahi, mis nägi mõistlik välja:

autoUpdater.quitAndInstall(false, true)
setTimeout(() => {
  if (this.updateDownloaded)
    app.quit() // only quit if the update is still "good"
  else console.log('Error detected — keeping app open')
}, 500)

Loogika: käivita installimine, oota pool sekundit ja sunni lõplik app.quit() välja ainult siis, kui lipp updateDownloaded on endiselt tõene — muidu hoia rakendus avatuna, et kasutaja ei jääks hätta.

Lõks on ühe rea kaugusel, veakäsitlejas. See käsitleja seadis this.updateDownloaded = false. Nii et kujuta ette ebaõnnestunud installimist: sündmus error vallandub ja tühjendab lipu. Kuid quitAndInstall oli juba alustanud lammutamist — see oli sulgenud aknad ja eemaldanud rakenduse sulgemiskuulajad. Siis ärkab 500 ms taimer, kontrollib nüüd vale lippu, otsustab "viga tuvastatud, hoia rakendus avatuna" ja jätab app.quit() vahele.

Nüüd on sul, just nimelt macOS-is, halvim võimalik olek. macOS ei sulge rakendust ainult sellepärast, et selle viimane aken sulgus — see on window-all-closed käitumine, millele iga Maci rakendus toetub. Nii et protsess on endiselt elus, kuid sellel pole akent, pole menüüriba teed ja selle sulgemiskuulajad on välja rebitud. Pole midagi, millele klõpsata. Cmd-Q-l pole millegagi rääkida. Ainus väljapääs on Force Quit Activity Monitorist. "Turva"-kontroll oli muutnud ebaõnnestunud uuenduse — taastatava tüli — zombiks, keda sa ei saanud tappa.

Parandus: lammutamine peab olema tingimusteta

Parandus v1.5.18-s on peaaegu agressiivselt igav, ja see ongi mõte. See eemaldab nutikuse:

  1. Eemalda window-all-closed ja before-quit kuulajad, mis võiksid segada.
  2. Hävita iga aken — window.destroy(), mitte window.close(). Sulgemist saab käsitleja vetostada; hävitamist ei saa. Kui sa pühendud väljalülitumisele, ei küsi sa viisakalt.
  3. Kutsu quitAndInstall.
  4. Kutsu app.quit() tingimusteta.

Ei mingit lippu, ei mingit taimerit, ei mingit "hoia see avatuna igaks juhuks". Sest tõde väljalülitumise tee kohta on see, et poolik väljalülitumine on halvem kui kumbki tulemus. Täielik sulgemine on korras. Täielikult avatuks jäämine on korras. Ainus olek, milleni sa ei tohi kunagi jõuda, on lammutatud, kuid endiselt töötav — ja täpselt sellesse olekusse võib sind tingimuslik sulgemine kinni jätta.

Veel kaks õppetundi, mille sama nädal andis

Suletamatu viga on pealkiri, kuid kuue väljalaske rabelemine karastas kaks muud harjumust, mida tasub varastada.

Filtreeri oma krahhitelemeetriat täpsete allkirjade, mitte laiade märksõnade järgi. Rabelemise keskel avastasime, et meie veateavitus oli seadistatud kõrvale heitma kõike, mis sisaldas sõnu nagu permission, token või microphone — katse müra vähendada, mis vaikselt neelas tõelisi krahhe, mis juhtusid neid sõnu mainima. Rebisime laiad filtrid välja ja asendasime need täpsete keeldumisstringidega (konkreetne teade, mille macOS väljastab, kui luba tagasi lükatakse) ja konkreetsete ajutiste võrgukoodidega nagu ERR_NETWORK_CHANGED. Müra vähendamine ja vigade peitmine on sama nupp, keeratud vastupidistesse suundadesse; kui sa filtreerid tunde järgi, filtreerid välja just selle, mida sul oli vaja näha.

Iga automaatne tee vajab käsitsi pääseteed. Automaatne uuendus on oma olemuselt parimale-pingutusele suunatud — võrgud tõrguvad, installimised ebaõnnestuvad. Nii sai iga tõrkerežiim inimliku varuvariandi: käsitsi nupu "Check for Updates", eksponentsiaalse tagasilibisemisega kordused, taaskontrolli taimeri ja — reserveeritud just juhtumiks, kui kasutaja käsitsi katse ebaõnnestus — lihtsas keeles teate "kustuta rakendus ja installi uuesti veebisaidilt". Automaatne tee on mugavus; käsitsi tee on garantii.

Peamine mõte

  1. Vaht pöördumatu toimingu ümber on ohtlikum kui toiming ise. Tingimuslik sulgemine üritas takistada halval uuendusel rakendust sulgeda ja tekitas selle asemel oleku, mis on halvem kui sulgemine või mittesulgemine. Väljalülitumise ja installimise teed peaksid olema tingimusteta ja idempotentsed — mitte kunagi seotud muudetava lipuga, mille teine käsitleja saab su alt välja lüüa.
  2. macOS-is "pole aknaid" ei ole "pole rakendust". Iga lammutusloogika peab arvestama platvormiga, kus aknata protsess töötab edasi. Testi tõrketeed päris operatsioonisüsteemis, mitte ainult õnnelikku teed.
  3. Funktsiooni, mille lased välja läbi uuendussüsteemi, ei saa testida läbi uuendussüsteemi. See asümmeetria on põhjus, miks automaatne uuendus väärib paranoilist, tingimusteta, tugevalt käsitsi kontrollitud koodi. Sa saad selle lihtsat teed pidi parandada alles pärast seda, kui see juba töötab.

See on töökindluse töö varaseim peatükk, millest lõpuks sai GeekBye v2. Selle kohta, kuhu see tee viis, vaata mida versioon 2 tegelikult nõuab (v2.0.0) ja kogu kaart artiklis tarkvara täiuseni väljalaskmise anatoomia.

Seotud artiklid

Katkenud ühendus ei tohiks kogu rakendust maha võtta — aga meie oma tegi seda
Steven
Steven5 min lugemist

Katkenud ühendus ei tohiks kogu rakendust maha võtta — aga meie oma tegi seda

Kui meie backend kadus keset koosolekut võrgust, ei pannud see lihtsalt transkriptsiooni pausile — see pani kogu rakenduse kokku jooksma. Põhjuseks oli üksainus käsitlemata sündmus ja parandus oli kümme rida. See on väljalasete kobar, mis pani GeekBye sisselogituna ja ühendatuna püsima läbi asjade, mis teda varem tapsid.

Inseneeria
Töökindlus
Electron
Vaikus oli kandev
Steven
Steven6 min lugemist

Vaikus oli kandev

Kaks viimast GeekBye v1 väljalaset räägivad samast ebamugavast tõest: reaalajas transkriptsioon üle päris võrgu ei ole kadudeta, ja aus samm on lõpetada teesklemine, et see on. v1.8.20 hoidis igast helitükist koopia kettal, enne kui selle taasühenduse ajal maha viskas, ja hakkas transkriptsiooni tühikuid valjult märkima. v1.9.0 lõpetas vaikuse saatmise ribalaiuse säästmiseks — ja avastas, et vaikus oli täpselt see signaal, mida transkribeerija kasutas, et teada, millal lause oli lõppenud. Kaks väljalaset asjade äraviskamise hinnast.

Arendus
Audio
Töökindlus
Koosoleku printimine PDF-i ilma PDF-teegita
Steven
Steven7 min lugemist

Koosoleku printimine PDF-i ilma PDF-teegita

GeekBye ekspordib koosoleku PDF-ina, ja koodis pole kusagil PDF-teeki. See renderdab HTML-i nähtamatus brauseriaknas ja prindib selle. See valik on kogu lugu: see tegi funktsiooni lihtsaks ehitada ja andis sellele iga tõrke, mis päris brauseril on — valge välgatuse, URL-i pikkuse piirangu ja leheküljemurru, mis lõikas ekraanipildid pooleks. Kõige inetuma vea parandus oli üks rida CSS-i.

Arendus
Electron
Desktop