Infrastruttura · media

keepix.cloud — un host multimediale che restituisce indirizzi finiti

Un servizio multimediale per app, negozi e marketplace: una richiesta firmata in — varianti WebP e una scala HLS in uscita, servita dal sottodominio del cliente con una cache permanente. Multi-tenant, fatturazione misurata fino a centesimi, EXIF rimosso all'ingresso, e un endpoint di cancellazione per persona che risponde con un numero. Abbiamo progettato e costruito tutto, dal pipeline di ingresso al dashboard.

Categoria
Infrastruttura · media
Costo stimato
a partire da €24.000
Cronologia
≈ 10–14 settimane
keepix.cloud
keepix
Homepage del progetto — keepix.cloud

01Panoramica del progetto

keepix.cloud è un host multimediale per prodotti che devono servire i file di altre persone: foto del catalogo in un negozio, immagini di recensioni in un marketplace, video di walkthrough in un'app. Inviate l'originale in una richiesta firmata, e la risposta porta già gli indirizzi finiti — un insieme nominato di varianti WebP per un'immagine, una scala HLS per un video. I file vengono serviti dal sottodominio del cliente, quindi il lettore vede il proprio marchio e non vede mai noi.

Il presupposto è che i media non siano una funzionalità che si costruisce una volta per progetto. Ogni prodotto che consente alle persone di caricare qualcosa finisce per scrivere la stessa cosa di nuovo: ridimensionamento, conversione di formato, uno schema di denominazione, una politica di cache, rimozione dei metadati, un percorso per eliminare tutto su questa persona. Scritto una quinta volta, viene scritto male una quinta volta — e le parti che vanno male (un tag GPS trapelato, un SVG che si è rivelato essere uno script) falliscono silenziosamente, senza un errore e senza una riga di log.

Quindi abbiamo costruito il servizio attorno a un'idea: l'indirizzo è dichiarato dal servizio e memorizzato dal cliente, mai calcolato dal lato del cliente. Questa singola decisione rimuove il modo più comune in cui le integrazioni multimediali si rompono — una pagina che si rende perfettamente con un buco dove dovrebbe esserci la foto del prodotto.

Abbiamo progettato e costruito l'intero prodotto: il pipeline di assunzione, il modello di varianti, la scala video, il modello multi-tenant con i propri domini e chiavi di firma, la fatturazione misurata, il dashboard, il contratto API pubblico e la documentazione. Di seguito è riportato quale problema risolve, come è assemblato e quali decisioni ingegneristiche prenderemmo allo stesso modo di nuovo.

02Contesto e problema

Memorizzare un'immagine caricata è facile. Gestire un percorso multimediale che rimane corretto per anni, sotto carico, attraverso diversi prodotti e i file di altre persone, non lo è. Quando abbiamo analizzato il compito, le insidie sono emerse rapidamente.

  • Larghezze arbitrarie sono una trappola.Un URL come ?w=473 sembra flessibile ed è in realtà due problemi contemporaneamente: una cache che non si riscalda mai, perché ogni pagina richiede un numero leggermente diverso, e un modo gratuito per chiunque di occupare il processore chiedendo mille larghezze di seguito.
  • Un indirizzo calcolato si rompe silenziosamente.La regola "id → shard → path", integrata nel codice del client, sopravvive esattamente fino al primo cambiamento di layout dall'altra parte. Poi la pagina continua a essere visualizzata e il prodotto ha semplicemente un buco dove c'era la sua foto — nessun errore, nulla nel log.
  • I metadati sono una fuga che nessuno nota.Le coordinate GPS della casa di qualcuno presenti nell'EXIF di una foto di recensione non sollevano errori, non rompono pagine e non raggiungono alcun monitoraggio. È solo una fuga quando qualcuno guarda.
  • SVG non è un'immagine.È un markup eseguibile. Accettato come un'immagine e servito dal dominio del client, uno script al suo interno viene eseguito per conto di quel dominio.
  • La cancellazione deve essere dimostrabile.Una richiesta di cancellazione GDPR a cui si risponde contrassegnando le righe come eliminate mentre i byte rimangono su disco è una cancellazione che non è avvenuta.
  • Il video è un insieme, non un file.Un caricamento deve diventare una scala riproducibile, un fotogramma di poster e un fallback — e nulla di tutto ciò può avvenire all'interno della richiesta che ha accettato il file.
  • La fatturazione deve essere onesta per numeri piccoli.Un gigabyte può costare meno di un centesimo; arrotondare a centesimi interi consuma l'intera bolletta misurata e rende la fattura una finzione.

