- 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
465 lines
12 KiB
Markdown
465 lines
12 KiB
Markdown
# 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
|