Files
computer/supabase/schema_analytics.sql
zeekay 6d6cdb2483 feat: Extract zoo.computer from monorepo
Extracted from zoo monorepo for independent deployment.

Domain: computer.zoo.ngo
Deployment: GitHub Pages (GitHub Actions)
App Directory: computer
2025-11-02 10:41:38 -08:00

115 lines
3.5 KiB
PL/PgSQL

-- Usage Records Table for Analytics
CREATE TABLE IF NOT EXISTS usage_records (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
reservation_id UUID,
gpu_type VARCHAR(100) NOT NULL,
hours_used DECIMAL(10, 2) NOT NULL,
compute_units DECIMAL(10, 2) NOT NULL,
cost_usd DECIMAL(10, 2) NOT NULL,
timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(),
metadata JSONB,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Indexes for performance
CREATE INDEX IF NOT EXISTS idx_usage_records_user_id ON usage_records(user_id);
CREATE INDEX IF NOT EXISTS idx_usage_records_timestamp ON usage_records(timestamp);
CREATE INDEX IF NOT EXISTS idx_usage_records_user_timestamp ON usage_records(user_id, timestamp DESC);
CREATE INDEX IF NOT EXISTS idx_usage_records_gpu_type ON usage_records(gpu_type);
-- Enable Row Level Security
ALTER TABLE usage_records ENABLE ROW LEVEL SECURITY;
-- Policies for usage_records
CREATE POLICY "Users can view their own usage records" ON usage_records
FOR SELECT
USING (auth.uid() = user_id);
CREATE POLICY "Service role can insert usage records" ON usage_records
FOR INSERT
WITH CHECK (true);
CREATE POLICY "Service role can update usage records" ON usage_records
FOR UPDATE
USING (true);
-- Function to get usage summary for a user
CREATE OR REPLACE FUNCTION get_user_usage_summary(p_user_id UUID)
RETURNS TABLE (
total_hours DECIMAL,
total_cost DECIMAL,
total_compute_units DECIMAL,
gpu_type VARCHAR,
gpu_hours DECIMAL,
gpu_cost DECIMAL
) AS $$
BEGIN
RETURN QUERY
WITH summary AS (
SELECT
SUM(hours_used) as total_hours,
SUM(cost_usd) as total_cost,
SUM(compute_units) as total_compute_units
FROM usage_records
WHERE user_id = p_user_id
),
by_gpu AS (
SELECT
gpu_type,
SUM(hours_used) as gpu_hours,
SUM(cost_usd) as gpu_cost
FROM usage_records
WHERE user_id = p_user_id
GROUP BY gpu_type
)
SELECT
s.total_hours,
s.total_cost,
s.total_compute_units,
g.gpu_type,
g.gpu_hours,
g.gpu_cost
FROM summary s
CROSS JOIN by_gpu g;
END;
$$ LANGUAGE plpgsql;
-- Function to get monthly spending
CREATE OR REPLACE FUNCTION get_monthly_spending(p_user_id UUID, p_months INTEGER DEFAULT 6)
RETURNS TABLE (
month TEXT,
cost DECIMAL
) AS $$
BEGIN
RETURN QUERY
SELECT
TO_CHAR(DATE_TRUNC('month', timestamp), 'YYYY-MM') as month,
SUM(cost_usd) as cost
FROM usage_records
WHERE user_id = p_user_id
AND timestamp >= NOW() - INTERVAL '1 month' * p_months
GROUP BY DATE_TRUNC('month', timestamp)
ORDER BY month;
END;
$$ LANGUAGE plpgsql;
-- Sample data insertion (for testing)
-- This can be commented out in production
/*
INSERT INTO usage_records (user_id, gpu_type, hours_used, compute_units, cost_usd, timestamp, metadata)
SELECT
(SELECT id FROM auth.users LIMIT 1),
gpu_types.gpu,
ROUND((RANDOM() * 10 + 1)::numeric, 2),
ROUND((RANDOM() * 100 + 10)::numeric, 2),
ROUND((RANDOM() * 50 + 5)::numeric, 2),
NOW() - INTERVAL '1 day' * FLOOR(RANDOM() * 90),
jsonb_build_object(
'project', 'Project-' || FLOOR(RANDOM() * 5 + 1),
'region', (ARRAY['us-west', 'us-east', 'eu-west'])[FLOOR(RANDOM() * 3 + 1)]
)
FROM
(SELECT unnest(ARRAY['NVIDIA H100', 'NVIDIA A100', 'NVIDIA A6000', 'NVIDIA RTX 4090', 'NVIDIA V100']) as gpu) as gpu_types,
generate_series(1, 50) as n;
*/