C'era un ulteriore requisito, e ha plasmato l'intero design: il servizio non deve uscire affatto su internet. Un host multimediale che recupera un'immagine da un indirizzo di terze parti per conto del cliente sa chi ha chiesto cosa e trasferisce quella conoscenza a qualunque CDN abbia utilizzato. keepix non conosce alcun indirizzo di terze parti, e questa è una proprietà del codice, non una promessa sulla pagina dei prezzi.

03Obiettivi del progetto

Il compito si è trasformato in un elenco di obiettivi a cui ci siamo aggrappati in ogni fase:

  • Una richiesta in, indirizzi finiti fuori.Il cliente invia l'originale e riceve immediatamente gli indirizzi da memorizzare — nessuna seconda chiamata, nessuna attesa per il completamento di un lavoro per le immagini.
  • Un insieme nominato e finito di varianti.Tre larghezze per le immagini e quattro forme per i video, dichiarate per tipo di file, in modo che la cache sia calda e il processore non sia in affitto.
  • Il dominio del cliente. File serviti da img.theirdomain, con il servizio invisibile nella barra degli indirizzi.
  • Una cache che può essere mantenuta per sempre. L'indirizzo porta un hash del contenuto, quindi sostituire un file cambia il suo indirizzo e raggiunge immediatamente il lettore.
  • Sicurezza integrata nel percorso. Tipo determinato dall'analisi, una scansione antivirus che rifiuta piuttosto che lasciare passare, ricodifica su ogni immagine, metadati rimossi, SVG rifiutato su entrambi i lati.
  • Cancellazione dimostrabile. Una richiesta dal dominio del cliente owner_ref, e una risposta che indica quanti oggetti e file sono andati.
  • Multi-tenancy con vera isolamento.Domini propri, tipi e varianti propri, limiti propri, due chiavi di firma in modo che la rotazione non comporti inattività.
  • Fatturazione misurata che puoi controllare.Storage come una media piuttosto che un picco, traffico come i byte effettivamente consegnati, operazioni contate una per una — suddivise per giorno nel dashboard.
  • Un'API che ammette cosa ha fatto.Ogni risposta dice cosa è stato creato e cosa è stato saltato, e c'è un endpoint di riconciliazione secca per controllare una migrazione in batch.

04Cosa abbiamo fatto

keepix si suddivide in alcuni pezzi chiari, ognuno con un compito:

  • Ricezione.Un endpoint firmato accetta l'originale con il suo tipo, la sua chiave e l'elenco delle varianti desiderate. Le immagini tornano pronte nella stessa risposta; i video vanno in coda e la risposta lo indica.
  • Il pipeline di elaborazione.Rilevamento del tipo, scansione dei virus, ricodifica, rimozione dei metadati, costruzione delle varianti — in un ordine fisso che non può essere saltato per richiesta.
  • Consegna.Un host separato senza sessioni, senza JavaScript e senza Set-Cookie, che serve file direttamente dal disco con una cache immutabile di un anno.
  • L'API del tenant.Firmata con HMAC-SHA256, con endpoint per risolvere indirizzi, riconciliare in batch, esportare un inventario, eliminare un oggetto e cancellare tutto ciò che appartiene a una persona.
  • Il cruscotto.Cartelle, trascina e rilascia, ricerca per titolo, descrizione e tag — e utilizzo suddiviso per giorno. Funziona completamente senza JavaScript; lo script aggiunge comodità, non la capacità di lavorare.
  • Fatturazione.Pacchetti più sovraccarico misurato, mantenuto in centesimi, con l'assunzione che si fermi piuttosto che spendere silenziosamente soldi sul piano gratuito.
  • Il magazzino.Uno strato di mercato dove gli inquilini possono comprare e vendere il proprio lavoro, condividendo lo stesso percorso di archiviazione e consegna.

