Modello Multi-Tenant: Isolamento Dati
Panoramica
La piattaforma implementa un modello multi-tenant con isolamento a livello di database. Ogni tenant (ristorante, punto vendita) dispone di un database MongoDB dedicato. Questo approccio garantisce separazione completa dei dati, semplifica backup e restore per singolo tenant e permette scaling indipendente.
Convenzioni di Naming dei Database
La piattaforma gestisce tre livelli di dati, ciascuno con la propria convenzione:
| Prefisso | Pattern | Esempio | Uso |
|---|---|---|---|
t_ | t_{tenantId} | t_ristorante01 | Dati operativi del singolo ristorante |
r_ | r_{resellerCode} | r_ACME | Dati cross-tenant del reseller (manutenzioni, installazioni) |
| nessuno | pos_platform | pos_platform | Dati condivisi della piattaforma (tenant registry, licenze, audit) |
Come Funziona l'Isolamento
Il flusso di isolamento segue questi passi:
- Il client invia una richiesta con header
Authorization: Bearer <JWT> - L'API Gateway valida il JWT e estrae
tenantIddal token (claim Keycloak o payload HS256) - Il gateway popola
ctx.meta.tenantIdnel contesto Moleculer - Il servizio destinatario usa il mixin appropriato per selezionare il database corretto
- Tutte le query operano esclusivamente sul database del tenant
Non esiste alcun modo per un servizio di accedere accidentalmente ai dati di un altro tenant: la selezione del database avviene a livello di mixin, non di query.
Pool di Connessioni Condiviso
Tutti i servizi condividono un singleton connection pool verso il cluster MongoDB. Il pool viene creato una sola volta alla prima connessione e riutilizzato da tutte le istanze dei mixin.
Parametri di configurazione principali (variabili ambiente):
MONGO_BASE_URI=mongodb+srv://user:pass@cluster.mongodb.net
MONGO_MAX_POOL_SIZE=500 # Connessioni massime (default: 500)
MONGO_MIN_POOL_SIZE=50 # Connessioni minime (default: 50)
MONGO_SOCKET_TIMEOUT=45000 # Timeout socket in ms
Il pool e scalato per supportare migliaia di tenant senza creare connessioni dedicate per ciascuno.
Caching Multi-Tenant
Il Redis cacher di Moleculer deve distinguere i dati cached di tenant diversi. I mixin implementano getCacheKey() che antepone il tenantId (o resellerCode) alla chiave di cache standard:
tenantId:nomeServizio.azione:parametriHash
Questo impedisce che una richiesta di un tenant riceva dati cached di un altro tenant. Le azioni di scrittura (create, update, remove) invalidano automaticamente la cache del servizio.
Dati della Piattaforma
Il database pos_platform contiene dati condivisi tra tutti i tenant:
- Tenant registry: elenco tenant, configurazioni, licenze
- Reseller registry: anagrafica reseller
- Audit log: log immutabile delle sessioni di supporto
- Device registry: dispositivi registrati e associazioni licenza
I servizi che accedono a pos_platform usano PlatformDbMixin che non richiede tenantId nel contesto.
Aggiungere un Nuovo Tenant
Per creare un nuovo tenant sulla piattaforma:
- Creare il record in
pos_platform.tenantstramitetenant-management.create - Il database
t_{tenantId}viene creato automaticamente da MongoDB al primo inserimento - Configurare i gruppi Keycloak per gli utenti del nuovo tenant
- Generare un OTP per registrare il primo dispositivo
Non e necessario creare manualmente il database o le collezioni: MongoDB li crea on-demand.
FAQ
D: Cosa succede se una richiesta arriva senza tenantId?
R: Il TenantDbMixin fa fallback sul database pos_platform. In produzione, i servizi che richiedono un tenant dovrebbero verificare esplicitamente la presenza di tenantId e rifiutare la richiesta se assente.
D: Posso fare query cross-tenant (es. report aggregati)?
R: Non direttamente tramite i mixin standard. I servizi di reporting platform-level devono iterare sui tenant registrati e aggregare i risultati. Il ResellerDbMixin supporta dati cross-tenant a livello reseller.
D: Come migro i dati da un tenant a un altro?
R: Usare il servizio tenant-clone che copia collezioni tra database tenant, rimappando gli ID interni.
Vedi Anche
- Mixin Database -- Dettagli implementativi dei tre mixin
- Token HS256 vs RS256 -- Come il tenantId viene estratto dal JWT
- Panoramica Architettura -- Visione d'insieme della piattaforma