first commit
This commit is contained in:
445
database_schema.sql
Normal file
445
database_schema.sql
Normal file
@@ -0,0 +1,445 @@
|
||||
-- Database Schema for Intelligent Planet Plan
|
||||
-- PostgreSQL 15+ with TimescaleDB
|
||||
-- Generated at: 2024-01-20
|
||||
|
||||
-- ============================================
|
||||
-- EXTENSIONS
|
||||
-- ============================================
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
CREATE EXTENSION IF NOT EXISTS "timescaledb";
|
||||
|
||||
-- ============================================
|
||||
-- ENUMS
|
||||
-- ============================================
|
||||
|
||||
CREATE TYPE user_role AS ENUM ('super_admin', 'admin', 'operator', 'viewer');
|
||||
CREATE TYPE datasource_priority AS ENUM ('P0', 'P1', 'P2');
|
||||
CREATE TYPE task_status AS ENUM ('pending', 'running', 'success', 'failed', 'cancelled');
|
||||
CREATE TYPE alert_severity AS ENUM ('critical', 'warning', 'info');
|
||||
CREATE TYPE alert_status AS ENUM ('active', 'acknowledged', 'resolved');
|
||||
CREATE TYPE data_module AS ENUM ('L1', 'L2', 'L3', 'L4');
|
||||
|
||||
-- ============================================
|
||||
-- USERS & AUTHENTICATION
|
||||
-- ============================================
|
||||
|
||||
CREATE TABLE users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username VARCHAR(50) NOT NULL UNIQUE,
|
||||
email VARCHAR(255) NOT NULL UNIQUE,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
role user_role NOT NULL DEFAULT 'viewer',
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
last_login_at TIMESTAMP WITH TIME ZONE,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_users_username ON users(username);
|
||||
CREATE INDEX idx_users_role ON users(role);
|
||||
CREATE INDEX idx_users_is_active ON users(is_active);
|
||||
|
||||
CREATE TABLE refresh_tokens (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
token VARCHAR(500) NOT NULL UNIQUE,
|
||||
expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
revoked_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_refresh_tokens_user ON refresh_tokens(user_id);
|
||||
CREATE INDEX idx_refresh_tokens_token ON refresh_tokens(token);
|
||||
CREATE INDEX idx_refresh_tokens_expires ON refresh_tokens(expires_at);
|
||||
|
||||
-- ============================================
|
||||
-- DATA SOURCES
|
||||
-- ============================================
|
||||
|
||||
CREATE TABLE data_sources (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
module data_module NOT NULL,
|
||||
priority datasource_priority NOT NULL DEFAULT 'P1',
|
||||
frequency_minutes INTEGER NOT NULL DEFAULT 60,
|
||||
collector_class VARCHAR(100) NOT NULL,
|
||||
config JSONB NOT NULL DEFAULT '{}',
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
last_run_at TIMESTAMP WITH TIME ZONE,
|
||||
last_status task_status,
|
||||
next_run_at TIMESTAMP WITH TIME ZONE,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_datasources_module ON data_sources(module);
|
||||
CREATE INDEX idx_datasources_priority ON data_sources(priority);
|
||||
CREATE INDEX idx_datasources_is_active ON data_sources(is_active);
|
||||
CREATE INDEX idx_datasources_next_run ON data_sources(next_run_at);
|
||||
|
||||
-- ============================================
|
||||
-- COLLECTION TASKS
|
||||
-- ============================================
|
||||
|
||||
CREATE TABLE collection_tasks (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
datasource_id INTEGER NOT NULL REFERENCES data_sources(id) ON DELETE CASCADE,
|
||||
status task_status NOT NULL DEFAULT 'pending',
|
||||
started_at TIMESTAMP WITH TIME ZONE,
|
||||
completed_at TIMESTAMP WITH TIME ZONE,
|
||||
records_processed INTEGER DEFAULT 0,
|
||||
error_message TEXT,
|
||||
traceback TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_tasks_datasource ON collection_tasks(datasource_id);
|
||||
CREATE INDEX idx_tasks_status ON collection_tasks(status);
|
||||
CREATE INDEX idx_tasks_created_at ON collection_tasks(created_at DESC);
|
||||
|
||||
-- Hypertable for time-series queries
|
||||
SELECT create_hypertable('collection_tasks', 'created_at');
|
||||
|
||||
-- ============================================
|
||||
-- GPU CLUSTERS (L1 - Hypertables)
|
||||
-- ============================================
|
||||
|
||||
CREATE TABLE gpu_clusters (
|
||||
time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
cluster_id VARCHAR(100) NOT NULL,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
country VARCHAR(100),
|
||||
city VARCHAR(100),
|
||||
latitude DOUBLE PRECISION,
|
||||
longitude DOUBLE PRECISION,
|
||||
organization VARCHAR(200),
|
||||
gpu_count INTEGER,
|
||||
gpu_type VARCHAR(100),
|
||||
total_flops DOUBLE PRECISION,
|
||||
rank INTEGER,
|
||||
source VARCHAR(50) NOT NULL
|
||||
);
|
||||
|
||||
SELECT create_hypertable('gpu_clusters', 'time');
|
||||
|
||||
CREATE INDEX idx_gpu_clusters_cluster_id ON gpu_clusters(cluster_id);
|
||||
CREATE INDEX idx_gpu_clusters_country ON gpu_clusters(country);
|
||||
CREATE INDEX idx_gpu_clusters_source ON gpu_clusters(source);
|
||||
CREATE INDEX idx_gpu_clusters_time ON gpu_clusters(time DESC);
|
||||
|
||||
-- Latest snapshot view
|
||||
CREATE VIEW gpu_clusters_latest AS
|
||||
SELECT DISTINCT ON (cluster_id) *
|
||||
FROM gpu_clusters
|
||||
ORDER BY cluster_id, time DESC;
|
||||
|
||||
-- ============================================
|
||||
-- MODEL ECOSYSTEM (L1)
|
||||
-- ============================================
|
||||
|
||||
CREATE TABLE model_ecosystem (
|
||||
time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
model_id VARCHAR(200) NOT NULL,
|
||||
model_name VARCHAR(200) NOT NULL,
|
||||
publisher VARCHAR(200),
|
||||
downloads INTEGER,
|
||||
likes INTEGER,
|
||||
stars INTEGER,
|
||||
license VARCHAR(100),
|
||||
size_bytes BIGINT,
|
||||
source VARCHAR(50) NOT NULL
|
||||
);
|
||||
|
||||
SELECT create_hypertable('model_ecosystem', 'time');
|
||||
|
||||
CREATE INDEX idx_models_model_id ON model_ecosystem(model_id);
|
||||
CREATE INDEX idx_models_source ON model_ecosystem(source);
|
||||
CREATE INDEX idx_models_time ON model_ecosystem(time DESC);
|
||||
|
||||
-- ============================================
|
||||
-- SUPERCOMPUTERS (L1)
|
||||
-- ============================================
|
||||
|
||||
CREATE TABLE supercomputers (
|
||||
time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
rank INTEGER NOT NULL,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
country VARCHAR(100),
|
||||
city VARCHAR(100),
|
||||
latitude DOUBLE PRECISION,
|
||||
longitude DOUBLE PRECISION,
|
||||
organization VARCHAR(200),
|
||||
rmax_tflops DOUBLE PRECISION,
|
||||
rpeak_tflops DOUBLE PRECISION,
|
||||
power_mw DOUBLE PRECISION,
|
||||
cpu_cores INTEGER,
|
||||
accelerator_cores INTEGER,
|
||||
memory_tb DOUBLE PRECISION,
|
||||
interconnect VARCHAR(100),
|
||||
os VARCHAR(100),
|
||||
source VARCHAR(50) NOT NULL
|
||||
);
|
||||
|
||||
SELECT create_hypertable('supercomputers', 'time');
|
||||
|
||||
CREATE INDEX idx_supercomputers_rank ON supercomputers(rank);
|
||||
CREATE INDEX idx_supercomputers_country ON supercomputers(country);
|
||||
CREATE INDEX idx_supercomputers_time ON supercomputers(time DESC);
|
||||
|
||||
-- ============================================
|
||||
-- SUBCABLE CABLES (L2)
|
||||
-- ============================================
|
||||
|
||||
CREATE TABLE submarine_cables (
|
||||
id SERIAL PRIMARY KEY,
|
||||
cable_id VARCHAR(100) NOT NULL UNIQUE,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
length_km INTEGER,
|
||||
owners JSONB DEFAULT '[]',
|
||||
capacity_tbps DOUBLE PRECISION,
|
||||
status VARCHAR(50) DEFAULT 'active',
|
||||
source VARCHAR(50) NOT NULL,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE cable_landing_points (
|
||||
id SERIAL PRIMARY KEY,
|
||||
cable_id VARCHAR(100) NOT NULL REFERENCES submarine_cables(cable_id) ON DELETE CASCADE,
|
||||
sequence_number INTEGER NOT NULL,
|
||||
country VARCHAR(100) NOT NULL,
|
||||
city VARCHAR(100),
|
||||
latitude DOUBLE PRECISION NOT NULL,
|
||||
longitude DOUBLE PRECISION NOT NULL,
|
||||
landing_type VARCHAR(50),
|
||||
UNIQUE(cable_id, sequence_number)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_cables_name ON submarine_cables(name);
|
||||
CREATE INDEX idx_cables_status ON submarine_cables(status);
|
||||
CREATE INDEX idx_landing_cable ON cable_landing_points(cable_id);
|
||||
|
||||
-- ============================================
|
||||
-- IXP NODES (L2)
|
||||
-- ============================================
|
||||
|
||||
CREATE TABLE ixp_nodes (
|
||||
id SERIAL PRIMARY KEY,
|
||||
ixp_id VARCHAR(100) NOT NULL UNIQUE,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
country VARCHAR(100),
|
||||
city VARCHAR(100),
|
||||
latitude DOUBLE PRECISION,
|
||||
longitude DOUBLE PRECISION,
|
||||
member_count INTEGER,
|
||||
traffic_tbps DOUBLE PRECISION,
|
||||
source VARCHAR(50) NOT NULL,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_ixp_country ON ixp_nodes(country);
|
||||
CREATE INDEX idx_ixp_source ON ixp_nodes(source);
|
||||
|
||||
-- ============================================
|
||||
-- CLOUD INFRASTRUCTURE (L1)
|
||||
-- ============================================
|
||||
|
||||
CREATE TABLE cloud_infrastructure (
|
||||
time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
provider VARCHAR(100) NOT NULL,
|
||||
region VARCHAR(100) NOT NULL,
|
||||
availability_zone VARCHAR(100),
|
||||
data_center_count INTEGER,
|
||||
total_capacity_mw DOUBLE PRECISION,
|
||||
source VARCHAR(50) NOT NULL
|
||||
);
|
||||
|
||||
SELECT create_hypertable('cloud_infrastructure', 'time');
|
||||
|
||||
CREATE INDEX idx_cloud_provider ON cloud_infrastructure(provider);
|
||||
CREATE INDEX idx_cloud_region ON cloud_infrastructure(region);
|
||||
CREATE INDEX idx_cloud_time ON cloud_infrastructure(time DESC);
|
||||
|
||||
-- ============================================
|
||||
-- ALERTS
|
||||
-- ============================================
|
||||
|
||||
CREATE TABLE alert_rules (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
description TEXT,
|
||||
datasource_id INTEGER REFERENCES data_sources(id) ON DELETE SET NULL,
|
||||
condition JSONB NOT NULL,
|
||||
severity alert_severity NOT NULL,
|
||||
notification_channels JSONB DEFAULT '[]',
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
cooldown_minutes INTEGER DEFAULT 30,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_alert_rules_active ON alert_rules(is_active);
|
||||
CREATE INDEX idx_alert_rules_severity ON alert_rules(severity);
|
||||
|
||||
CREATE TABLE alerts (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
rule_id INTEGER NOT NULL REFERENCES alert_rules(id),
|
||||
datasource_id INTEGER REFERENCES data_sources(id) ON DELETE SET NULL,
|
||||
severity alert_severity NOT NULL,
|
||||
status alert_status NOT NULL DEFAULT 'active',
|
||||
message TEXT NOT NULL,
|
||||
detail JSONB DEFAULT '{}',
|
||||
acknowledged_by INTEGER REFERENCES users(id),
|
||||
acknowledged_at TIMESTAMP WITH TIME ZONE,
|
||||
resolved_by INTEGER REFERENCES users(id),
|
||||
resolved_at TIMESTAMP WITH TIME ZONE,
|
||||
resolution_note TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
SELECT create_hypertable('alerts', 'created_at');
|
||||
|
||||
CREATE INDEX idx_alerts_status ON alerts(status);
|
||||
CREATE INDEX idx_alerts_severity ON alerts(severity);
|
||||
CREATE INDEX idx_alerts_datasource ON alerts(datasource_id);
|
||||
CREATE INDEX idx_alerts_created ON alerts(created_at DESC);
|
||||
|
||||
-- ============================================
|
||||
-- AUDIT LOGS
|
||||
-- ============================================
|
||||
|
||||
CREATE TABLE audit_logs (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
||||
action VARCHAR(100) NOT NULL,
|
||||
resource VARCHAR(100) NOT NULL,
|
||||
resource_id VARCHAR(100),
|
||||
detail JSONB DEFAULT '{}',
|
||||
ip_address INET,
|
||||
user_agent TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
SELECT create_hypertable('audit_logs', 'created_at');
|
||||
|
||||
CREATE INDEX idx_audit_user ON audit_logs(user_id);
|
||||
CREATE INDEX idx_audit_action ON audit_logs(action);
|
||||
CREATE INDEX idx_audit_resource ON audit_logs(resource);
|
||||
CREATE INDEX idx_audit_created ON audit_logs(created_at DESC);
|
||||
|
||||
-- ============================================
|
||||
-- SYSTEM CONFIGURATION
|
||||
-- ============================================
|
||||
|
||||
CREATE TABLE system_config (
|
||||
id SERIAL PRIMARY KEY,
|
||||
key VARCHAR(100) NOT NULL UNIQUE,
|
||||
value JSONB NOT NULL,
|
||||
description TEXT,
|
||||
is_sensitive BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Default configurations
|
||||
INSERT INTO system_config (key, value, description) VALUES
|
||||
('data_retention_days', '30', 'Number of days to retain time-series data'),
|
||||
('refresh_interval', '300', 'Default WebSocket refresh interval in seconds'),
|
||||
('timezone', 'Asia/Shanghai', 'System timezone'),
|
||||
('max_concurrent_tasks', '5', 'Maximum concurrent collection tasks'),
|
||||
('api_rate_limit', '100', 'API requests per minute per user'),
|
||||
('jwt_access_token_expire', '900', 'JWT access token expiration in seconds'),
|
||||
('jwt_refresh_token_expire', '604800', 'JWT refresh token expiration in seconds');
|
||||
|
||||
-- ============================================
|
||||
-- FUNCTIONS & TRIGGERS
|
||||
-- ============================================
|
||||
|
||||
-- Updated_at trigger function
|
||||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- Apply updated_at trigger to all tables with updated_at column
|
||||
CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON users
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
CREATE TRIGGER update_datasources_updated_at BEFORE UPDATE ON data_sources
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
CREATE TRIGGER update_alert_rules_updated_at BEFORE UPDATE ON alert_rules
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
CREATE TRIGGER update_system_config_updated_at BEFORE UPDATE ON system_config
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- ============================================
|
||||
-- VIEWS
|
||||
-- ============================================
|
||||
|
||||
-- Data source overview
|
||||
CREATE VIEW datasource_overview AS
|
||||
SELECT
|
||||
ds.id,
|
||||
ds.name,
|
||||
ds.module,
|
||||
ds.priority,
|
||||
ds.frequency_minutes,
|
||||
ds.is_active,
|
||||
ds.last_run_at,
|
||||
ds.last_status,
|
||||
COUNT(ct.id) FILTER (WHERE ct.status = 'success') as total_success,
|
||||
COUNT(ct.id) FILTER (WHERE ct.status = 'failed') as total_failed,
|
||||
MAX(ct.created_at) as last_task_at
|
||||
FROM data_sources ds
|
||||
LEFT JOIN collection_tasks ct ON ct.datasource_id = ds.id
|
||||
GROUP BY ds.id;
|
||||
|
||||
-- System health view
|
||||
CREATE VIEW system_health AS
|
||||
SELECT
|
||||
NOW() as check_time,
|
||||
(SELECT COUNT(*) FROM data_sources WHERE is_active = true) as active_datasources,
|
||||
(SELECT COUNT(*) FROM collection_tasks WHERE status = 'running') as running_tasks,
|
||||
(SELECT COUNT(*) FROM alerts WHERE status = 'active') as active_alerts,
|
||||
(SELECT COUNT(*) FROM users WHERE is_active = true) as active_users;
|
||||
|
||||
-- ============================================
|
||||
-- DATA RETENTION POLICY
|
||||
-- ============================================
|
||||
|
||||
-- Example: Add retention policy for hypertables
|
||||
-- SELECT add_retention_policy('gpu_clusters', INTERVAL '30 days');
|
||||
-- SELECT add_retention_policy('collection_tasks', INTERVAL '90 days');
|
||||
-- SELECT add_retention_policy('audit_logs', INTERVAL '180 days');
|
||||
|
||||
-- ============================================
|
||||
-- ROW LEVEL SECURITY (RLS)
|
||||
-- ============================================
|
||||
|
||||
-- Enable RLS for sensitive tables
|
||||
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE audit_logs ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- RLS policies
|
||||
CREATE POLICY "Admins can view all users" ON users
|
||||
FOR SELECT USING (current_setting('app.current_role', true) IN ('super_admin', 'admin'));
|
||||
|
||||
CREATE POLICY "Users can view own data" ON users
|
||||
FOR SELECT USING (auth.uid() = id);
|
||||
|
||||
-- ============================================
|
||||
-- COMMENTS
|
||||
-- ============================================
|
||||
|
||||
COMMENT ON TABLE gpu_clusters IS 'L1: Global AI GPU cluster distribution data';
|
||||
COMMENT ON TABLE submarine_cables IS 'L2: Submarine cable infrastructure and landing points';
|
||||
COMMENT ON TABLE ixp_nodes IS 'L2: Internet Exchange Point nodes and connectivity';
|
||||
COMMENT ON TABLE model_ecosystem IS 'L1: AI model download statistics and ecosystem data';
|
||||
COMMENT ON TABLE cloud_infrastructure IS 'L1: Cloud data center capacity and distribution';
|
||||
Reference in New Issue
Block a user