Tutto ciò che segue è uno sguardo più da vicino alle decisioni all'interno di quei pezzi — quelli che sarebbero costosi da cambiare in seguito.

05Architettura della soluzione

Il servizio è tre spazi con punti di ingresso fisicamente separati, e quella separazione è la spina dorsale dell'intero design:

  • Consegna pubblica — nessuna API. Il server web cerca il file su disco e lo serve. Non trovato significa 404, non "generarlo al volo". Non c'è codice eseguibile su quel percorso, motivo per cui l'host di consegna può portare default-src 'none'; sandbox e intenderlo.
  • L'API privata del locatario. Ogni richiesta firmata; la firma copre il metodo, il percorso con la sua stringa di query, il timestamp e un hash del corpo. Firmare il percorso senza la query lascerebbe tipo e chiave non firmato — scambiabile, e nessuno se ne accorgerebbe.
  • L'API admin per il pannello di controllo, con un proprio punto di accesso e le proprie credenziali.

Le risposte sono sempre in JSON e sempre in inglese, con una formulazione per codice di rifiuto — quindi lo stesso errore viene registrato allo stesso modo nei log di ogni cliente, qualunque lingua parli il loro prodotto.

All'interno, lo storage si divide in un albero freddo che contiene gli originali, che non viene mai servito all'esterno, e l'albero servito delle varianti. Mantenere l'originale è ciò che rende possibile una nuova variante un anno dopo senza chiedere al cliente di caricare nuovamente nulla — ed è anche il motivo per cui "non serviamo il file che hai inviato" può essere una regola assoluta piuttosto che una consuetudine.

06La vita di un file

Un file passa attraverso una sequenza fissa, e l'ordine è il punto:

  • Il tipo è determinato dal parsing — dal contenuto, non dall'estensione e non da ciò che il client dice che sia. L'estensione del file di output è compito del servizio assegnarla.
  • La scansione dei virus viene eseguita e può rifiutare. Se lo scanner non è raggiungibile, l'assunzione risponde 503 invece di far passare il file. Far passare un file silenziosamente mentre il controllo è inattivo è una menzogna sul lavoro svolto, ed è il tipo di menzogna che riemerge solo molto dopo.
  • L'immagine viene ri-encodificata. Non un byte del file che è arrivato viene mai restituito.
  • I metadati non sopravvivono alla ri-encodifica. EXIF e GPS sono scomparsi a causa di come è costruito il percorso, non perché chi ha caricato si sia ricordato di rimuoverli.
  • Le varianti sono costruite e i loro indirizzi vengono restituiti nella stessa risposta.

SVG non è né accettato né servito — mai, in entrata o in uscita. Il controllo viene eseguito due volte, sul tipo di contenuto dichiarato e sui primi byte del file, perché per SVG un tipo sniffer dirà spesso solo "text". Ciò che viene servito è WebP, JPEG, PNG, MP4, una playlist HLS e i suoi segmenti; tutto il resto è un 415.

L'assunzione è idempotente: lo stesso sha256 sotto la stessa chiave non ripete il lavoro e restituisce gli stessi indirizzi. I tentativi dopo una connessione interrotta sono quindi gratuiti, il che è importante quando il file è di due gigabyte e la rete è un telefono.

07Varianti nominate, non larghezze arbitrarie

Le immagini hanno tre larghezze nominate — thumb 400, card 1000, full 1400, tutte WebP con qualità 82 — e richiedi una variante per nome. Il set è finito e dichiarato per tipo di file. Questa è la decisione su cui si basa l'intero servizio, e rimuove una classe di problemi piuttosto che un bug.

Due regole governano quando una variante può legittimamente non apparire, e entrambe esistono per evitare di mentire al lettore:

  • Niente è allungato. Se l'originale è più stretto della larghezza della variante, la variante rimane alla dimensione dell'originale e la risposta lo dice onestamente — i w e h campi portano i numeri reali. Una copia ingrandita sembra un errore del servizio, e lo sarebbe.
  • Le copie identiche non vengono memorizzate due volte.Se due larghezze producono esattamente lo stesso file, il secondo indirizzo non viene creato. Due file identici in byte a due indirizzi sono due download della stessa cosa sul telefono di qualcuno.

