-- Cluster pool allocation, health snapshots, and audit logs. ALTER TABLE clusters ADD COLUMN IF NOT EXISTS weight INTEGER NOT NULL DEFAULT 1, ADD COLUMN IF NOT EXISTS tags JSONB NOT NULL DEFAULT '[]'::jsonb, ADD COLUMN IF NOT EXISTS "healthStatus" VARCHAR NOT NULL DEFAULT 'unknown', ADD COLUMN IF NOT EXISTS "lastHealthCheckedAt" TIMESTAMPTZ, ADD COLUMN IF NOT EXISTS "healthMessage" VARCHAR, ADD COLUMN IF NOT EXISTS "availableResources" JSONB; ALTER TABLE cluster_pools ADD COLUMN IF NOT EXISTS "isDefault" BOOLEAN NOT NULL DEFAULT FALSE, ADD COLUMN IF NOT EXISTS priority INTEGER NOT NULL DEFAULT 100; CREATE INDEX IF NOT EXISTS idx_clusters_status_health ON clusters(status, "healthStatus"); CREATE INDEX IF NOT EXISTS idx_clusters_tags ON clusters USING GIN(tags); CREATE INDEX IF NOT EXISTS idx_cluster_pools_default_priority ON cluster_pools("isDefault", priority) WHERE "isActive" = TRUE; CREATE TABLE IF NOT EXISTS cluster_health ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), "clusterId" UUID NOT NULL REFERENCES clusters(id) ON DELETE CASCADE, status VARCHAR NOT NULL DEFAULT 'unknown', "readyNodes" INTEGER NOT NULL DEFAULT 0, "nodeCount" INTEGER NOT NULL DEFAULT 0, "cpuAllocatable" VARCHAR, "memoryAllocatable" VARCHAR, "podCount" INTEGER NOT NULL DEFAULT 0, "appCount" INTEGER NOT NULL DEFAULT 0, message VARCHAR, resources JSONB, "checkedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_cluster_health_cluster_checked ON cluster_health("clusterId", "checkedAt" DESC); CREATE TABLE IF NOT EXISTS cluster_allocation_logs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), "applicationId" UUID REFERENCES applications(id) ON DELETE SET NULL, "userId" UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, "poolId" UUID REFERENCES cluster_pools(id) ON DELETE SET NULL, "selectedClusterId" UUID REFERENCES clusters(id) ON DELETE SET NULL, strategy VARCHAR NOT NULL DEFAULT 'weighted-resource', "estimatedRequest" JSONB, "candidateScores" JSONB, "rejectionReasons" JSONB, status VARCHAR NOT NULL DEFAULT 'success', message VARCHAR, "createdAt" TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_cluster_allocation_logs_user_created ON cluster_allocation_logs("userId", "createdAt" DESC); CREATE INDEX IF NOT EXISTS idx_cluster_allocation_logs_app ON cluster_allocation_logs("applicationId"); CREATE INDEX IF NOT EXISTS idx_cluster_allocation_logs_cluster_created ON cluster_allocation_logs("selectedClusterId", "createdAt" DESC); ALTER TABLE applications ADD COLUMN IF NOT EXISTS "clusterId" UUID, ADD COLUMN IF NOT EXISTS "poolId" UUID; DO $$ BEGIN IF EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_name = 'applications' AND column_name = 'clusterId' AND data_type <> 'uuid' ) THEN ALTER TABLE applications ALTER COLUMN "clusterId" TYPE UUID USING NULLIF("clusterId", '')::uuid; END IF; IF EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_name = 'applications' AND column_name = 'poolId' AND data_type <> 'uuid' ) THEN ALTER TABLE applications ALTER COLUMN "poolId" TYPE UUID USING NULLIF("poolId", '')::uuid; END IF; END $$; DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'fk_applications_cluster' ) THEN ALTER TABLE applications ADD CONSTRAINT fk_applications_cluster FOREIGN KEY ("clusterId") REFERENCES clusters(id) ON DELETE SET NULL; END IF; IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'fk_applications_pool' ) THEN ALTER TABLE applications ADD CONSTRAINT fk_applications_pool FOREIGN KEY ("poolId") REFERENCES cluster_pools(id) ON DELETE SET NULL; END IF; END $$; CREATE INDEX IF NOT EXISTS idx_applications_cluster_id ON applications("clusterId"); CREATE INDEX IF NOT EXISTS idx_applications_pool_id ON applications("poolId");