Durant sis mòduls, Escena Viva ha viscut d'un fitxer: dades/esdeveniments.json. Ens ha servit bé. Ens va ensenyar fs.promises, ens va permetre construir un domini ric amb Esdeveniment i Sessio, ens va donar de menjar per al servidor node:http del mòdul 4 i per a l'API Express del mòdul 6. Però en tancar aquell mòdul vam deixar una promesa pendent: el problema de l'aforament i la sobrevenda no es resolia amb validació ni amb errors ben tipats, perquè no és un problema de forma ni d'estat, sinó de concurrència i persistència. Aquest problema és la porta d'entrada d'aquest mòdul.
Aquí encara no escriurem ni un esquema de Mongoose ni una sentència CREATE TABLE. Farem una cosa més important: entendre què ens falta, què ens dóna un sistema gestor de bases de dades a canvi de què, com es tria entre el món relacional i el documental sense caure en bàndols, i com es dissenya el model de dades d'Escena Viva. Al final tindràs el plànol complet del que construirem en les cinc lliçons següents.
Contingut
- Per què un fitxer JSON deixa de servir
- Què aporta realment un SGBD
- Relacional davant de documental
- ACID, BASE i el teorema CAP aplicats a un aforament
- El panorama de bases de dades per a Node.js
- Controlador natiu davant d'ORM/ODM
- Dissenyar el model de dades d'Escena Viva
- El model definitiu en un diagrama
- Aïllar la persistència: el patró repositori
- Instal·lar MongoDB i comprovar la connexió
Per què un fitxer JSON deixa de servir
Siguem honestos i concrets. src/cataleg-dades.js no és un mal mòdul: llegeix dades/esdeveniments.json amb fs.promises, memoritza el resultat i exposa obtenirCataleg() i obtenirEsdevenimentPerId(). El problema no és el seu codi, és el seu model d'emmagatzematge. Aquestes són les fallades reals, no teòriques, que Escena Viva ja té avui:
- Escriptures concurrents que es trepitgen. Si dues peticions venen entrades alhora, totes dues llegeixen el fitxer, totes dues modifiquen la seva còpia en memòria i totes dues el reescriuen sencer. L'última escriptura guanya i la primera venda desapareix. No hi ha blocatge, no hi ha arbitratge, no hi ha ningú que decideixi l'ordre. És exactament l'escenari de sobrevenda.
- Escriptures no atòmiques. Un
writeFiled'un catàleg complet es pot interrompre (fallada de disc,SIGKILL, contenidor reiniciat) i deixar un JSON truncat. Un JSON truncat no és un catàleg amb un esdeveniment menys: és un fitxer que ja no s'analitza, i l'aplicació no arrenca. - Tot el catàleg en memòria. Amb 3 esdeveniments i 7 sessions és gratis. Amb 40.000 esdeveniments històrics, cada procés Node carrega megabytes que mai no consulta. La memòria d'un procés és un recurs car i compartit amb el bucle d'esdeveniments.
- Sense consultes eficients. "Dóna'm les sessions del Teatro Almendra entre l'1 i el 15 de març amb entrades lliures" avui es resol recorrent l'array sencer en JavaScript. És O(n) sobre tot el conjunt de dades, al fil principal, i no hi ha manera de millorar-ho sense escriure tu mateix un índex.
- Sense integritat. Res no impedeix que una comanda apunti a
ses-999-9, una sessió que no existeix. Res no impedeix quevenudessuperi l'aforament. Les invariants viuen només a les classes del domini, i si algú escriu el JSON a mà o un script se salta el domini, queden dades corruptes per sempre. - Sense historial. El fitxer només té l'estat actual. Quantes entrades es van vendre dimarts passat? Qui va anul·lar la comanda? No hi ha resposta: l'estat anterior es va sobreescriure.
- Sense accés des de diversos processos. Aquest és el que més fa mal de cara al futur. Al mòdul 10 veurem
clusteri arrencarem diversos processos Node per aprofitar tots els nuclis de la màquina. Amb un fitxer JSON, cada procés tindria la seva pròpia memòria cau i la seva pròpia idea de l'aforament; ni tan sols s'assabentarien de les vendes dels altres. La persistència en fitxer impedeix escalar. I al mòdul 11, en desplegar amb PM2 o diverses rèpliques en contenidors, el problema es multiplica pel nombre d'instàncies.
La conclusió no és que els fitxers siguin dolents. Un fitxer JSON és perfecte per a configuració, per a llavors, per exportar un informe. És dolent com a magatzem d'estat mutable compartit i concurrent. I això és precisament el que és l'aforament d'una sessió.
Què aporta realment un SGBD
Un sistema gestor de bases de dades (SGBD) és un procés especialitzat, normalment en una altra màquina o en un altre contenidor, la única feina del qual és custodiar dades. A canvi d'aprendre'l i d'operar-lo, et dóna sis coses que tu no reimplementaràs bé:
| Garantia | Què significa | Què resol a Escena Viva |
|---|---|---|
| Persistència duradora | Una escriptura confirmada sobreviu a una tallada de llum, gràcies al registre d'escriptura anticipada (WAL/journal) | Mai no es perd una venda ja cobrada |
| Concurrència controlada | Blocatges i control de versions perquè N clients escriguin alhora sense corrompre res | Dos compradors simultanis no es trepitgen |
| Llenguatge de consulta | Filtrar, ordenar, agrupar i agregar al motor, no al teu procés | Informes de recaptació sense llegir tot el catàleg |
| Índexs | Estructures auxiliars que converteixen cerques O(n) en O(log n) | Cercar per sala o per rang de dates és instantani |
| Integritat | Restriccions que el motor fa complir passi el que passi | venudes <= aforament com a llei física, no com a bona intenció |
| Transaccions | Diverses operacions que passen totes o cap | Reservar aforament + crear comanda + emetre entrades com un sol acte |
Fixa't en la darrera fila. És la que resol el problema que arrosseguem, i li dedicarem mitja lliçó 07-06.
Relacional davant de documental
Hi ha dues grans famílies que un desenvolupador de Node es troba cada dia. Cap no és "moderna" i l'altra "antiga"; cap no és "seriosa" i l'altra "de joguina". Són models amb compromisos diferents.
| Criteri | Relacional (PostgreSQL, MySQL) | Documental (MongoDB) |
|---|---|---|
| Unitat de dades | Fila en una taula, amb columnes fixes | Document BSON, semblant a un objecte JSON imbricat |
| Esquema | Rígid i declarat; canviar-lo requereix migració | Flexible; el motor no exigeix forma, l'imposa el teu ODM |
| Relacions | Claus foranes i JOIN resolts pel motor |
Referències resoltes amb consultes extra, o dades incrustades |
| Integritat referencial | Sí, garantida pel motor | No entre col·leccions; la garanteixes tu |
| Transaccions | Natives, multitaula, des de sempre | Atòmiques per document; multidocument des de la 4.0 amb rèpliques |
| Consultes complexes | SQL, molt expressiu i optimitzat durant dècades | Framework d'agregació, potent però diferent |
| Escalat | Vertical i rèpliques de lectura; particionat més costós | Particionat horitzontal (sharding) de sèrie |
| Casos ideals | Dades molt relacionades, informes, diners, invariants dures | Documents autocontinguts, esquema canviant, alt volum de lectura |
La manera sana de llegir aquesta taula: tria el model que s'assembli al teu patró d'accés. Si la teva aplicació gairebé sempre llegeix "un esdeveniment amb totes les seves sessions", el documental et dóna això en una sola lectura de disc. Si la teva aplicació gairebé sempre creua cinc entitats per treure un informe, el relacional t'ho dóna en una sola consulta optimitzada.
Escena Viva, curiosament, té les dues cares: el catàleg és documental per naturalesa (un esdeveniment conté les seves sessions) i la venda és relacional per naturalesa (comandes, entrades, usuaris i diners). Per això aquest mòdul fa les dues coses: MongoDB serà la persistència oficial a les lliçons 2 a 4, i a les lliçons 5 i 6 modelarem el mateix a PostgreSQL per veure què canvia — i descobrirem que la sobrevenda es resol de manera especialment elegant allà.
ACID, BASE i el teorema CAP aplicats a un aforament
ACID descriu les garanties d'una transacció. Atomicitat: la transacció passa sencera o no passa. Consistència: en acabar, totes les regles de l'esquema continuen complint-se. Aïllament: dues transaccions simultànies no es veuen a mitges, el resultat és com si s'haguessin executat en algun ordre. Durabilitat: un cop confirmada, sobreviu a la fallada del servidor. Els sistemes relacionals van néixer amb ACID i els documentals l'han anat incorporant. BASE és el compromís contrari, típic de sistemes distribuïts massius: Basically Available (sempre respon), Soft state (l'estat pot estar en trànsit), Eventually consistent (si deixes d'escriure, en algun moment totes les rèpliques coincidiran). BASE canvia correcció immediata per disponibilitat i escala.
El teorema CAP explica per què existeix aquest canvi. En un sistema distribuït en què la xarxa es pot partir (i sempre pot), no es poden mantenir alhora consistència forta (C) i disponibilitat total (A): quan dos nodes deixen de veure's, o bé rebutges escriptures per no divergir, o bé les acceptes i divergiràs. Com que la tolerància a particions (P) no és opcional en una xarxa real, la decisió pràctica és entre CP (rebutjo escriptures dubtoses, continuo sent correcte) i AP (accepto tot, ja reconciliaré).
| ACID | BASE | |
|---|---|---|
| Prioritza | Correcció immediata | Disponibilitat i escala |
| Davant d'una partició de xarxa | Rebutja escriptures dubtoses (CP) | Les accepta i reconcilia després (AP) |
| Estat després d'escriure | Definitiu i visible per a tothom | Pot trigar a propagar-se |
| Exemple a Escena Viva | venudes d'una sessió, estat de la comanda |
Comptador de visites, recomanacions |
Aplicat a Escena Viva: un aforament exigeix garanties fortes. Vendre una entrada de més no és un detall cosmètic que s'arregli "eventualment"; és una persona amb un codi EV-2026-000431 dreta a la porta del Teatro Almendra sense butaca, i un reemborsament, i una reclamació. El comptador venudes és l'exemple de llibre de dada que necessita consistència immediata: preferim rebutjar una compra dubtosa (CP) a acceptar-la i descobrir després que no hi havia lloc. En canvi, altres dades de la mateixa plataforma toleren perfectament consistència eventual: el nombre de visites de la pàgina d'un esdeveniment, les recomanacions, o la memòria cau del catàleg que veurem amb Redis al mòdul 10. La garantia es tria per dada, no per aplicació.
El panorama de bases de dades per a Node.js
| Motor | Família | Punt fort | Quan triar-lo | Paquet npm |
|---|---|---|---|---|
| PostgreSQL | Relacional | El més complet: JSONB, tipus rics, transaccions sòlides, extensions | Per defecte si dubtes i hi ha diners o invariants pel mig | pg |
| MySQL / MariaDB | Relacional | Desplegament enorme, operació coneguda, molt ràpid en lectures simples | Ecosistema o allotjament que ja l'imposa | mysql2 |
| SQLite | Relacional incrustada | Sense servidor: la base de dades és un fitxer | Aplicacions d'escriptori, CLI, proves, prototips | better-sqlite3 |
| MongoDB | Documental | Documents imbricats, esquema flexible, sharding de sèrie | Dades autocontingudes i amb forma canviant | mongodb |
| Redis | Clau-valor en memòria | Latència de microsegons, estructures de dades, TTL | Memòria cau, sessions, cues — és del mòdul 10, no un magatzem principal | redis |
Redis mereix un aclariment perquè es malinterpreta molt: no és "una base de dades més ràpida", és una base de dades en memòria amb un model de durabilitat diferent. S'utilitza davant de la base de dades principal, no en el seu lloc. Al mòdul 10 la farem servir per posar el catàleg a la memòria cau i per encuar els correus de confirmació.
Controlador natiu davant d'ORM/ODM
Entre el teu codi i el motor sempre hi ha un controlador (driver): parla el protocol binari de la base de dades i exposa una API de baix nivell. A sobre hi pot haver un ORM (Object-Relational Mapper, món SQL) o un ODM (Object-Document Mapper, món documental), que tradueix entre files o documents i objectes de JavaScript.
| Aspecte | Controlador natiu | ORM / ODM |
|---|---|---|
| Control sobre la consulta | Total, escrius exactament el que s'executa | Indirecte: la genera la biblioteca |
| Rendiment màxim | El sostre del motor | Una mica menys, per la capa de traducció |
| Esquema i validació | L'escrius tu | Declarativa, inclosa |
| Relacions | Les resols a mà | populate / include |
| Migracions | Teves | Eina integrada |
| Corba d'aprenentatge | Aprens el motor | Aprens el motor i la biblioteca |
| Risc | Codi repetitiu, errors manuals | Consultes ineficients que no veus, "màgia" difícil de depurar |
El que et dóna un ORM/ODM: menys codi repetitiu, validació declarativa, tipus coherents, hooks, migracions i un model mental uniforme per a tot l'equip. El que et treu: transparència. Una línia innocent pot generar 200 consultes (el problema N+1 que veurem a la lliçó 07-04). La regla professional és: fes servir l'ORM per al 95 % del codi i no tinguis por de baixar a consultes en cru per al 5 % que importa, mesurant abans de decidir. En aquest mòdul farem servir Mongoose (ODM) i Sequelize (ORM), i en tots dos casos veurem com escapar a la consulta crua.
Dissenyar el model de dades d'Escena Viva
Abans d'escriure un esquema cal decidir què és una entitat. Una entitat és quelcom que té identitat pròpia i cicle de vida propi: existeix abans i després de l'operació que la va crear, i té sentit cercar-la per si mateixa. Un esdeveniment és una entitat. Una comanda és una entitat. El nom de la sala, en canvi, és un atribut.
La segona decisió és què s'agrupa i què se separa. Al món documental això s'anomena incrustar davant de referenciar i ho estudiarem a fons a la lliçó 07-04, però el criteri ja el podem aplicar amb dues preguntes:
- Es llegeixen sempre junts? Si mai no demanes una sessió sense el seu esdeveniment, agrupa'ls.
- Creix sense límit? Si la col·lecció filla creix indefinidament, separa-la.
Apliquem-ho a les nostres entitats:
Esdevenimentamb les seves sessions incrustades. Un esdeveniment té entre 1 i 7 sessions al nostre catàleg; una obra en cartell en podria tenir 60. És un nombre acotat i conegut per endavant. A més, la pantalla de detall de l'esdeveniment i la mateixa API (GET /esdeveniments/:id) les demanen sempre juntes: ja avui el controladorllistarSessionsDeLEsdevenimentparteix d'unEsdevenimentcarregat. I la seva mida és minúscula. S'incrusten.Comandacom a col·lecció a part. Les comandes creixen sense sostre: un esdeveniment popular en pot acumular desenes de milers. Tenen cicle de vida propi (pendent → pagat → emes | anullat) i es consulten pel seu compte ("les meves comandes"). Ficar-les dins de l'esdeveniment faria créixer el document fins a rebentar el límit i obligaria a reescriure'l sencer a cada compra. Se separen.Entradacom a col·lecció a part. Cada entrada té el seu codi únicEV-2026-000431, el seu estat (valida → usada | anullada) i es valida individualment a la porta, escanejant. És la unitat d'accés més petita del sistema i la de més volum. Se separa, amb referències a la comanda i a la sessió.Usuaricom a col·lecció a part, amb el seurol(assistent, organitzador, administrador). En aquest mòdul el creem sense contrasenyes ni autenticació: això és íntegrament el mòdul 8. Aquí només deixem el forat preparat.
I una tercera decisió, deliberadament incòmoda: el comptador venudes viu dins de la sessió, encara que es podria calcular comptant entrades vàlides. És una desnormalització a propòsit, perquè comprovar l'aforament sigui una lectura d'un camp i no una agregació. El preu és mantenir la coherència entre el comptador i les entrades reals; aquest preu el paguem amb les tècniques de la lliçó 07-06.
El model definitiu en un diagrama
erDiagram
USUARI ||--o{ COMANDA : "realitza"
ESDEVENIMENT ||--|{ SESSIO : "conte (incrustada)"
COMANDA ||--|{ ENTRADA : "agrupa"
SESSIO ||--o{ ENTRADA : "es reservada per"
USUARI {
string _id
string correu
string nom
string rol
}
ESDEVENIMENT {
string _id
string esdevenimentId
string titol
string sala
string organitzadorId
string categoria
string estat
int duracioMinuts
}
SESSIO {
string sessioId
date dataHora
int aforament
int venudes
int preuCentims
}
COMANDA {
string _id
string usuariId
string sessioId
int quantitat
int totalCentims
string estat
string canal
}
ENTRADA {
string _id
string codi
string comandaId
string sessioId
string estat
}
Llegeix-ho així: SESSIO apareix com a entitat al diagrama perquè conceptualment ho és, però físicament viu dins del document ESDEVENIMENT com a subdocument. COMANDA i ENTRADA són col·leccions independents que es relacionen per referència. Aquest és el plànol que implementarem a la lliçó 07-02 amb Mongoose i que traduirem a taules a la 07-05 amb Sequelize — on SESSIO sí que serà una taula pròpia, i veurem per què.
Aïllar la persistència: el patró repositori
Aquí va l'advertència d'arquitectura més important del mòdul. Si els controladors criden directament Esdeveniment.find(...), la teva aplicació queda casada amb MongoDB per sempre. Canviar de motor, o provar amb dades falses, o consultar dues fonts diferents, exigiria reescriure tots els controladors.
La solució és una capa fina: src/repositoris/. Un repositori exposa operacions en el llenguatge del negoci (obtenirCataleg, obtenirEsdevenimentPerId, reservarAforament, crearComanda) i amaga per complet com es compleixen. Per damunt d'ell, controladors i domini no saben si a sota hi ha Mongo, Postgres o un array.
// src/repositoris/esdeveniments.js (contracte, la implementacio arriba a la llico 07-03)
'use strict';
/**
* Retorna el cataleg complet com a instancies del domini.
* Qui crida no sap si ve de Mongo, de Postgres o d'un fitxer.
*/
async function obtenirCataleg() {
throw new Error('sense implementar');
}
/** Retorna un Esdeveniment del domini, o null si no existeix. */
async function obtenirEsdevenimentPerId(esdevenimentId) {
throw new Error('sense implementar');
}
module.exports = { obtenirCataleg, obtenirEsdevenimentPerId };Fixa't en el detall decisiu: és exactament la signatura pública de src/cataleg-dades.js. Per això podrem substituir el mòdul sencer sense tocar src/controladors/esdeveniments.js. I per això, a la lliçó 07-05, escriurem una segona implementació sobre Sequelize sense canviar una línia de l'aplicació. El repositori retorna objectes del domini (Esdeveniment, Sessio), no documents de Mongoose: així el domini conserva els seus getters (ocupacio, exhaurida) i les seves invariants, tal com els vam deixar al mòdul 2.
Instal·lar MongoDB i comprovar la connexió
Tres camins, tots vàlids. Tria'n un.
Opció A: servei local. Instal·la MongoDB Community Server des del lloc oficial i arrenca'l com a servei del sistema:
# Comprovar que el servei esta viu (Linux amb systemd)
sudo systemctl status mongod
sudo systemctl start mongodOpció B: Docker. La més neta perquè no embruta la teva màquina i s'esborra en una ordre. Al mòdul 11 formalitzarem això amb docker compose:
# Aixeca MongoDB 7 al port estandard, amb volum persistent
docker run -d --name mongo-escena-viva \
-p 27017:27017 \
-v escena-viva-dades:/data/db \
mongo:7Opció C: MongoDB Atlas. El servei gestionat al núvol. Té una capa gratuïta suficient per a aquest curs; et donarà una URL del tipus mongodb+srv://usuari:[email protected]/escena_viva. És el que faràs servir en producció si no vols operar el motor tu mateix.
Sigui quina sigui l'opció, comprova la connexió amb el client oficial mongosh:
I dins de l'intèrpret:
// Veure en quina base som (la crea al primer escrit, no abans)
db.getName(); // 'escena_viva'
// Inserir un document de prova i recuperar-lo
db.prova.insertOne({ sala: 'Teatro Almendra', creat: new Date() });
db.prova.find();
// Netejar
db.prova.drop();Una peculiaritat que sorprèn: MongoDB no crea la base de dades ni la col·lecció fins al primer document. Si show dbs no llista escena_viva acabat de connectar, no és un error.
L'URL de connexió no s'escriurà mai a mà al codi. Anirà a .env i es llegirà des de src/config/index.js, que ja és l'únic punt de l'aplicació que toca process.env:
I amb la connexió comprovada, convé fixar per endavant quines preguntes farà l'aplicació, perquè el model de dades es dissenya des de les consultes cap enrere. Aquestes són les cinc consultes més freqüents d'Escena Viva, i són les que governaran els índexs de la lliçó 07-02:
| Consulta | Freqüència | Entitat de partida |
|---|---|---|
| Catàleg d'esdeveniments publicats | Molt alta | Esdeveniment |
| Detall d'un esdeveniment amb les seves sessions | Molt alta | Esdeveniment |
| Comprovar l'aforament lliure d'una sessió | Molt alta (crítica) | Sessió dins de l'Esdeveniment |
| Comandes d'un usuari | Mitjana | Comanda |
| Validar una entrada pel seu codi a la porta | Alta en horari de funció | Entrada |
Errors Comuns i Consells
- Triar el motor per moda. "Fem servir Mongo perquè és JavaScript" no és un criteri. El criteri és el patró d'accés, les garanties que necessites i el que el teu equip sap operar.
- Creure que "sense esquema" significa "sense disseny". MongoDB no t'obliga a declarar una forma, però les teves dades la tenen igualment. Si no la decideixes tu, la decidirà cada
insertque escriguis, i acabaràs amb set variants del mateix document. - Ficar l'URL de connexió al codi. Amb credencials a dins i pujada a git. Va a la configuració, sempre. Ja tens el lloc:
src/config/index.js. - Deixar la base de dades sense autenticació "perquè és desenvolupament". Un MongoDB exposat al 27017 sense usuari és dels blancs preferits dels escàners automàtics. En local, com a mínim no publiquis el port fora de
localhost. - Consell: abans de modelar, escriu les cinc consultes que la teva aplicació farà més vegades. El model de dades es dissenya des de les consultes cap enrere, no des de les entitats cap endavant.
- Consell: conserva
dades/esdeveniments.json. No l'esborrarem: a la lliçó 07-06 es convertirà en la llavor que carrega la base de dades. Es jubila com a magatzem, no com a font.
Exercicis
Exercici 1: auditoria del teu propi codi
Obre src/cataleg-dades.js i src/controladors/comandes.js i localitza, sense executar res, els punts exactes on dues peticions simultànies poden corrompre l'estat. Escriu per a cadascun: quina línia llegeix, quina línia escriu, i què passa si una altra petició es cola entre totes dues.
Exercici 2: decidir el model
Escena Viva vol afegir dues coses: (a) les ressenyes que els assistents deixen sobre un esdeveniment, i (b) el plànol de butaques de cada sala. Per a cadascuna, decideix si s'incrusta o se separa i justifica la decisió amb els dos criteris d'aquesta lliçó (lectura conjunta i creixement).
Exercici 3: triar garanties
Classifica aquestes quatre dades segons necessitin consistència forta o eventual, i justifica-ho: (1) venudes d'una sessió, (2) el comptador de visites de la fitxa d'un esdeveniment, (3) l'estat d'una comanda, (4) el llistat d'"esdeveniments recomanats per a tu".
Solucions
Exercici 1. El patró perillós és sempre llegir-modificar-escriure sense exclusió mútua. Al flux de compra: es llegeix el catàleg memoritzat, es comprova sessio.lliures >= quantitat, es crida sessio.vendre() i es persisteix. Si dues peticions executen la comprovació abans que qualsevol de les dues escrigui, totes dues la superen encara que només quedi una entrada. La memorització empitjora les coses: la còpia en memòria pot portar minuts desactualitzada respecte al fitxer. I com que Node és monofil, el forat s'obre exactament a cada await — el bucle d'esdeveniments del mòdul 2 cedeix el torn just allà.
Exercici 2. (a) Les ressenyes se separen: creixen sense límit (un festival en pot acumular milers), no calen per renderitzar el catàleg, es paginen i s'ordenen per data, i es moderen amb cicle de vida propi. (b) El plànol de butaques s'incrusta a la sala (o es referencia com a catàleg a part si diverses sales comparteixen plantilla), perquè és de mida acotada, no canvia gairebé mai i sempre es llegeix juntament amb la sala. Compte: l'ocupació de cada butaca en una sessió concreta sí que és volàtil i de molta escriptura, així que aquest estat no ha de viure al plànol estàtic.
Exercici 3. (1) venudes: forta, és la definició mateixa del problema de sobrevenda. (3) Estat de la comanda: forta, decideix si es cobra i si s'emeten entrades; una lectura obsoleta pot duplicar un cobrament. (2) Visites: eventual, un error d'un 2 % durant uns segons no perjudica ningú i a canvi permet comptar en memòria i abocar per lots. (4) Recomanacions: eventual, es calculen en diferit i ningú no nota que porten una hora de retard.
Conclusió
Hem tancat l'etapa del fitxer. Ara saps, amb noms concrets, què li falta a dades/esdeveniments.json: atomicitat, concurrència, consultes, índexs, integritat, historial i accés multiprocés. Saps què et dóna un SGBD a canvi, què separa el model relacional del documental sense necessitat de prendre partit, i per què un aforament pertany al territori de les garanties fortes segons ACID i CAP. Has vist el panorama real de motors per a Node i el compromís entre baixar al controlador natiu o recolzar-te en un ORM/ODM. I, sobretot, tens el model de dades d'Escena Viva decidit i raonat: Esdeveniment amb les seves sessions incrustades, Comanda, Entrada i Usuari com a col·leccions separades, amb el comptador venudes desnormalitzat a propòsit.
També tens la peça d'arquitectura que sosté tot el mòdul: src/repositoris/, la frontera que impedirà que el motor de base de dades es filtri als controladors i al domini.
A la lliçó següent baixem al codi. Connectarem amb MongoDB des de src/config/index.js, escriurem src/db/connexio.js amb la seva obertura en arrencar i el seu tancament a l'aturada ordenada que ja existeix a src/servidor.js, i traduirem aquest diagrama a esquemes i models de Mongoose a src/models/: tipus, validadors, virtuals, middleware d'esquema i índexs. El plànol es converteix en estructura.
Curs de Node.js: De Principiant a Avançat
Mòdul 1: Introducció a Node.js
- Què és Node.js?
- Instal·lació i Configuració de l'Entorn
- El Teu Primer Programa en Node.js
- El REPL de Node.js
- JavaScript Modern per a Node.js
- El Projecte del Curs: la Plataforma Escena Viva
Mòdul 2: Conceptes Bàsics
- Arquitectura de Node.js
- El Bucle d'Esdeveniments (Event Loop)
- Callbacks i Programació Asíncrona
- Promeses i async/await
- Esdeveniments i EventEmitter
- Mòduls CommonJS i require()
- Mòduls ES i Interoperabilitat
Mòdul 3: Sistema de Fitxers i E/S
- Lectura i Escriptura de Fitxers
- El Mòdul fs a Fons
- Rutes Multiplataforma amb el Mòdul path
- Treballant amb Streams
- Streams de Transformació i pipeline
- Buffers i Dades Binàries
Mòdul 4: HTTP i Servidors Web
- Creant un Servidor HTTP Simple
- Gestió de Sol·licituds i Respostes
- Enrutament Manual
- Servint Fitxers Estàtics
- Rebent Dades: Cossos de Petició i JSON
- Consumint APIs Externes des de Node.js
Mòdul 5: NPM i Gestió de Paquets
- Introducció a NPM i package.json
- Instal·lació i Ús de Paquets
- Versionat Semàntic i package-lock
- Scripts d'npm i Automatització del Projecte
- Creació i Publicació de Paquets
- Seguretat i Manteniment de Dependències
Mòdul 6: Framework Express.js
- Introducció a Express.js
- Configuració d'una Aplicació Express
- Enrutament a Express
- Middleware
- Middleware de Tercers Essencials
- Validació de Dades d'Entrada
- Gestió d'Errors
Mòdul 7: Bases de Dades i ORMs
- Introducció a les Bases de Dades
- Usant MongoDB amb Mongoose
- Operacions CRUD
- Relacions, Poblat i Consultes Avançades
- Usant Bases de Dades SQL amb Sequelize
- Migracions, Transaccions i Dades de Prova
Mòdul 8: Autenticació i Autorització
- Introducció a l'Autenticació
- Registre d'Usuaris i Hash de Contrasenyes
- Sessions i Galetes amb Passport.js
- Autenticació amb JWT
- Control d'Accés Basat en Rols
- Bones Pràctiques de Seguretat en APIs
Mòdul 9: Proves i Depuració
- Introducció a les Proves
- Proves Unitàries amb Mocha i Chai
- Dobles de Prova amb Sinon
- Proves d'Integració
- Cobertura i Automatització de les Proves
- Depuració d'Aplicacions Node.js
Mòdul 10: Temes Avançats
- El Mòdul Cluster
- Fils de Treball (Worker Threads)
- Memòria Cau i Cues de Treball amb Redis
- Optimització del Rendiment
- Construcció d'APIs RESTful
- GraphQL amb Node.js
Mòdul 11: Desplegament i DevOps
- Configuració i Variables d'Entorn
- Registre i Monitoratge en Producció
- Usant PM2 per a la Gestió de Processos
- Empaquetatge amb Docker
- Desplegant a Heroku i Altres PaaS
- Integració i Desplegament Continus