Il che significa che la risposta deve essere letta, non assunta: puoi richiedere due varianti e riceverne una, con un saltato blocco che spiega il perché. Abbiamo reso questa una risposta normale e attesa piuttosto che un caso limite, perché un'integrazione scritta contro la forma ottimistica si interrompe al primo piccolo immagine che un utente carica.

Aggiungere una nuova variante in seguito non richiede il ricaricamento di nulla: viene costruita dall'originale nell'albero freddo. Questa è l'intera ragione per cui l'originale viene mantenuto.

08Video: una scala HLS, un poster e un'anteprima

Un caricamento video diventa un set, perché è ciò di cui un giocatore ha realmente bisogno: un HLS ladder di fino a tre livelli di qualità (640, 1280 e 1920 px), un poster inquadratura presa al 10% della durata, un preview silenziosa dei primi secondi per l'autoplay al passaggio del mouse e nel feed, e un MP4 come fallback per i client più vecchi.

Un passo più ampio dell'originale non viene realizzato, per lo stesso motivo per cui un'immagine allungata non lo è: una copia ingrandita sembra un errore del servizio. Il poster è preso a un decimo della durata piuttosto che al primo fotogramma, perché il primo fotogramma di un vero video è molto spesso nero.

L'elaborazione video non avviene all'interno della richiesta che ha accettato il file — va in una coda, e la risposta lo indica. La risposta di ricezione è onesta riguardo a quali parti sono pronte ora e quali sono in attesa, in modo che un cliente possa memorizzare ciò che ha e chiedere di nuovo più tardi piuttosto che bloccare lo schermo di caricamento di un utente su una transcodifica.

09Il tuo dominio e una cache per sempre

I file vengono serviti dal sottodominio del locatario — img.theirdomain — a cui il locatario punta il servizio con un record A. Il lettore vede il proprio marchio e il proprio indirizzo, e non vede affatto keepix. Nel piano gratuito il dominio è condiviso; entrambi i percorsi funzionano allo stesso modo.

Un locatario può collegare quanti più domini desidera ma esattamente uno canonico uno, e quella restrizione è deliberata: con due domini canonici un file ottiene due indirizzi, il che significa due cache e gli stessi byte scaricati due volte sul telefono dello stesso lettore.

Le intestazioni di consegna sono le stesse per ogni locatario e non cambiano: un anno intero immutabile cache, nosniff, default-src 'none'; sandbox, una politica CORS permissiva per la lettura, e non un singolo Set-Cookie. La cache per sempre è sicura proprio perché l'indirizzo porta un hash del contenuto: cambia i byte e l'indirizzo cambia con essi, quindi un'immagine sostituita raggiunge immediatamente il lettore invece di aspettare un TTL.

E questo è esattamente il motivo per cui l'indirizzo non può essere calcolato dal lato del client. Viene restituito dal servizio, memorizzato accanto al record a cui appartiene, e richiesto di nuovo tramite risolvi se viene mai perso.

10Accettazione: tipo, scansione virus, metadati

Tutto nel servizio è un file che qualcuno ha inviato — una foto in una recensione, un video di walkthrough. Le regole di assunzione sono scritte per il loro bene piuttosto che per forma, e ognuna di esse esiste perché l'alternativa fallisce silenziosamente.

Determinare il tipo analizzando piuttosto che per estensione non è pedanteria: l'estensione è l'unica cosa che un uploader controlla completamente.Rifiutare quando lo scanner è inattivo costa disponibilità e compra la garanzia che "scansionato" significa scansionato.Re-encoding ogni immagine significa che un file elaborato non raggiunge mai un lettore nella sua forma originale.Rimuovere i metadati durante quella nuova codifica significa che non può essere dimenticato.

