Skip to content

La Dispensa — Il Layer di Storage

“A dispensa bbona nun se vede — se sente quanno manca.” — Proverbio napoletano

Nessuna cucina sopravvive senza una dispensa ben organizzata. Nel Pasta Protocol, La Dispensa è il layer di storage distribuito che garantisce la persistenza degli stati, la durabilità dei dati e la coerenza tra i nodi del cluster. Non importa cosa succede fuori — terremoti, riavvii, partizioni di rete — la dispensa sa dove si trovano gli ingredienti.

Il layer astrae tre backend distinti attraverso un’interfaccia unificata. Puoi cambiare il backend senza toccare una riga di logica applicativa. La pasta rimane sempre la pasta, che tu usi un tavolo di marmo o un banco di acciaio.

L’Interfaccia Unificata

interface Dispensa {
/** Recupera un valore per chiave. Ritorna undefined se assente. */
get<T>(key: string): Promise<T | undefined>;
/** Salva un valore con TTL opzionale (in cotture). */
set<T>(key: string, value: T, ttlCotture?: number): Promise<void>;
/** Rimuove una chiave. Idempotente se la chiave non esiste. */
delete(key: string): Promise<boolean>;
/** Verifica l'esistenza di una chiave senza recuperare il valore. */
exists(key: string): Promise<boolean>;
/** Operazione atomica compare-and-swap. */
cas<T>(key: string, expected: T, next: T): Promise<boolean>;
/** Elenca le chiavi corrispondenti a un pattern. */
keys(pattern: string): AsyncIterable<string>;
/** Transazione atomica multi-chiave. */
transaction(ops: ReadonlyArray<DispensaOp>): Promise<TransactionResult>;
}

I Backend di Storage

Il backend Tavolo di Lavoro è lo storage in memoria — velocissimo, senza dipendenze esterne, perfetto per sviluppo, test e cache locale. Come il tavolo di marmo del pizzaiolo: immediato, sempre disponibile, ma tutto si perde quando si spegne la luce.

import { createDispensa, InMemoryBackend } from '@pasta-protocol/storage';
const dispensa = createDispensa({
backend: new InMemoryBackend({
maxEntries: 10_000,
evictionPolicy: 'LRU',
ttlCheckIntervalCotture: 5,
}),
});
// Lettura e scrittura immediate
await dispensa.set('ordine:001', { tavolo: 7, piatti: ['margherita', 'calzone'] });
const ordine = await dispensa.get<Ordine>('ordine:001');

Configurazione .ricetta:

[dispensa]
backend = "in-memory"
max_entries = 10000
eviction_policy = "LRU"
ttl_check_interval_cotture = 5

Quando usarlo:

  • Ambiente di sviluppo locale
  • Test di integrazione isolati
  • Cache di secondo livello su singolo nodo
  • Prototipazione rapida

Limitazioni: I dati non sopravvivono al riavvio del nodo. Non adatto per produzione con requisiti di durabilità.

Strategie di Caching Multi-Livello

Il Pasta Protocol supporta una configurazione a livelli — come una layered lasagna. Scrivi nella Cantina per durabilità, ma leggi prima dalla Mozzarella Cache:

import { createDispensa, LayeredBackend } from '@pasta-protocol/storage';
const dispensa = createDispensa({
backend: new LayeredBackend({
layers: [
{ backend: new InMemoryBackend({ maxEntries: 1_000 }), ttlCotture: 2 },
{ backend: new RedisBackend({ host: 'redis.local' }), ttlCotture: 60 },
{ backend: new PostgresBackend({ connectionString: process.env.DATABASE_URL }) },
],
writeStrategy: 'WRITE_THROUGH', // scrive su tutti i livelli
readStrategy: 'READ_FIRST_HIT', // legge dal primo livello che risponde
}),
});

Metriche e Osservabilità

La Dispensa espone metriche sul proprio funzionamento attraverso l’interfaccia standard:

const stats = await dispensa.stats();
// {
// hits: 4821,
// misses: 143,
// hitRate: 0.97,
// avgLatencyMs: 1.2,
// backend: 'redis',
// connectedNodes: 3
// }

Dal CLI del framework:

pasta> dispensa stats
Backend: Mozzarella Cache (Redis)
Hit rate: 97.2%
Avg latency: 1.2ms
Keys stored: 18,432
Memory used: 42.1 MB

La dispensa ben tenuta è la fondamenta invisibile di ogni buon piatto. Non ci pensi quando funziona — la rimpianti solo quando manca.