Add database adapter system, production deployment configs, and new dashboard components
- Add PostgreSQL and SQLite database adapters with factory pattern - Add migration script for SQLite to PostgreSQL - Add production Dockerfiles and docker-compose configs - Add deployment documentation and scripts - Add BIA sync dashboard and matching service - Add data completeness configuration and components - Add new dashboard components (BusinessImportanceComparison, ComplexityDynamics, etc.) - Update various services and routes - Remove deprecated management-parameters.json and taxonomy files
This commit is contained in:
464
docs/DATABASE-RECOMMENDATION.md
Normal file
464
docs/DATABASE-RECOMMENDATION.md
Normal file
@@ -0,0 +1,464 @@
|
||||
# Database Engine Aanbeveling - Azure Productie
|
||||
|
||||
## Huidige Situatie
|
||||
|
||||
De applicatie gebruikt momenteel **SQLite** via `better-sqlite3`:
|
||||
- **cmdb-cache.db**: ~20MB - CMDB object cache
|
||||
- **classifications.db**: Classification history
|
||||
|
||||
## Aanbeveling: PostgreSQL
|
||||
|
||||
> **Belangrijk**: Azure Database for MariaDB wordt afgeschaft (retirement september 2025).
|
||||
> De keuze is daarom tussen **PostgreSQL** en **MySQL** (niet MariaDB).
|
||||
|
||||
### PostgreSQL vs MySQL Vergelijking
|
||||
|
||||
| Feature | PostgreSQL | MySQL (Azure) |
|
||||
|---------|------------|---------------|
|
||||
| **Azure Support** | ✅ Flexible Server | ✅ Flexible Server |
|
||||
| **Kosten (B1ms)** | ~€20-30/maand | ~€20-30/maand |
|
||||
| **JSON Support** | ✅ JSONB (superieur) | ✅ JSON (basis) |
|
||||
| **Performance** | ✅ Uitstekend | ✅ Goed |
|
||||
| **Concurrency** | ✅ MVCC (zeer goed) | ✅ Goed |
|
||||
| **SQL Standards** | ✅ Zeer compliant | ⚠️ Eigen dialect |
|
||||
| **Full-Text Search** | ✅ Ingebouwd | ⚠️ Basis |
|
||||
| **Community** | ✅ Groot & actief | ✅ Groot & actief |
|
||||
| **Development Tools** | ✅ Uitstekend | ✅ Goed |
|
||||
|
||||
**Voor jouw use case (JSON data, 20 gebruikers):**
|
||||
|
||||
✅ **PostgreSQL heeft voordeel:**
|
||||
- **JSONB**: Betere JSON performance en querying (gebruikt in huidige schema)
|
||||
- **MVCC**: Betere concurrency voor 20 gelijktijdige gebruikers
|
||||
- **SQL Standards**: Makkelijker migreren van SQLite
|
||||
- **Full-Text Search**: Ingebouwd (handig voor toekomstige zoekfuncties)
|
||||
|
||||
✅ **MySQL is ook goed:**
|
||||
- Vergelijkbare kosten
|
||||
- Goede performance
|
||||
- Veel gebruikt (bekende technologie)
|
||||
|
||||
**Conclusie**: Beide zijn goede keuzes. PostgreSQL heeft lichte voordelen voor JSON-heavy workloads en betere SQLite compatibiliteit.
|
||||
|
||||
### Waarom PostgreSQL?
|
||||
|
||||
✅ **Identieke Dev/Prod Stack**
|
||||
- Lokaal: PostgreSQL via Docker (gratis)
|
||||
- Azure: Azure Database for PostgreSQL Flexible Server
|
||||
- Zelfde database engine, zelfde SQL syntax
|
||||
|
||||
✅ **Azure Integratie**
|
||||
- Native ondersteuning in Azure
|
||||
- Managed service (geen server management)
|
||||
- Betaalbaar: Basic tier ~€20-30/maand voor 20 gebruikers
|
||||
|
||||
✅ **Performance**
|
||||
- Betere concurrency dan SQLite (20 gebruikers)
|
||||
- Connection pooling (nodig voor web apps)
|
||||
- Betere query performance bij groei
|
||||
|
||||
✅ **Features**
|
||||
- JSON support (gebruikt in huidige schema)
|
||||
- Transactions
|
||||
- Foreign keys
|
||||
- Full-text search (toekomstig)
|
||||
|
||||
✅ **Development Experience**
|
||||
- Docker setup identiek aan productie
|
||||
- Migraties mogelijk (Prisma, Knex, etc.)
|
||||
- Betere tooling
|
||||
|
||||
### Alternatief: SQLite Blijven
|
||||
|
||||
**Voordelen:**
|
||||
- ✅ Geen migratie nodig
|
||||
- ✅ Werkt in Azure App Service (file storage)
|
||||
- ✅ Gratis
|
||||
- ✅ Eenvoudig
|
||||
|
||||
**Nadelen:**
|
||||
- ❌ Beperkte concurrency (kan problemen geven met 20 gebruikers)
|
||||
- ❌ Geen connection pooling
|
||||
- ❌ File-based (moeilijker backup/restore)
|
||||
- ❌ Beperkte query performance bij groei
|
||||
|
||||
**Conclusie**: SQLite kan werken voor 20 gebruikers, maar PostgreSQL is beter voor productie.
|
||||
|
||||
---
|
||||
|
||||
## Migratie naar PostgreSQL
|
||||
|
||||
### Stappenplan
|
||||
|
||||
#### 1. Database Abstraction Layer
|
||||
|
||||
Maak een database abstraction layer zodat we kunnen wisselen tussen SQLite (dev) en PostgreSQL (prod):
|
||||
|
||||
```typescript
|
||||
// backend/src/services/database/interface.ts
|
||||
export interface DatabaseAdapter {
|
||||
query(sql: string, params?: any[]): Promise<any[]>;
|
||||
execute(sql: string, params?: any[]): Promise<void>;
|
||||
transaction<T>(callback: (db: DatabaseAdapter) => Promise<T>): Promise<T>;
|
||||
close(): Promise<void>;
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. PostgreSQL Adapter
|
||||
|
||||
```typescript
|
||||
// backend/src/services/database/postgresAdapter.ts
|
||||
import { Pool } from 'pg';
|
||||
|
||||
export class PostgresAdapter implements DatabaseAdapter {
|
||||
private pool: Pool;
|
||||
|
||||
constructor(connectionString: string) {
|
||||
this.pool = new Pool({ connectionString });
|
||||
}
|
||||
|
||||
async query(sql: string, params?: any[]): Promise<any[]> {
|
||||
const result = await this.pool.query(sql, params);
|
||||
return result.rows;
|
||||
}
|
||||
|
||||
// ... implement other methods
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. SQLite Adapter (voor backward compatibility)
|
||||
|
||||
```typescript
|
||||
// backend/src/services/database/sqliteAdapter.ts
|
||||
import Database from 'better-sqlite3';
|
||||
|
||||
export class SqliteAdapter implements DatabaseAdapter {
|
||||
private db: Database.Database;
|
||||
|
||||
constructor(dbPath: string) {
|
||||
this.db = new Database(dbPath);
|
||||
}
|
||||
|
||||
async query(sql: string, params?: any[]): Promise<any[]> {
|
||||
const stmt = this.db.prepare(sql);
|
||||
return stmt.all(...(params || [])) as any[];
|
||||
}
|
||||
|
||||
// ... implement other methods
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. Schema Migratie
|
||||
|
||||
**SQLite → PostgreSQL verschillen:**
|
||||
- `INTEGER PRIMARY KEY AUTOINCREMENT` → `SERIAL PRIMARY KEY`
|
||||
- `TEXT` → `TEXT` of `VARCHAR`
|
||||
- `JSON` → `JSONB` (beter in PostgreSQL)
|
||||
- `ON CONFLICT` → `ON CONFLICT` (werkt in beide)
|
||||
|
||||
**SQLite → MySQL verschillen:**
|
||||
- `INTEGER PRIMARY KEY AUTOINCREMENT` → `INT AUTO_INCREMENT PRIMARY KEY`
|
||||
- `TEXT` → `TEXT` of `VARCHAR(255)`
|
||||
- `JSON` → `JSON` (basis support)
|
||||
- `ON CONFLICT` → `ON DUPLICATE KEY UPDATE` (andere syntax)
|
||||
|
||||
---
|
||||
|
||||
## Azure Setup
|
||||
|
||||
### Optie 1: Azure Database for PostgreSQL Flexible Server
|
||||
|
||||
**Basic Tier (aanbevolen voor 20 gebruikers):**
|
||||
- **Burstable B1ms**: 1 vCore, 2GB RAM
|
||||
- **Storage**: 32GB (meer dan genoeg voor 20MB database)
|
||||
- **Kosten**: ~€20-30/maand
|
||||
- **Backup**: 7 dagen retention (gratis)
|
||||
|
||||
**Configuratie:**
|
||||
```bash
|
||||
# Azure CLI
|
||||
az postgres flexible-server create \
|
||||
--resource-group rg-cmdb-gui \
|
||||
--name psql-cmdb-gui \
|
||||
--location westeurope \
|
||||
--admin-user cmdbadmin \
|
||||
--admin-password <secure-password> \
|
||||
--sku-name Standard_B1ms \
|
||||
--tier Burstable \
|
||||
--storage-size 32 \
|
||||
--version 15
|
||||
```
|
||||
|
||||
**Connection String:**
|
||||
```
|
||||
postgresql://cmdbadmin:<password>@psql-cmdb-gui.postgres.database.azure.com:5432/cmdb?sslmode=require
|
||||
```
|
||||
|
||||
### Optie 2: Azure Database for MySQL Flexible Server
|
||||
|
||||
**Basic Tier (aanbevolen voor 20 gebruikers):**
|
||||
- **Burstable B1ms**: 1 vCore, 2GB RAM
|
||||
- **Storage**: 32GB (meer dan genoeg voor 20MB database)
|
||||
- **Kosten**: ~€20-30/maand
|
||||
- **Backup**: 7 dagen retention (gratis)
|
||||
|
||||
**Configuratie:**
|
||||
```bash
|
||||
# Azure CLI
|
||||
az mysql flexible-server create \
|
||||
--resource-group rg-cmdb-gui \
|
||||
--name mysql-cmdb-gui \
|
||||
--location westeurope \
|
||||
--admin-user cmdbadmin \
|
||||
--admin-password <secure-password> \
|
||||
--sku-name Standard_B1ms \
|
||||
--tier Burstable \
|
||||
--storage-size 32 \
|
||||
--version 8.0.21
|
||||
```
|
||||
|
||||
**Connection String:**
|
||||
```
|
||||
mysql://cmdbadmin:<password>@mysql-cmdb-gui.mysql.database.azure.com:3306/cmdb?ssl-mode=REQUIRED
|
||||
```
|
||||
|
||||
**MySQL vs PostgreSQL voor jouw schema:**
|
||||
- **JSON**: MySQL heeft JSON type, maar PostgreSQL JSONB is sneller voor queries
|
||||
- **AUTOINCREMENT**: MySQL gebruikt `AUTO_INCREMENT`, PostgreSQL gebruikt `SERIAL` (beide werken)
|
||||
- **ON CONFLICT**: MySQL gebruikt `ON DUPLICATE KEY UPDATE`, PostgreSQL gebruikt `ON CONFLICT` (beide werken)
|
||||
|
||||
---
|
||||
|
||||
## Local Development Setup
|
||||
|
||||
### Optie 1: Docker Compose voor PostgreSQL
|
||||
|
||||
Voeg toe aan `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
environment:
|
||||
POSTGRES_DB: cmdb
|
||||
POSTGRES_USER: cmdb
|
||||
POSTGRES_PASSWORD: cmdb-dev
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U cmdb"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
```
|
||||
|
||||
### Optie 2: Docker Compose voor MySQL
|
||||
|
||||
Voeg toe aan `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
environment:
|
||||
MYSQL_DATABASE: cmdb
|
||||
MYSQL_USER: cmdb
|
||||
MYSQL_PASSWORD: cmdb-dev
|
||||
MYSQL_ROOT_PASSWORD: root-dev
|
||||
ports:
|
||||
- "3306:3306"
|
||||
volumes:
|
||||
- mysql_data:/var/lib/mysql
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
mysql_data:
|
||||
```
|
||||
|
||||
**Environment variabelen (lokaal - PostgreSQL):**
|
||||
```bash
|
||||
# .env.local
|
||||
DATABASE_URL=postgresql://cmdb:cmdb-dev@localhost:5432/cmdb
|
||||
# of
|
||||
DATABASE_TYPE=postgres
|
||||
DATABASE_HOST=localhost
|
||||
DATABASE_PORT=5432
|
||||
DATABASE_NAME=cmdb
|
||||
DATABASE_USER=cmdb
|
||||
DATABASE_PASSWORD=cmdb-dev
|
||||
```
|
||||
|
||||
**Environment variabelen (Azure):**
|
||||
```bash
|
||||
# Azure App Service Configuration
|
||||
DATABASE_TYPE=postgres
|
||||
DATABASE_HOST=psql-cmdb-gui.postgres.database.azure.com
|
||||
DATABASE_PORT=5432
|
||||
DATABASE_NAME=cmdb
|
||||
DATABASE_USER=cmdbadmin
|
||||
DATABASE_PASSWORD=<from-key-vault>
|
||||
DATABASE_SSL=true
|
||||
```
|
||||
|
||||
**Environment variabelen (lokaal - MySQL):**
|
||||
```bash
|
||||
# .env.local
|
||||
DATABASE_URL=mysql://cmdb:cmdb-dev@localhost:3306/cmdb
|
||||
# of
|
||||
DATABASE_TYPE=mysql
|
||||
DATABASE_HOST=localhost
|
||||
DATABASE_PORT=3306
|
||||
DATABASE_NAME=cmdb
|
||||
DATABASE_USER=cmdb
|
||||
DATABASE_PASSWORD=cmdb-dev
|
||||
```
|
||||
|
||||
**Environment variabelen (Azure - MySQL):**
|
||||
```bash
|
||||
# Azure App Service Configuration
|
||||
DATABASE_TYPE=mysql
|
||||
DATABASE_HOST=mysql-cmdb-gui.mysql.database.azure.com
|
||||
DATABASE_PORT=3306
|
||||
DATABASE_NAME=cmdb
|
||||
DATABASE_USER=cmdbadmin
|
||||
DATABASE_PASSWORD=<from-key-vault>
|
||||
DATABASE_SSL=true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Kosten Vergelijking
|
||||
|
||||
| Optie | Lokaal | Azure (maandelijks) | Totaal |
|
||||
|-------|--------|---------------------|--------|
|
||||
| **PostgreSQL** | Gratis (Docker) | €20-30 | €20-30 |
|
||||
| **MySQL** | Gratis (Docker) | €20-30 | €20-30 |
|
||||
| **SQLite** | Gratis | €0 (in App Service) | €0 |
|
||||
| **Azure SQL** | SQL Server Express | €50-100 | €50-100 |
|
||||
|
||||
**Aanbeveling**: PostgreSQL - beste balans tussen kosten, performance en identieke stack.
|
||||
MySQL is ook een goede keuze met vergelijkbare kosten en performance.
|
||||
|
||||
---
|
||||
|
||||
## Migratie Script
|
||||
|
||||
### SQLite naar PostgreSQL Converter
|
||||
|
||||
```typescript
|
||||
// scripts/migrate-sqlite-to-postgres.ts
|
||||
import Database from 'better-sqlite3';
|
||||
import { Pool } from 'pg';
|
||||
|
||||
async function migrate() {
|
||||
// Connect to SQLite
|
||||
const sqlite = new Database('./data/cmdb-cache.db');
|
||||
|
||||
// Connect to PostgreSQL
|
||||
const pg = new Pool({
|
||||
connectionString: process.env.DATABASE_URL
|
||||
});
|
||||
|
||||
// Migrate cached_objects
|
||||
const objects = sqlite.prepare('SELECT * FROM cached_objects').all();
|
||||
for (const obj of objects) {
|
||||
await pg.query(
|
||||
`INSERT INTO cached_objects (id, object_key, object_type, label, data, jira_updated_at, jira_created_at, cached_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
ON CONFLICT (id) DO NOTHING`,
|
||||
[obj.id, obj.object_key, obj.object_type, obj.label, obj.data, obj.jira_updated_at, obj.jira_created_at, obj.cached_at]
|
||||
);
|
||||
}
|
||||
|
||||
// Migrate relations, metadata, etc.
|
||||
// ...
|
||||
|
||||
sqlite.close();
|
||||
await pg.end();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementatie Plan
|
||||
|
||||
### Fase 1: Database Abstraction (1-2 dagen)
|
||||
1. Maak `DatabaseAdapter` interface
|
||||
2. Implementeer `PostgresAdapter` en `SqliteAdapter`
|
||||
3. Update `CacheStore` en `DatabaseService` om adapter te gebruiken
|
||||
|
||||
### Fase 2: Local PostgreSQL Setup (0.5 dag)
|
||||
1. Voeg PostgreSQL toe aan docker-compose.yml
|
||||
2. Test lokaal met PostgreSQL
|
||||
3. Update environment configuratie
|
||||
|
||||
### Fase 3: Schema Migratie (1 dag)
|
||||
1. Converteer SQLite schema naar PostgreSQL
|
||||
2. Maak migratie script
|
||||
3. Test migratie lokaal
|
||||
|
||||
### Fase 4: Azure Setup (1 dag)
|
||||
1. Maak Azure Database for PostgreSQL
|
||||
2. Configureer connection string in Key Vault
|
||||
3. Test connectiviteit
|
||||
|
||||
### Fase 5: Productie Migratie (0.5 dag)
|
||||
1. Migreer data van SQLite naar PostgreSQL
|
||||
2. Update App Service configuratie
|
||||
3. Test in productie
|
||||
|
||||
**Totaal**: ~3-4 dagen werk
|
||||
|
||||
---
|
||||
|
||||
## Aanbeveling
|
||||
|
||||
### 🏆 PostgreSQL (Aanbevolen)
|
||||
|
||||
**Gebruik PostgreSQL** voor:
|
||||
- ✅ Identieke dev/prod stack
|
||||
- ✅ Betere JSON performance (JSONB)
|
||||
- ✅ Betere concurrency (MVCC)
|
||||
- ✅ Azure native ondersteuning
|
||||
- ✅ Toekomstbestendig
|
||||
- ✅ Betaalbaar (~€20-30/maand)
|
||||
- ✅ Makkelijker migratie van SQLite (SQL syntax)
|
||||
|
||||
### ✅ MySQL (Ook goed)
|
||||
|
||||
**MySQL is ook een goede keuze** als:
|
||||
- Je team meer ervaring heeft met MySQL
|
||||
- Je voorkeur geeft aan MySQL ecosystem
|
||||
- Vergelijkbare kosten en performance acceptabel zijn
|
||||
- Je JSON queries niet te complex zijn
|
||||
|
||||
**Nadelen t.o.v. PostgreSQL:**
|
||||
- ⚠️ Minder geavanceerde JSON support (geen JSONB)
|
||||
- ⚠️ Minder SQL standards compliant
|
||||
- ⚠️ Iets andere syntax voor conflicten
|
||||
|
||||
### 💰 SQLite (Minimale kosten)
|
||||
|
||||
**SQLite blijft optie** als:
|
||||
- Je snel moet deployen zonder migratie
|
||||
- Kosten kritiek zijn (€0 vs €20-30)
|
||||
- Je accepteert beperkingen (concurrency, performance)
|
||||
|
||||
**Conclusie**: Voor jouw use case (JSON data, 20 gebruikers) is **PostgreSQL de beste keuze**, maar MySQL is ook prima. Beide zijn veel beter dan SQLite voor productie.
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Beslissing**: PostgreSQL of SQLite blijven?
|
||||
2. **Als PostgreSQL**: Start met Fase 1 (Database Abstraction)
|
||||
3. **Als SQLite**: Documenteer beperkingen en overweeg toekomstige migratie
|
||||
Reference in New Issue
Block a user