Dal lato della consegna, le garanzie sono strutturali piuttosto che procedurali. L'host di consegna non ha sessioni, nessun JavaScript e nessun codice eseguibile nel percorso; il contenuto viene inviato con una politica di sicurezza dei contenuti che impedirebbe a un browser di eseguire qualsiasi cosa anche se qualcosa di pericoloso fosse entrato. Due strati indipendenti, perché i fallimenti interessanti sono quelli in cui il primo strato era mal configurato e nessuno se ne è accorto.

Il registro di consegna, con gli indirizzi dei lettori, vive 24 ore. Niente nel servizio ne ha bisogno per più tempo, il che rende il mantenerlo più a lungo una semplice accumulazione delle tracce di altre persone.

11Cancellare tutto su una persona

Ogni oggetto porta un owner_ref — qualunque cosa chiami l'inquilino il proprietario di quel file. Per le immagini del catalogo è vuoto: non riguardano una persona. Per le foto di recensioni e i video degli utenti è richiesto.

Una richiesta cancella tutto ciò che è sotto di essa, e la risposta nomina un numero: quanti oggetti e quanti file sono andati. Quel numero è il punto dell'endpoint. Un gate per i dati personali dovrebbe controllare l'esecuzione, non l'intento — una riga contrassegnata come eliminata mentre i byte giacciono ancora su disco è un'eliminazione che non è avvenuta, e continuerà a non avvenire finché qualcuno non guarda.

L'eliminazione rimuove record e byte contemporaneamente piuttosto che secondo un programma, e porta con sé le copie differite delle versioni precedenti. È anche il pezzo che rende keepix utilizzabile da un prodotto con le proprie obbligazioni GDPR: un flusso di eliminazione nel codice del cliente può chiamarlo inline e leggere il conteggio, invece di fidarsi che un lavoro di pulizia da qualche parte ci arriverà.

Le chiavi di firma funzionano allo stesso modo.Un inquilino ha sempre due in uso, perché con una chiave la rotazione significa inattività — e l'inattività è il motivo per cui la rotazione viene rimandata all'infinito. Il segreto viene mostrato una sola volta al momento dell'emissione e non viene mai restituito al pannello di controllo: essere in grado di firmare una richiesta è il diritto di scrivere nello spazio di archiviazione di qualcun altro.

12Un'API firmata e riconciliazione

Ogni richiesta privata porta quattro intestazioni — inquilino, id chiave, timestamp e firma — e la firma è HMAC-SHA256 sul metodo, il percorso completo con query, il timestamp e l'hash del corpo. La finestra è di 300 secondi. Una richiesta firmata identica ripetuta entro la stessa seconda viene rifiutata come un replay, il che è la protezione che funziona come previsto, e il contratto lo afferma chiaramente invece di lasciare agli integratori il compito di scoprirlo.

L'insieme di endpoint è ridotto e ognuno risponde a una vera domanda operativa:

  • mettere — accetta un originale; mettere-varianti — accetta una copia già finita senza ricodificarla, per trasferire ciò che un cliente ha già. Ricodificare una copia finita significa perdere qualità senza motivo.
  • risolvi e risolvere-lotto (fino a 1000 chiavi) — quali indirizzi ha questa chiave. Questo è uno strumento di riparazione: se un record è perso chiedi piuttosto che indovinare.
  • riconciliare — un controllo a secco, fino a 1000 record alla volta, che non cambia nulla e risponde ok / mancante / discrepanza / in attesa per record più un riepilogo del lotto.
  • inventario — l'esportazione che esegue il confronto al contrario, l'elenco del servizio contro quello del cliente, paginato dalla chiave stessa in modo che la pagina non scivoli mentre le cose vengono accettate a metà percorso.
  • oggetto, cancellare, quota, ping, e un non firmato healthz che dice che il front end è attivo e nient'altro — nessuna versione, nessuno stato del database.

La riconciliazione merita una nota a parte, perché è l'endpoint che giustifica l'intero contratto. Dopo una grande migrazione c'è esattamente una domanda che conta: è tutto passato. Rispondere file per file significa tante richieste quanti sono i file, quindi nessuno lo fa — e poi una migrazione viene dichiarata conclusa sulla base del fatto che lo script di caricamento non sia andato in crash. La riconciliazione in batch rende la risposta onesta abbastanza economica da ottenere.

