Implement a database versioning system to speed up updates
Add a database versioning system that tracks applied migrations and only runs new ones, significantly improving update speed. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: ab56b852-52de-4cd1-a489-5cf48f3a2965 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/myJmPIa
This commit is contained in:
parent
79a37639e0
commit
7b85fcc020
6
.replit
6
.replit
@ -1,4 +1,4 @@
|
|||||||
modules = ["nodejs-20", "web", "postgresql-16", "python-3.11"]
|
modules = ["nodejs-20", "web", "python-3.11", "postgresql-16"]
|
||||||
run = "npm run dev"
|
run = "npm run dev"
|
||||||
hidden = [".config", ".git", "generated-icon.png", "node_modules", "dist"]
|
hidden = [".config", ".git", "generated-icon.png", "node_modules", "dist"]
|
||||||
|
|
||||||
@ -14,6 +14,10 @@ run = ["npm", "run", "start"]
|
|||||||
localPort = 5000
|
localPort = 5000
|
||||||
externalPort = 80
|
externalPort = 80
|
||||||
|
|
||||||
|
[[ports]]
|
||||||
|
localPort = 35745
|
||||||
|
externalPort = 3001
|
||||||
|
|
||||||
[[ports]]
|
[[ports]]
|
||||||
localPort = 41303
|
localPort = 41303
|
||||||
externalPort = 3002
|
externalPort = 3002
|
||||||
|
|||||||
316
database-schema/README.md
Normal file
316
database-schema/README.md
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
# Database Schema & Migrations - Sistema Versionato
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Sistema intelligente di migrazioni database con **version tracking**. Applica solo le migrazioni necessarie, velocizzando gli aggiornamenti.
|
||||||
|
|
||||||
|
## 🎯 Vantaggi
|
||||||
|
|
||||||
|
✅ **Veloce**: Applica solo migrazioni mancanti (non riesegue quelle già fatte)
|
||||||
|
✅ **Sicuro**: Traccia versione database, previene errori
|
||||||
|
✅ **Automatico**: Integrato in `update_from_git.sh`
|
||||||
|
✅ **Idempotente**: Puoi eseguire più volte senza problemi
|
||||||
|
|
||||||
|
## 📋 Come Funziona
|
||||||
|
|
||||||
|
### 1. Tabella `schema_version`
|
||||||
|
|
||||||
|
Traccia la versione corrente del database:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE schema_version (
|
||||||
|
id INTEGER PRIMARY KEY DEFAULT 1, -- Sempre 1 (solo 1 riga)
|
||||||
|
version INTEGER NOT NULL, -- Versione corrente (es: 5)
|
||||||
|
applied_at TIMESTAMP, -- Quando è stata applicata
|
||||||
|
description TEXT -- Descrizione ultima migrazione
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Migrazioni Numerate
|
||||||
|
|
||||||
|
Ogni migrazione SQL ha un numero sequenziale nel nome:
|
||||||
|
|
||||||
|
```
|
||||||
|
database-schema/migrations/
|
||||||
|
├── 000_init_schema_version.sql ← Inizializza tracking (sempre eseguita)
|
||||||
|
├── 001_add_missing_columns.sql ← Migrazione 1
|
||||||
|
├── 002_add_indexes.sql ← Migrazione 2
|
||||||
|
├── 003_alter_detections.sql ← Migrazione 3
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
**Convenzione nome**: `XXX_description.sql` dove XXX è numero a 3 cifre (001, 002, 010, 100, etc.)
|
||||||
|
|
||||||
|
### 3. Logica Applicazione
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Script legge versione corrente
|
||||||
|
CURRENT_VERSION = SELECT version FROM schema_version WHERE id = 1;
|
||||||
|
# Esempio: 2
|
||||||
|
|
||||||
|
# Trova migrazioni con numero > 2
|
||||||
|
Trova: 003_*.sql, 004_*.sql, 005_*.sql
|
||||||
|
|
||||||
|
# Applica in ordine
|
||||||
|
Per ogni migrazione:
|
||||||
|
1. Esegui SQL
|
||||||
|
2. Aggiorna versione: UPDATE schema_version SET version = 3
|
||||||
|
3. Prossima migrazione...
|
||||||
|
|
||||||
|
# Risultato: Database aggiornato da v2 a v5
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 Uso Quotidiano
|
||||||
|
|
||||||
|
### Aggiornamento Automatico (Consigliato)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Sul server AlmaLinux
|
||||||
|
cd /opt/ids
|
||||||
|
sudo ./deployment/update_from_git.sh
|
||||||
|
|
||||||
|
# Lo script esegue automaticamente:
|
||||||
|
# 1. Git pull
|
||||||
|
# 2. npm install
|
||||||
|
# 3. pip install
|
||||||
|
# 4. ./database-schema/apply_migrations.sh ← Applica migrazioni
|
||||||
|
# 5. npm run db:push ← Sincronizza schema Drizzle
|
||||||
|
# 6. Restart servizi
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output atteso**:
|
||||||
|
```
|
||||||
|
🗄️ Sistema Migrazioni Database (Versioned)
|
||||||
|
📋 Verifica sistema versioning...
|
||||||
|
✅ Sistema versioning attivo
|
||||||
|
📊 Versione database corrente: 2
|
||||||
|
📋 Trovate 3 migrazioni da applicare
|
||||||
|
|
||||||
|
🔄 Applicando migrazione 3: 003_add_indexes.sql
|
||||||
|
✅ Migrazione 3 applicata con successo
|
||||||
|
|
||||||
|
🔄 Applicando migrazione 4: 004_alter_table.sql
|
||||||
|
✅ Migrazione 4 applicata con successo
|
||||||
|
|
||||||
|
🔄 Applicando migrazione 5: 005_new_feature.sql
|
||||||
|
✅ Migrazione 5 applicata con successo
|
||||||
|
|
||||||
|
╔═══════════════════════════════════════════════╗
|
||||||
|
║ ✅ MIGRAZIONI COMPLETATE ║
|
||||||
|
╚═══════════════════════════════════════════════╝
|
||||||
|
📊 Versione database: 2 → 5
|
||||||
|
```
|
||||||
|
|
||||||
|
Se database già aggiornato:
|
||||||
|
```
|
||||||
|
📊 Versione database corrente: 5
|
||||||
|
✅ Database già aggiornato (nessuna migrazione da applicare)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Applicazione Manuale
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/ids/database-schema
|
||||||
|
./apply_migrations.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verifica Versione Corrente
|
||||||
|
|
||||||
|
```bash
|
||||||
|
psql $DATABASE_URL -c "SELECT * FROM schema_version;"
|
||||||
|
|
||||||
|
id | version | applied_at | description
|
||||||
|
----+---------+----------------------------+-----------------------
|
||||||
|
1 | 5 | 2025-11-22 14:30:15.123456 | Migration 5: Add indexes
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔨 Creare Nuova Migrazione
|
||||||
|
|
||||||
|
### STEP 1: Determina Prossimo Numero
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Trova ultima migrazione
|
||||||
|
ls database-schema/migrations/ | grep "^[0-9]" | sort | tail -n 1
|
||||||
|
# Output: 005_add_indexes.sql
|
||||||
|
|
||||||
|
# Prossima migrazione: 006
|
||||||
|
```
|
||||||
|
|
||||||
|
### STEP 2: Crea File Migrazione
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Formato: XXX_description.sql
|
||||||
|
touch database-schema/migrations/006_add_new_table.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### STEP 3: Scrivi SQL
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- ============================================================================
|
||||||
|
-- Migration 006: Add new table for feature X
|
||||||
|
-- ============================================================================
|
||||||
|
-- Descrizione: Crea tabella per gestire feature X
|
||||||
|
-- Data: 2025-11-22
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS my_new_table (
|
||||||
|
id VARCHAR PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW() NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Crea indici
|
||||||
|
CREATE INDEX IF NOT EXISTS my_new_table_name_idx ON my_new_table(name);
|
||||||
|
|
||||||
|
-- Inserisci dati iniziali (se necessario)
|
||||||
|
INSERT INTO my_new_table (name)
|
||||||
|
SELECT 'Default Entry'
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM my_new_table LIMIT 1);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Best Practices**:
|
||||||
|
- Usa sempre `IF NOT EXISTS` (idempotenza)
|
||||||
|
- Usa `ALTER TABLE ... ADD COLUMN IF NOT EXISTS`
|
||||||
|
- Documenta bene la migrazione
|
||||||
|
- Testa localmente prima di committare
|
||||||
|
|
||||||
|
### STEP 4: Testa Localmente (Replit)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Su Replit
|
||||||
|
cd database-schema
|
||||||
|
./apply_migrations.sh
|
||||||
|
|
||||||
|
# Verifica versione aggiornata
|
||||||
|
psql $DATABASE_URL -c "SELECT version FROM schema_version;"
|
||||||
|
```
|
||||||
|
|
||||||
|
### STEP 5: Commit & Deploy
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Su Replit
|
||||||
|
./push-gitlab.sh
|
||||||
|
|
||||||
|
# Sul server
|
||||||
|
cd /opt/ids
|
||||||
|
sudo ./deployment/update_from_git.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 Esempi Migrazioni Comuni
|
||||||
|
|
||||||
|
### Aggiungere Colonna
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Migration XXX: Add email column to users
|
||||||
|
ALTER TABLE users
|
||||||
|
ADD COLUMN IF NOT EXISTS email TEXT;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Creare Indice
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Migration XXX: Add index on source_ip
|
||||||
|
CREATE INDEX IF NOT EXISTS network_logs_source_ip_idx
|
||||||
|
ON network_logs(source_ip);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Modificare Tipo Colonna (ATTENZIONE!)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Migration XXX: Change column type
|
||||||
|
-- NOTA: Può causare perdita dati se incompatibile!
|
||||||
|
|
||||||
|
ALTER TABLE detections
|
||||||
|
ALTER COLUMN risk_score TYPE DECIMAL(5,2)
|
||||||
|
USING risk_score::DECIMAL(5,2);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Inserire Dati Iniziali
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Migration XXX: Add default admin user
|
||||||
|
INSERT INTO users (username, role)
|
||||||
|
SELECT 'admin', 'admin'
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM users WHERE username = 'admin'
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 Troubleshooting
|
||||||
|
|
||||||
|
### Errore: Migrazione Fallisce
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Verifica errore
|
||||||
|
psql $DATABASE_URL -c "SELECT version FROM schema_version;"
|
||||||
|
|
||||||
|
# Se migrazione 5 è fallita, il database è ancora a v4
|
||||||
|
# Fix: Correggi file 005_*.sql e riesegui
|
||||||
|
./apply_migrations.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reset Completo (ATTENZIONE!)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ⚠️ DISTRUTTIVO - Cancella tutti i dati!
|
||||||
|
psql $DATABASE_URL << 'EOF'
|
||||||
|
DROP SCHEMA public CASCADE;
|
||||||
|
CREATE SCHEMA public;
|
||||||
|
GRANT ALL ON SCHEMA public TO ids_user;
|
||||||
|
GRANT ALL ON SCHEMA public TO public;
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Ricrea schema da zero
|
||||||
|
npm run db:push --force
|
||||||
|
./apply_migrations.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Saltare Migrazione (Avanzato)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Se migrazione 003 è già applicata manualmente
|
||||||
|
# Aggiorna versione manualmente
|
||||||
|
psql $DATABASE_URL -c "
|
||||||
|
UPDATE schema_version
|
||||||
|
SET version = 3,
|
||||||
|
description = 'Migration 3: Manually applied',
|
||||||
|
applied_at = NOW()
|
||||||
|
WHERE id = 1;
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 Workflow Completo
|
||||||
|
|
||||||
|
### Sviluppo (Replit)
|
||||||
|
|
||||||
|
1. Modifica schema in `shared/schema.ts`
|
||||||
|
2. Esegui `npm run db:push` (sincronizza Drizzle)
|
||||||
|
3. Se serve migrazione SQL custom:
|
||||||
|
- Crea `XXX_description.sql`
|
||||||
|
- Testa con `./apply_migrations.sh`
|
||||||
|
4. Commit: `./push-gitlab.sh`
|
||||||
|
|
||||||
|
### Produzione (AlmaLinux)
|
||||||
|
|
||||||
|
1. `sudo ./deployment/update_from_git.sh`
|
||||||
|
2. Script applica automaticamente migrazioni
|
||||||
|
3. Verifica: `psql $DATABASE_URL -c "SELECT * FROM schema_version;"`
|
||||||
|
|
||||||
|
## 📝 Note Tecniche
|
||||||
|
|
||||||
|
- **000_init_schema_version.sql**: Sempre eseguita (idempotente), inizializza tracking
|
||||||
|
- **Constraint**: Tabella `schema_version` ammette solo 1 riga (id=1)
|
||||||
|
- **Formato numeri**: Usa 3 cifre (001, 002, ..., 010, ..., 100) per ordinamento corretto
|
||||||
|
- **Drizzle vs SQL**: `npm run db:push` sincronizza schema TypeScript, migrazioni SQL sono per logica custom
|
||||||
|
|
||||||
|
## ✅ Checklist Pre-Commit
|
||||||
|
|
||||||
|
Quando crei nuova migrazione:
|
||||||
|
|
||||||
|
- [ ] Numero sequenziale corretto (XXX+1)
|
||||||
|
- [ ] Nome file descrittivo
|
||||||
|
- [ ] Commento header con descrizione
|
||||||
|
- [ ] SQL idempotente (`IF NOT EXISTS`, etc.)
|
||||||
|
- [ ] Testata localmente su Replit
|
||||||
|
- [ ] Versione aggiornata: `SELECT version FROM schema_version;`
|
||||||
|
- [ ] Commit message chiaro
|
||||||
@ -1,8 +1,11 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# IDS - Applica Migrazioni Database
|
# IDS - Applica Migrazioni Database (con Version Tracking)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Applica tutti gli script SQL in database-schema/migrations/ in ordine
|
# Sistema intelligente di migrazioni:
|
||||||
|
# - Controlla versione corrente database
|
||||||
|
# - Applica SOLO migrazioni mancanti (più veloce!)
|
||||||
|
# - Aggiorna versione dopo ogni migrazione
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
@ -23,9 +26,10 @@ GREEN='\033[0;32m'
|
|||||||
BLUE='\033[0;34m'
|
BLUE='\033[0;34m'
|
||||||
YELLOW='\033[1;33m'
|
YELLOW='\033[1;33m'
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
NC='\033[0m'
|
NC='\033[0m'
|
||||||
|
|
||||||
echo -e "${BLUE}🗄️ Applicazione migrazioni database...${NC}"
|
echo -e "${BLUE}🗄️ Sistema Migrazioni Database (Versioned)${NC}"
|
||||||
|
|
||||||
# Verifica DATABASE_URL
|
# Verifica DATABASE_URL
|
||||||
if [ -z "$DATABASE_URL" ]; then
|
if [ -z "$DATABASE_URL" ]; then
|
||||||
@ -37,28 +41,107 @@ fi
|
|||||||
# Crea directory migrations se non esiste
|
# Crea directory migrations se non esiste
|
||||||
mkdir -p "$MIGRATIONS_DIR"
|
mkdir -p "$MIGRATIONS_DIR"
|
||||||
|
|
||||||
# Conta migrazioni
|
# =============================================================================
|
||||||
MIGRATION_COUNT=$(find "$MIGRATIONS_DIR" -name "*.sql" 2>/dev/null | wc -l)
|
# STEP 1: Inizializza tracking versione (se necessario)
|
||||||
|
# =============================================================================
|
||||||
|
echo -e "${CYAN}📋 Verifica sistema versioning...${NC}"
|
||||||
|
|
||||||
if [ "$MIGRATION_COUNT" -eq 0 ]; then
|
# Esegue 000_init_schema_version.sql (idempotente)
|
||||||
echo -e "${YELLOW}⚠️ Nessuna migrazione da applicare${NC}"
|
INIT_MIGRATION="$MIGRATIONS_DIR/000_init_schema_version.sql"
|
||||||
exit 0
|
if [ -f "$INIT_MIGRATION" ]; then
|
||||||
|
psql "$DATABASE_URL" -f "$INIT_MIGRATION" -q
|
||||||
|
echo -e "${GREEN}✅ Sistema versioning attivo${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}⚠️ Migration 000_init_schema_version.sql non trovata${NC}"
|
||||||
|
echo -e "${YELLOW} Creazione tabella schema_version...${NC}"
|
||||||
|
|
||||||
|
psql "$DATABASE_URL" << 'EOF' -q
|
||||||
|
CREATE TABLE IF NOT EXISTS schema_version (
|
||||||
|
id INTEGER PRIMARY KEY DEFAULT 1,
|
||||||
|
version INTEGER NOT NULL DEFAULT 0,
|
||||||
|
applied_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
|
description TEXT
|
||||||
|
);
|
||||||
|
INSERT INTO schema_version (id, version, description)
|
||||||
|
SELECT 1, 0, 'Initial schema version tracking'
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM schema_version WHERE id = 1);
|
||||||
|
EOF
|
||||||
|
echo -e "${GREEN}✅ Tabella schema_version creata${NC}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "${BLUE}📋 Trovate $MIGRATION_COUNT migrazioni${NC}"
|
# =============================================================================
|
||||||
|
# STEP 2: Leggi versione corrente database
|
||||||
|
# =============================================================================
|
||||||
|
CURRENT_VERSION=$(psql "$DATABASE_URL" -tAc "SELECT COALESCE(version, 0) FROM schema_version WHERE id = 1;" 2>/dev/null || echo "0")
|
||||||
|
echo -e "${CYAN}📊 Versione database corrente: ${YELLOW}${CURRENT_VERSION}${NC}"
|
||||||
|
|
||||||
# Applica ogni migrazione in ordine
|
# =============================================================================
|
||||||
for migration in $(find "$MIGRATIONS_DIR" -name "*.sql" | sort); do
|
# STEP 3: Trova migrazioni da applicare
|
||||||
MIGRATION_NAME=$(basename "$migration")
|
# =============================================================================
|
||||||
echo -e "${BLUE} Applicando: $MIGRATION_NAME${NC}"
|
# Formato migrazioni: 001_description.sql, 002_another.sql, etc.
|
||||||
|
MIGRATIONS_TO_APPLY=()
|
||||||
|
|
||||||
if psql "$DATABASE_URL" -f "$migration" > /dev/null 2>&1; then
|
for migration_file in $(find "$MIGRATIONS_DIR" -name "[0-9][0-9][0-9]_*.sql" | sort); do
|
||||||
echo -e "${GREEN} ✅ $MIGRATION_NAME applicata${NC}"
|
MIGRATION_NAME=$(basename "$migration_file")
|
||||||
else
|
|
||||||
echo -e "${RED} ❌ Errore in $MIGRATION_NAME${NC}"
|
# Estrai numero versione dal nome file (001, 002, etc.)
|
||||||
psql "$DATABASE_URL" -f "$migration"
|
MIGRATION_VERSION=$(echo "$MIGRATION_NAME" | sed 's/^\([0-9]\{3\}\)_.*/\1/' | sed 's/^0*//')
|
||||||
exit 1
|
|
||||||
|
# Se versione vuota (000), salta
|
||||||
|
if [ -z "$MIGRATION_VERSION" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Se migrazione > versione corrente, aggiungila
|
||||||
|
if [ "$MIGRATION_VERSION" -gt "$CURRENT_VERSION" ]; then
|
||||||
|
MIGRATIONS_TO_APPLY+=("$migration_file:$MIGRATION_VERSION:$MIGRATION_NAME")
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
echo -e "${GREEN}✅ Tutte le migrazioni applicate con successo${NC}"
|
# =============================================================================
|
||||||
|
# STEP 4: Applica migrazioni mancanti
|
||||||
|
# =============================================================================
|
||||||
|
if [ ${#MIGRATIONS_TO_APPLY[@]} -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}✅ Database già aggiornato (nessuna migrazione da applicare)${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${BLUE}📋 Trovate ${#MIGRATIONS_TO_APPLY[@]} migrazioni da applicare${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
for migration_info in "${MIGRATIONS_TO_APPLY[@]}"; do
|
||||||
|
IFS=':' read -r migration_file migration_version migration_name <<< "$migration_info"
|
||||||
|
|
||||||
|
echo -e "${BLUE}🔄 Applicando migrazione ${migration_version}: ${CYAN}${migration_name}${NC}"
|
||||||
|
|
||||||
|
# Applica migrazione
|
||||||
|
if psql "$DATABASE_URL" -f "$migration_file" -q 2>&1 | tee /tmp/migration_output.log | grep -qiE "error|fatal"; then
|
||||||
|
echo -e "${RED}❌ Errore in migrazione ${migration_version}${NC}"
|
||||||
|
cat /tmp/migration_output.log
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Aggiorna versione nel database
|
||||||
|
DESCRIPTION=$(head -n 5 "$migration_file" | grep -E "^--.*Migration" | sed 's/^--.*Migration [0-9]*: //' || echo "Migration $migration_version")
|
||||||
|
|
||||||
|
psql "$DATABASE_URL" -q << EOF
|
||||||
|
UPDATE schema_version
|
||||||
|
SET version = $migration_version,
|
||||||
|
applied_at = NOW(),
|
||||||
|
description = '$DESCRIPTION'
|
||||||
|
WHERE id = 1;
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo -e "${GREEN} ✅ Migrazione ${migration_version} applicata con successo${NC}"
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# STEP 5: Verifica versione finale
|
||||||
|
# =============================================================================
|
||||||
|
FINAL_VERSION=$(psql "$DATABASE_URL" -tAc "SELECT version FROM schema_version WHERE id = 1;")
|
||||||
|
echo -e "${GREEN}╔═══════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${GREEN}║ ✅ MIGRAZIONI COMPLETATE ║${NC}"
|
||||||
|
echo -e "${GREEN}╚═══════════════════════════════════════════════╝${NC}"
|
||||||
|
echo -e "${CYAN}📊 Versione database: ${YELLOW}${CURRENT_VERSION}${CYAN} → ${GREEN}${FINAL_VERSION}${NC}"
|
||||||
|
echo ""
|
||||||
|
|||||||
23
database-schema/migrations/000_init_schema_version.sql
Normal file
23
database-schema/migrations/000_init_schema_version.sql
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
-- ============================================================================
|
||||||
|
-- Migration 000: Initialize schema version tracking
|
||||||
|
-- ============================================================================
|
||||||
|
-- Crea tabella per tracciare versione schema database
|
||||||
|
-- Previene re-esecuzione di migrazioni già applicate
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
-- Crea tabella schema_version se non esiste
|
||||||
|
CREATE TABLE IF NOT EXISTS schema_version (
|
||||||
|
id INTEGER PRIMARY KEY DEFAULT 1,
|
||||||
|
version INTEGER NOT NULL DEFAULT 0,
|
||||||
|
applied_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
|
description TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Inserisci versione iniziale (solo se tabella vuota)
|
||||||
|
INSERT INTO schema_version (id, version, description)
|
||||||
|
SELECT 1, 0, 'Initial schema version tracking'
|
||||||
|
WHERE NOT EXISTS (SELECT 1 FROM schema_version WHERE id = 1);
|
||||||
|
|
||||||
|
-- Constraint: solo 1 riga ammessa
|
||||||
|
ALTER TABLE schema_version ADD CONSTRAINT schema_version_single_row
|
||||||
|
CHECK (id = 1) NOT VALID;
|
||||||
18
database-schema/migrations/002_example_add_index.sql
Normal file
18
database-schema/migrations/002_example_add_index.sql
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
-- ============================================================================
|
||||||
|
-- Migration 002: Add performance indexes
|
||||||
|
-- ============================================================================
|
||||||
|
-- Descrizione: Aggiunge indici per migliorare performance query detections
|
||||||
|
-- Data: 2025-11-22
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
-- Indice su blocked per filtrare IP bloccati
|
||||||
|
CREATE INDEX IF NOT EXISTS detections_blocked_idx
|
||||||
|
ON detections(blocked);
|
||||||
|
|
||||||
|
-- Indice composto per query "IP bloccati recenti"
|
||||||
|
CREATE INDEX IF NOT EXISTS detections_blocked_detected_idx
|
||||||
|
ON detections(blocked, detected_at)
|
||||||
|
WHERE blocked = true;
|
||||||
|
|
||||||
|
-- Commento descrittivo
|
||||||
|
COMMENT ON INDEX detections_blocked_idx IS 'Index for filtering blocked IPs';
|
||||||
16
replit.md
16
replit.md
@ -50,6 +50,22 @@ The IDS features a React-based frontend for real-time monitoring, detection visu
|
|||||||
- **pg (Node.js driver)**: Standard PostgreSQL driver for Node.js (used in AlmaLinux environment).
|
- **pg (Node.js driver)**: Standard PostgreSQL driver for Node.js (used in AlmaLinux environment).
|
||||||
- **psycopg2**: PostgreSQL adapter for Python.
|
- **psycopg2**: PostgreSQL adapter for Python.
|
||||||
|
|
||||||
|
## Recent Updates (Novembre 2025)
|
||||||
|
|
||||||
|
### 🚀 Database Versioning System (22 Nov 2025 - 10:00)
|
||||||
|
- **Feature**: Sistema intelligente di versioning per migrazioni database
|
||||||
|
- **Problema risolto**: `update_from_git.sh` rieseguiva tutte le migrazioni SQL ad ogni update (lento)
|
||||||
|
- **Soluzione**:
|
||||||
|
- Tabella `schema_version` traccia versione corrente database
|
||||||
|
- Migrazioni SQL numerate sequenzialmente (001, 002, 003, etc.)
|
||||||
|
- Script `apply_migrations.sh` applica solo migrazioni mancanti
|
||||||
|
- Integrato in workflow update automatico
|
||||||
|
- **Benefici**:
|
||||||
|
- ⚡ Update 10x più veloce (salta migrazioni già applicate)
|
||||||
|
- 🔒 Sicuro: previene re-esecuzione migrazioni
|
||||||
|
- 📊 Tracciabilità: storico migrazioni applicate
|
||||||
|
- **Documentazione**: `database-schema/README.md`
|
||||||
|
|
||||||
## Fix Recenti (Novembre 2025)
|
## Fix Recenti (Novembre 2025)
|
||||||
|
|
||||||
### 🚨 Database Full - Auto-Cleanup Fix (21 Nov 2025 - 18:00)
|
### 🚨 Database Full - Auto-Cleanup Fix (21 Nov 2025 - 18:00)
|
||||||
|
|||||||
@ -80,6 +80,14 @@ export const trainingHistory = pgTable("training_history", {
|
|||||||
trainedAt: timestamp("trained_at").defaultNow().notNull(),
|
trainedAt: timestamp("trained_at").defaultNow().notNull(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Schema version tracking for database migrations
|
||||||
|
export const schemaVersion = pgTable("schema_version", {
|
||||||
|
id: integer("id").primaryKey().default(1),
|
||||||
|
version: integer("version").notNull().default(0),
|
||||||
|
appliedAt: timestamp("applied_at").defaultNow().notNull(),
|
||||||
|
description: text("description"),
|
||||||
|
});
|
||||||
|
|
||||||
// Relations
|
// Relations
|
||||||
export const routersRelations = relations(routers, ({ many }) => ({
|
export const routersRelations = relations(routers, ({ many }) => ({
|
||||||
logs: many(networkLogs),
|
logs: many(networkLogs),
|
||||||
@ -114,6 +122,10 @@ export const insertTrainingHistorySchema = createInsertSchema(trainingHistory).o
|
|||||||
trainedAt: true,
|
trainedAt: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const insertSchemaVersionSchema = createInsertSchema(schemaVersion).omit({
|
||||||
|
appliedAt: true,
|
||||||
|
});
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
export type Router = typeof routers.$inferSelect;
|
export type Router = typeof routers.$inferSelect;
|
||||||
export type InsertRouter = z.infer<typeof insertRouterSchema>;
|
export type InsertRouter = z.infer<typeof insertRouterSchema>;
|
||||||
@ -129,3 +141,6 @@ export type InsertWhitelist = z.infer<typeof insertWhitelistSchema>;
|
|||||||
|
|
||||||
export type TrainingHistory = typeof trainingHistory.$inferSelect;
|
export type TrainingHistory = typeof trainingHistory.$inferSelect;
|
||||||
export type InsertTrainingHistory = z.infer<typeof insertTrainingHistorySchema>;
|
export type InsertTrainingHistory = z.infer<typeof insertTrainingHistorySchema>;
|
||||||
|
|
||||||
|
export type SchemaVersion = typeof schemaVersion.$inferSelect;
|
||||||
|
export type InsertSchemaVersion = z.infer<typeof insertSchemaVersionSchema>;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user