Vorläufig fertiger server

Dieser Commit ist enthalten in:
2025-06-19 13:17:24 +02:00
Ursprung c30d974d57
Commit f82131b5f9
19 geänderte Dateien mit 1595 neuen und 583 gelöschten Zeilen

Datei anzeigen

@@ -0,0 +1,75 @@
# Database Migrations
## License Heartbeats Table Migration
### Overview
The `create_license_heartbeats_table.sql` migration creates a partitioned table for storing real-time license validation data. This table is essential for the Live Dashboard & Analytics functionality.
### Features
- Monthly partitioning for efficient data management
- Automatic creation of current and next month partitions
- Optimized indexes for performance
- Foreign key relationship with licenses table
### Running the Migration
#### Option 1: Using the Python Script
```bash
cd /path/to/v2_adminpanel
python apply_license_heartbeats_migration.py
```
#### Option 2: Manual SQL Execution
```bash
psql -h postgres -U postgres -d v2_adminpanel -f migrations/create_license_heartbeats_table.sql
```
#### Option 3: Docker Exec
```bash
docker exec -it v2_adminpanel_postgres psql -U postgres -d v2_adminpanel -f /migrations/create_license_heartbeats_table.sql
```
### Verification
After running the migration, verify the table was created:
```sql
-- Check if table exists
SELECT EXISTS (
SELECT 1
FROM information_schema.tables
WHERE table_name = 'license_heartbeats'
);
-- List all partitions
SELECT tablename
FROM pg_tables
WHERE tablename LIKE 'license_heartbeats_%'
ORDER BY tablename;
```
### Partition Management
The system automatically creates partitions as needed. To manually create future partitions:
```python
from utils.partition_helper import create_future_partitions
import psycopg2
conn = psycopg2.connect(...)
create_future_partitions(conn, 'license_heartbeats', months_ahead=6)
```
### Data Retention
Consider implementing a data retention policy to remove old partitions:
```sql
-- Drop partitions older than 3 months
DROP TABLE IF EXISTS license_heartbeats_2025_03;
```
### Troubleshooting
1. **Table already exists**: The migration is idempotent and will skip creation if the table exists.
2. **Permission denied**: Ensure the database user has CREATE privileges.
3. **Foreign key violation**: The licenses table must exist before running this migration.

Datei anzeigen

@@ -0,0 +1,58 @@
-- Migration: Add June 2025 partition for license_heartbeats table
-- This migration adds the missing partition for the current month (June 2025)
-- Check if the partition already exists before creating it
DO $$
BEGIN
-- Check if the June 2025 partition exists
IF NOT EXISTS (
SELECT 1
FROM pg_tables
WHERE tablename = 'license_heartbeats_2025_06'
) THEN
-- Create the June 2025 partition
EXECUTE 'CREATE TABLE license_heartbeats_2025_06 PARTITION OF license_heartbeats
FOR VALUES FROM (''2025-06-01'') TO (''2025-07-01'')';
RAISE NOTICE 'Created partition license_heartbeats_2025_06';
ELSE
RAISE NOTICE 'Partition license_heartbeats_2025_06 already exists';
END IF;
END $$;
-- Also create partitions for the next few months to avoid future issues
DO $$
DECLARE
partition_name text;
start_date date;
end_date date;
i integer;
BEGIN
-- Create partitions for the next 6 months
FOR i IN 0..6 LOOP
start_date := date_trunc('month', CURRENT_DATE + (i || ' months')::interval);
end_date := start_date + interval '1 month';
partition_name := 'license_heartbeats_' || to_char(start_date, 'YYYY_MM');
-- Check if partition already exists
IF NOT EXISTS (
SELECT 1
FROM pg_tables
WHERE tablename = partition_name
) THEN
EXECUTE format('CREATE TABLE %I PARTITION OF license_heartbeats FOR VALUES FROM (%L) TO (%L)',
partition_name, start_date, end_date);
RAISE NOTICE 'Created partition %', partition_name;
END IF;
END LOOP;
END $$;
-- Verify the partitions were created
SELECT
schemaname,
tablename,
tableowner
FROM pg_tables
WHERE tablename LIKE 'license_heartbeats_%'
ORDER BY tablename;

Datei anzeigen

@@ -0,0 +1,79 @@
-- Migration: Create license_heartbeats partitioned table
-- Date: 2025-06-19
-- Description: Creates the license_heartbeats table with monthly partitioning
-- Create the partitioned table
CREATE TABLE IF NOT EXISTS license_heartbeats (
id BIGSERIAL,
license_id INTEGER NOT NULL,
hardware_id VARCHAR(255) NOT NULL,
ip_address INET NOT NULL,
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
session_data JSONB,
PRIMARY KEY (id, timestamp),
FOREIGN KEY (license_id) REFERENCES licenses(id) ON DELETE CASCADE
) PARTITION BY RANGE (timestamp);
-- Create indexes for better query performance
CREATE INDEX IF NOT EXISTS idx_license_heartbeats_license_id_timestamp
ON license_heartbeats (license_id, timestamp DESC);
CREATE INDEX IF NOT EXISTS idx_license_heartbeats_timestamp
ON license_heartbeats (timestamp DESC);
CREATE INDEX IF NOT EXISTS idx_license_heartbeats_hardware_id
ON license_heartbeats (hardware_id);
CREATE INDEX IF NOT EXISTS idx_license_heartbeats_ip_address
ON license_heartbeats (ip_address);
-- Create partitions for current and next month
DO $$
DECLARE
current_year INTEGER;
current_month INTEGER;
next_year INTEGER;
next_month INTEGER;
partition_name TEXT;
start_date DATE;
end_date DATE;
BEGIN
-- Get current date info
current_year := EXTRACT(YEAR FROM CURRENT_DATE);
current_month := EXTRACT(MONTH FROM CURRENT_DATE);
-- Calculate next month
IF current_month = 12 THEN
next_year := current_year + 1;
next_month := 1;
ELSE
next_year := current_year;
next_month := current_month + 1;
END IF;
-- Create current month partition
partition_name := 'license_heartbeats_' || current_year || '_' || LPAD(current_month::TEXT, 2, '0');
start_date := DATE_TRUNC('month', CURRENT_DATE);
end_date := DATE_TRUNC('month', CURRENT_DATE) + INTERVAL '1 month';
EXECUTE format('CREATE TABLE IF NOT EXISTS %I PARTITION OF license_heartbeats FOR VALUES FROM (%L) TO (%L)',
partition_name, start_date, end_date);
-- Create next month partition
partition_name := 'license_heartbeats_' || next_year || '_' || LPAD(next_month::TEXT, 2, '0');
start_date := end_date;
end_date := start_date + INTERVAL '1 month';
EXECUTE format('CREATE TABLE IF NOT EXISTS %I PARTITION OF license_heartbeats FOR VALUES FROM (%L) TO (%L)',
partition_name, start_date, end_date);
RAISE NOTICE 'Created partitions for current and next month';
END $$;
-- Add comment to the table
COMMENT ON TABLE license_heartbeats IS 'Stores heartbeat data from license validations for real-time monitoring';
COMMENT ON COLUMN license_heartbeats.license_id IS 'Foreign key to licenses table';
COMMENT ON COLUMN license_heartbeats.hardware_id IS 'Hardware identifier of the device';
COMMENT ON COLUMN license_heartbeats.ip_address IS 'IP address from which the heartbeat was sent';
COMMENT ON COLUMN license_heartbeats.timestamp IS 'Timestamp of the heartbeat';
COMMENT ON COLUMN license_heartbeats.session_data IS 'Additional session data in JSON format';