13Dashboard, utilizzo e fatturazione

Il dashboard è una libreria senza codice: cartelle, trascinamento di file con il mouse, ricerca per titolo, descrizione e tag. Funziona completamente senza JavaScript — lo script aggiunge comodità, non la capacità di lavorare. Non è nostalgia; è il modo più economico per garantire che il pannello rimanga utilizzabile su una connessione scadente e rimanga testabile senza un motore del browser.

L'uso è conteggiato dall'inizio del mese e suddiviso per giorno: quanto spazio di archiviazione, quanto traffico di consegna e quante operazioni sono cadute in ciascuna data, quanto del pacchetto è stato consumato e cosa è venuto sopra. La suddivisione conta più del totale — una fattura che non puoi attribuire a un giorno è una fattura con cui non puoi discutere.

Tre decisioni nella fatturazione meritano di essere nominate:

  • Lo storage è la media nel periodo, non il picco.Un singolo giorno con un grande upload non dovrebbe far pagare l'intero mese.
  • Il traffico di consegna è i byte effettivamente consegnati, presi dal log del server — non "dimensione del file × numero di richieste", che sovrastima ogni richiesta di intervallo e ogni download abbandonato.
  • Le tariffe sono mantenute in centesimi.Un gigabyte può costare meno di un centesimo; arrotondare a centesimi interi mangerebbe l'intera fattura misurata e trasformerebbe silenziosamente la fattura in finzione.

Nel piano gratuito non c'è affatto fatturazione misurata: l'assunzione si ferma invece di iniziare silenziosamente a spendere i soldi del cliente. Un servizio che decide autonomamente di fatturare qualcuno che non ha mai inserito una carta è un servizio che nessuno raccomanda due volte.

14Stack tecnologico

Abbiamo scelto lo stack per un servizio il cui percorso principale è un server web che consegna un file:

  • PHP 8.4 per l'API e il pannello di controllo — maturo, abbastanza veloce su questo percorso e economico da mantenere in esecuzione, il che è importante per un prodotto con un piano gratuito.
  • Un host di consegna dedicato che serve direttamente dal disco, senza alcun codice applicativo nel percorso della richiesta.
  • WebP per immagini a qualità fissa, H.264 + AAC in HLS per video con un fallback MP4 progressivo.
  • Una coda per il lavoro video, quindi una transcodifica non si trova mai all'interno di una richiesta di upload.
  • HMAC-SHA256 firma della richiesta con due chiavi live per inquilino e una finestra di 300 secondi.
  • Un albero freddo di originali al di fuori del percorso servito, che è ciò che rende possibili nuove varianti e ricostruzioni in seguito.

Il servizio è deliberatamente conservativo in ciò di cui dipende. Non effettua richieste outbound proprie, non utilizza CDN di terze parti e non conserva alcun record sugli utenti del cliente oltre a inquilino, chiave, tipo, conteggio byte e varianti. Ogni dipendenza che non hai è una dipendenza che non può rompere i tuoi media di martedì.

15Design e UX

Il sito pubblico aveva un compito: rendere un prodotto infrastrutturale leggibile per l'ingegnere che lo integrerà effettivamente. Quindi il primo schermo mostra la richiesta reale e la risposta reale — gli indirizzi che tornano in JSON — piuttosto che un'astrazione di essi. Un integratore decide in circa trenta secondi se un servizio media si adatta al proprio codice, e lo decide guardando la forma della sua risposta.

Il resto del sito è scritto allo stesso modo. Ogni capacità è dichiarata insieme alla sua restrizione: varianti nominate eperché le larghezze arbitrarie sono rifiutate; una cache per sempreel'hash nell'indirizzo che lo rende sicuro; un endpoint di cancellazioneeil numero con cui risponde. La documentazione che elenca solo ciò che un servizio può fare lascia il lettore a scoprire i limiti in produzione.

Nel dashboard, lo stesso principio si trasforma nella base senza JavaScript e nella suddivisione dell'uso giorno per giorno: nulla sullo schermo che il lettore non possa controllare e nulla che smetta di funzionare quando uno script non riesce a caricarsi.

