
Backend izņemšana no augšupielādes ceļa
GeekBye ieraksta tavu ekrānu un saglabā video tavā Google Drive. Pirmā versija piegādāja katru ierakstu caur GeekBye paša serveriem ceļā uz turieni; vienu laidienu vēlāk fails devās tieši no tavas mašīnas uz Drive, un backend tika pazemināts līdz viena rādītāja turēšanai. Interesantākā daļa ir tas, cik maz koda 'tiešā, atsākamā' versija patiesībā satur — jo atsākamība nāca no starpniekservera dzēšanas, nevis no tā rakstīšanas.
GeekBye var ierakstīt tavu ekrānu — video, sistēmas audio un mikrofonu — un automātiski nomest pabeigto ierakstu tavā Google Drive. Starp v1.8.11 un v1.8.13 funkcijas lietotājam redzamais apraksts gandrīz nemainījās, bet ceļš, pa kuru video nokļūst līdz Drive, tika pilnībā pārmaršrutēts. Pirmajā versijā tavs ieraksts ceļoja caur GeekBye serveriem. Otrajā tas devās tieši no tavas mašīnas uz tavu Drive, un GeekBye backend nekad neredzēja nevienu tā baitu. Šī pārmaršrutēšana ir viss stāsts, un gandarījums ir tajā, ka "labākā" versija satur uzkrītoši mazāk koda nekā tā, kuru tā aizstāja.
Konveijers, no gala līdz galam
Ierakstīšana notiek renderētājā. ScreenRecordingService.ts izveido MediaRecorder pār tveršanas straumi ar { mimeType: 'video/webm;codecs=vp9,opus', videoBitsPerSecond: 1_000_000 } un palaiž to ar vienas sekundes laika nogriezni (CHUNK_INTERVAL_MS = 1000). Katrs ondataavailable blob tiek nosūtīts caur IPC uz galveno procesu, kur recording:save-chunk apstrādātājs pievieno to failam diskā ar fs.promises.appendFile. Vērts to atzīmēt jau agri, jo to ir kārdinoši nepareizi izlasīt: šī vienas sekundes kadence ir diska-ieraksta ritms, nevis augšupielādes gabala izmērs. Līdz brīdim, kad sākas augšupielāde, diskā jau atrodas viens pabeigts WebM fails.
Vienīgais, kas atšķiras starp abiem laidieniem, ir tas, kas notiek ar šo pabeigto failu.
Pirms: viss caur backend (v1.8.11)
v1.8.11 augšupielādes ceļš failā CloudUploader.processRecording() ir acīmredzamais dizains un pilnīgi saprātīga pirmā versija:
POST /api/geekbye/recordings, lai izveidotu backend ierakstu ar ieraksta metadatiem.- Ielasīt visu video atmiņā un POST to uz backend kā multipart —
const fileBuffer = fs.readFileSync(filePath)— trāpotPOST /api/geekbye/recordings/${id}/upload. Backend tad augšupielādē šo failu Drive un atgrieždriveUrl. POST …/process, lai nosūtītu transkriptu AI analīzei.
Nesošā detaļa ir 2. solis: klients ielādē visu ierakstu atmiņā, un katrs tā baits šķērso GeekBye paša serverus ceļā uz Drive. Īsam klipam tas ir labi. Garam ekrāna ierakstam tās ir trīs problēmas uzreiz — atmiņas spiediens uz klientu no readFileSync, joslas platuma un retranslācijas izmaksas backend pusē failam, ko tas pat nepatur, un viens monolīts POST, kam jāstartē no nulles, ja tīkls uz pusceļa nostrādā.
Ir arī vērts būt godīgam, ka šis "pirms" nebija kāds neskarts oriģināldizains. v1.8.11 funkcija saspieda kopā vienas nedēļas ietvaros notikušu pagriezienu: agrīnā versija augšupielādēja uz Cloudflare R2 caur iepriekš parakstītiem URL un pārveidoja WebM par MP4 ar iepakotu ffmpeg-static; to aizstāja ar backend-starpniecības Drive plūsmu; un tad ffmpeg konversija tika pilnībā izrauta par labu WebM augšupielādei tāda, kāda tā ir (komits atzīmē, ka tas pazemināja bitu ātrumu un radīja aptuveni četras reizes mazākus failus — iekļauts novērtējums, nevis etalonmērījums). Tātad pat "pirms" jau bija iemācījies izdzēst native atkarību vienreiz. Nākamais laidiens izdzēstu arī starpniekserveri.
Pēc: tieši uz Drive (v1.8.13)
v1.8.13 pārraksta CloudUploader.processRecording() ap vienu teikumu no komita, kas to piegādāja: augšupielādēt tieši uz Drive, "keeping backend for metadata record + AI transcript analysis only." Jaunais ceļš:
POST /api/geekbye/recordings— tikai metadati (nosaukums, ilgums, faila izmērs,format: 'webm'). Komentārs kodā ir tiešs:// Create backend record (metadata only — no file upload).- Augšupielādēt video tieši uz Google Drive, pilnībā apejot backend starpnieku.
PATCH /api/geekbye/recordings/${backendRecordingId}ar iegūto{ driveUrl, driveFolderId }— backend ierakstam tiek paziņots, kur fails nonāca.- Transkripts joprojām dodas uz
…/processanalīzei.
Backend no atrašanās failā ceļā kļuva par to, kam paziņo par failu pēc fakta. Tas tur rindu un rādītāju; baiti dzīvo tikai lietotāja diskā un lietotāja Drive.
Kļūšana par īstu Drive klientu
Lai klients varētu tieši sarunāties ar Drive, tam jābūt īstam Google Drive API klientam, un v1.8.13 pievieno tam mehānismu: jaunu DriveService (Drive klients), jaunu DriveAuthRepository, ko atbalsta jauna drive_auth SQLite tabula, un googleapis SDK kā atkarību.
Autorizācija ir tīra spēju nodošana. Backend lietotnes konfigurācijas galapunkts retranslē Google OAuth klienta akreditācijas datus — clientId un clientSecret — lejup uz lietotni, kurus CloudUploader nolasa un nodod driveService.initialize(...). No turienes darbvirsmas lietotne pati palaiž visu OAuth plūsmu: tā izveido pagaidu http serveri uz nejauša 127.0.0.1 porta, atver piekrišanas ekrānu sistēmas pārlūkā ar shell.openExternal, noķer novirzīšanu uz /callback un apmaina kodu pret marķieriem ar google-auth-library. Šie marķieri tiek saglabāti lokāli — saveDriveAuth(access_token, refresh_token, expiry_date) tabulā drive_auth — ar drive.file tvērumu, kas ļauj lietotnei pārvaldīt tikai tos failus, ko tā izveido. Atjaunošana arī ir lokāla: oauth2Client.on('tokens', …) klausītājs raksta atjaunotos marķierus tieši atpakaļ tabulā. Backend nodod spēju vienreiz un tad paliek ārpus cilpas.
"Atsākamā" daļa, godīgi
Lūk detaļa, par kuru es visvairāk gribu būt tiešs, jo tā ir tieši tāda lieta, ko izmaiņu žurnāls noapaļo. Laidiena piezīme saka "resumable uploads", un no lietotāja skatpunkta tas ir taisnība. Bet GeekBye neieviesa atsākamo protokolu. Nekur GeekBye pirmkodā nav gabala izmēra konstantes, baitu nobīdes sekotāja vai Content-Range / 308 Resume Incomplete apstrādes. Grep tos un tu nedabūsi neko — tie dzīvo googleapis SDK iekšienē.
Tas, ko dara GeekBye paša kods, ir šis:
const fileStats = statSync(videoFilePath)
const videoStream = createReadStream(videoFilePath)
const videoRes = await this.drive.files.create(
{
requestBody: { name: `${title}.webm`, parents: [folderId] },
media: { mimeType: 'video/webm', body: videoStream },
fields: 'id',
},
{
onUploadProgress: (evt) => {
const percent = Math.round((evt.bytesRead / fileStats.size) * 100)
onProgress(percent)
},
},
)
Divas izvēles paveic visu darbu. Pirmkārt, media.body ir straume (createReadStream), nevis buferis — un straumes nodošana ir tieši tas, kas liek googleapis tavā vārdā risināt atsākamu sesiju, nevis darīt vienā piegājienā. Otrkārt, progress tiek nolasīts no SDK onUploadProgress atgriezeniskā izsaukuma pret fileStats.size. Tā ir visa "atsākamās augšupielādes" implementācija lietotnes līmenī: straume iekšā, progress ārā. Grūto protokolu — atvērt sesiju, augšupielādēt gabalos, atsākt no nobīdes pēc pārtraukuma — dara SDK, un pareizais inženierijas lēmums bija ļaut tam darīt šo darbu, nevis izgudrot to no jauna.
Kas pārkadrē visu laidienu. Uzticamības uzlabojums nenāca no augšupielādes dzinēja rakstīšanas. Tas nāca no starpniekservera dzēšanas, kas atradās tā priekšā — un, agrāk tajā pašā nedēļā, no ffmpeg soļa dzēšanas tā priekšā. Mazāk koda, vairāk noturības, jo noturīgā lieta bija labi novalkāta bibliotēka brīdī, kad tu pārstāji to barot ar buferi no rokas.
Daļas, kas patiesi ir GeekBye
Pārsūtīšanas nodošana SDK nenozīmē, ka nekas nepalika ko būvēt. Divas īstas lietotnes loģikas daļas to ietver.
Bāreņu-mapes atritināšana. Katrs ieraksts iegūst savu Drive apakšmapi (izveidotu ar mimeType: 'application/vnd.google-apps.folder'), un transkripts nolaižas tur kā otrs fails blakus video. Ja augšupielāde met kļūdu, catch izdzēš šo mapi — this.drive.files.delete({ fileId: folderId }), reģistrēts kā Rolled back orphaned Drive folder — tā ka neveiksmīga augšupielāde neatstāj tukšu mapju pēdas tavā Drive. Konteinera izveide pirms tu zini, ka operācija izdosies, ir neliela saistība; neveiksmes ceļa likšana to sakopt ir labojums.
Dzīves cikls ap singltonu. DriveService ir singltons, kas tur atmiņā esošu OAuth klientu, un šis atmiņā esošais klients nepārdzīvo lietotnes restartu, kaut arī marķieri to dara (tie ir datubāzē). Tāpēc CloudUploader no jauna inicializē DriveService no saglabātajiem marķieriem pirms katras augšupielādes, kas nozīmē, ka ieraksts, kas veikts tūlīt pēc atkārtotas palaišanas, joprojām augšupielādējas, neprasot tev atkārtoti savienoties. Un pārskatīšanas piegājiens padarīja drive-connect apstrādātāju par "palaid-un-aizmirsti", jo bloķējošs savienošanās izsaukums apstādināja renderētāja statusa aptauju — UI nevarēja parādīt "savienojas…", ja savienošanās izsaukums turēja pavedienu. Šie divi — atkārtota inicializācija no krātuves un nebloķējoša savienošana — ir tiešā ceļa īstie robežgadījumi, un, ievērojami, neviens no tiem nav par augšupielādes sadalīšanu gabalos. Kad tu deleģē grūto daļu, kļūdas, kas paliek, ir dzīves cikla kļūdas.
Trīs lietas, ko šis laidiens mums iemācīja
- Jautā, kur plūst baiti, nevis tikai vai tas strādā. v1.8.11 starpniekserveris strādāja. Bet katra ieraksta maršrutēšana caur taviem paša serveriem maksā tev joslas platumu, atmiņu un atsākamību failam, ko tu nepatur. Datu ceļa pārzīmēšana tā, lai klients sarunājas tieši ar galamērķi, bieži ir visa optimizācija.
- Labākā atsākamā augšupielāde ir tā, ko tu neuzrakstīji. Straumes nodošana nobriedušam SDK nopirka pilnu atsākamu sesiju par divām koda rindiņām. Instinkts pašrocīgi rakstīt gabalu sadalīšanu un nobīžu matemātiku būtu radījis vairāk koda un mazāk uzticamības.
- Kad tu deleģē kodolu, tu manto dzīves ciklu, nevis algoritmus. Tiešā klienta īstās kļūdas bija "no jauna inicializē singltonu pēc restarta" un "nebloķē savienošanās izsaukumu", nevis baitu nobīdes. Tā ir laba maiņa — dzīves cikla kļūdas ir redzamas un lokālas; protokola kļūdas nav ne viena, ne otra.
Iepriekšējai nodaļai v1 stāstā — dzimis un izlabots divpadsmit minūtēs (v1.8.10); un visai lokai — programmatūras piegādes līdz pilnībai anatomiju.