Skip to content

0007. File connector: storage × codec

  • Stato: Accettata
  • Data: 2026-06-03
  • Decisori: Team BI/ETL

Contesto

Servono connettori per file su diversi formati (CSV, XLSX, JSON/NDJSON, XML, Parquet) e diversi storage (filesystem locale, S3, Azure Blob, GCS, FTP, SFTP). Formato e storage sono concern ortogonali: lo stesso CSV può arrivare da locale o da S3; su S3 possono esserci CSV, XLSX o Parquet.

Decisione

Modelliamo due astrazioni componibili invece di un connettore per combinazione:

  • StorageProvider — stream di byte indipendente dal formato: list(prefix), get(path) -> AsyncIterable<Uint8Array>, put(path, data).
  • FileCodec<T> — byte ↔ record indipendente dallo storage: decode(bytes), encode(records).
  • fileSource(storage, codec, { path | prefix }) e fileSink(storage, codec, { path }) combinano i due in un Source/Sink del core.

Con N formati e M storage bastano N+M pezzi (non N×M). Esempio: "CSV da SFTP", "Parquet su S3" sono semplici composizioni.

Incluso in questa issue (#21): le interfacce, fileSource/fileSink, e un StorageProvider in-memory (memoryStorage, riusabile nei test come arraySink), validati end-to-end con un codec di prova. Gli storage concreti (filesystem #27, S3 #28, SFTP #29, …) e i codec concreti (CSV #22, XLSX #23, …) arrivano nelle rispettive issue, ognuno con il proprio ADR per la dipendenza.

Alternative considerate

  • Un connettore per combinazione (es. s3CsvSource) — esplode in N×M, duplicazione.
  • Un'unica classe "file" parametrica con format+storage hardcoded — meno componibile e testabile.

Conseguenze

  • Positive: massima riusabilità (ogni storage funziona con ogni codec), test in isolamento, streaming di byte preservato, crescita per piccoli pezzi indipendenti.
  • Costi: due livelli di astrazione da comporre; i formati non-streamabili (es. XLSX/Parquet) potranno bufferizzare per-file nel codec (documentato nei rispettivi connettori).

Noeva è un marchio registrato di 4D S.R.L.