16Come abbiamo lavorato

Il progetto è stato eseguito in fasi, ognuna delle quali si concludeva con qualcosa di dimostrabile:

  • Contratto prima.Abbiamo scritto il contratto API — schema di firma, endpoint, codici di rifiuto, forme di risposta — prima dell'implementazione, perché il contratto è la parte su cui i clienti costruiscono e la parte che è costosa da cambiare.
  • Accettazione e varianti.Il pipeline, nel suo ordine fisso, con le due regole su non allungare e non memorizzare duplicati integrate fin dall'inizio.
  • Consegna.L'host separato, l'intestazione impostata, l'indirizzamento basato sul contenuto che rende la cache per sempre sicura.
  • Video.La scala, il poster e l'anteprima, e la coda che continua a transcoding dalla richiesta di upload.
  • Multi-tenant.Domini, tipi, varianti, limiti e il modello di rotazione a due chiavi.
  • Fatturazione e cruscotto.Conteggio misurato con una suddivisione giorno per giorno, poi l'interfaccia della libreria sopra di essa.
  • Una vera migrazione.Abbiamo spostato un catalogo live sul servizio e lo abbiamo riconciliato in batch — ed è così che il punto finale di riconciliazione ha preso forma.

Quell'ultima fase è stata più preziosa di qualsiasi quantità di test interni. Spostare centinaia di migliaia di file reali ha trovato cose che una suite di test non fa: oggetti che il servizio ha accettato e perso, record il cui indirizzo memorizzato era cambiato, e la differenza tra un controllo che verifica gli hash e un controllo che semplicemente conferma che una riga esiste. Una verifica con nulla da verificare riporta successo — quindi abbiamo fatto in modo che la modalità debole indicasse in quale modalità si trova.

17Il risultato

Ciò che è emerso è un host multimediale su cui un prodotto può fare affidamento: una richiesta firmata in, indirizzi finiti fuori, serviti dal dominio del cliente con una cache che può essere mantenuta per sempre.

1 richiesta
originale in — indirizzi finiti indietro
0
richieste in uscita: il servizio non conosce indirizzi di terze parti
24 h
il registro delle consegne con gli indirizzi dei lettori vive un giorno
  • Varianti nominate e una scala HLS, costruita una volta e memorizzata per sempre dietro un indirizzo con hash del contenuto.
  • Il sottodominio del cliente: il lettore vede il proprio marchio, non il nostro.
  • Sicurezza integrata nel percorso di assunzione — tipo analizzato, scansione virus rifiutata, ricodifica, metadati rimossi, SVG rifiutato su entrambi i lati.
  • Cancellazione che risponde con un numero, in modo che un gate di dati personali possa controllare l'esecuzione piuttosto che l'intento.
  • Multi-tenancy con domini propri, propri limiti e rotazione a due chiavi senza downtime.
  • Fatturazione misurata mantenuta in centesimi, suddivisa per giorno, e un piano gratuito che si ferma piuttosto che spende.

18Lezioni apprese

keepix è un caso in cui la maggior parte dell'ingegneria è stata dedicata a decidere cosa il servizio avrebbe rifiutato di fare. Nessuna larghezza arbitraria, nessun indirizzo calcolato, nessun SVG, nessuna richiesta in uscita, nessun mantenimento dei byte originali nel percorso servito, nessuna fatturazione sul piano gratuito. Ognuno di questi rimuove un'intera classe di fallimenti invece di gestirne uno.

La lezione principale che porteremmo al prossimo progetto infrastrutturale: rendere la risposta onesta economica da ottenere. Riconciliazione in batch, utilizzo suddiviso per giorno, un'operazione di cancellazione che restituisce un conteggio, una risposta di assunzione che nomina ciò che ha saltato — in ogni caso l'alternativa non era una risposta sbagliata ma nessuna risposta, e nessuna risposta è ciò con cui i team si accontentano silenziosamente.

Se hai bisogno di un servizio media sotto il tuo dominio, un pipeline di file che deve essere sicura con i caricamenti di altre persone, o un prodotto API-first dove il contratto conta più degli schermi, questo è il tipo di lavoro che facciamo end to end.