-- Migration 018: Centralized Configuration Management System -- PostgreSQL NOTIFY/LISTEN hot-reload, validation, and audit support -- Main configuration settings table CREATE TABLE IF NOT EXISTS config_settings ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), service_scope VARCHAR(64) NOT NULL, config_key VARCHAR(128) NOT NULL, config_value JSONB NOT NULL, data_type VARCHAR(32) NOT NULL, validation_rules JSONB, description TEXT, is_active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_by VARCHAR(128), CONSTRAINT unique_service_key UNIQUE (service_scope, config_key) ); -- Index for faster lookups by service_scope and key CREATE INDEX IF NOT EXISTS idx_config_settings_service_key ON config_settings (service_scope, config_key); -- Index for active configurations CREATE INDEX IF NOT EXISTS idx_config_settings_active ON config_settings (is_active) WHERE is_active = TRUE; -- Configuration audit log table CREATE TABLE IF NOT EXISTS config_audit_log ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), action VARCHAR(32) NOT NULL, service_scope VARCHAR(64) NOT NULL, config_key VARCHAR(128) NOT NULL, old_value JSONB, new_value JSONB, changed_by VARCHAR(128) NOT NULL, change_timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Index for audit log queries CREATE INDEX IF NOT EXISTS idx_config_audit_log_timestamp ON config_audit_log (change_timestamp DESC); CREATE INDEX IF NOT EXISTS idx_config_audit_log_service_key ON config_audit_log (service_scope, config_key); -- Trigger for updated_at column CREATE OR REPLACE FUNCTION update_config_settings_updated_at() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER trigger_update_config_settings_updated_at BEFORE UPDATE ON config_settings FOR EACH ROW EXECUTE FUNCTION update_config_settings_updated_at(); -- Trigger for PostgreSQL NOTIFY on configuration changes CREATE OR REPLACE FUNCTION notify_config_change() RETURNS TRIGGER AS $$ DECLARE payload JSON; BEGIN -- Build notification payload payload := json_build_object( 'service_scope', NEW.service_scope, 'config_key', NEW.config_key, 'action', TG_OP ); -- Global notification for all services PERFORM pg_notify('config_updates_global', payload::text); -- Service-specific notification PERFORM pg_notify('config_updates_' || NEW.service_scope, json_build_object('config_key', NEW.config_key, 'action', TG_OP)::text); RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER trigger_notify_config_change AFTER INSERT OR UPDATE ON config_settings FOR EACH ROW EXECUTE FUNCTION notify_config_change(); -- Seed default configurations INSERT INTO config_settings (service_scope, config_key, config_value, data_type, validation_rules, description, updated_by) VALUES -- Global configurations ('global', 'system_timezone', '"UTC"', 'string', '{"regex": "^[A-Z]{3}$"}', 'System timezone', 'system'), ('global', 'max_concurrent_connections', '1000', 'integer', '{"min": 1, "max": 10000}', 'Maximum concurrent connections', 'system'), ('global', 'cache_ttl_seconds', '300', 'integer', '{"min": 1, "max": 3600}', 'Cache TTL in seconds', 'system'), -- Trading service configurations ('trading', 'max_position_size', '0.1', 'float', '{"min": 0.0, "max": 1.0}', 'Maximum position size as fraction of portfolio', 'system'), ('trading', 'risk_limit_daily', '0.02', 'float', '{"min": 0.0, "max": 0.1}', 'Daily risk limit as fraction', 'system'), ('trading', 'order_timeout_ms', '5000', 'integer', '{"min": 100, "max": 30000}', 'Order timeout in milliseconds', 'system'), -- Backtesting service configurations ('backtesting', 'default_commission_bps', '5.0', 'float', '{"min": 0.0, "max": 100.0}', 'Default commission in basis points', 'system'), ('backtesting', 'slippage_model', '"FIXED"', 'string', '{"enum": ["FIXED", "VOLUME_BASED", "SPREAD_BASED"]}', 'Slippage model type', 'system'), -- ML Training service configurations ('ml_training', 'batch_size', '64', 'integer', '{"min": 1, "max": 1024}', 'Training batch size', 'system'), ('ml_training', 'learning_rate', '0.001', 'float', '{"min": 0.00001, "max": 0.1}', 'Learning rate', 'system'), ('ml_training', 'max_epochs', '100', 'integer', '{"min": 1, "max": 1000}', 'Maximum training epochs', 'system') ON CONFLICT (service_scope, config_key) DO NOTHING; -- Grant permissions (adjust as needed for your security model) -- GRANT SELECT, INSERT, UPDATE ON config_settings TO api_gateway_role; -- GRANT SELECT, INSERT ON config_audit_log TO api_gateway_role;