143 lines
5.2 KiB
Python
143 lines
5.2 KiB
Python
"""Initial Hub schema with clients, instances, and usage samples.
|
|
|
|
Revision ID: 001
|
|
Revises:
|
|
Create Date: 2024-12-09
|
|
|
|
"""
|
|
from typing import Sequence, Union
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision: str = "001"
|
|
down_revision: Union[str, None] = None
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
# Create clients table
|
|
op.create_table(
|
|
"clients",
|
|
sa.Column("id", sa.UUID(), nullable=False),
|
|
sa.Column("name", sa.String(length=255), nullable=False),
|
|
sa.Column("contact_email", sa.String(length=255), nullable=True),
|
|
sa.Column("billing_plan", sa.String(length=50), nullable=False, server_default="free"),
|
|
sa.Column("status", sa.String(length=50), nullable=False, server_default="active"),
|
|
sa.Column(
|
|
"created_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.text("now()"),
|
|
),
|
|
sa.Column(
|
|
"updated_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.text("now()"),
|
|
),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
|
|
# Create instances table
|
|
op.create_table(
|
|
"instances",
|
|
sa.Column("id", sa.UUID(), nullable=False),
|
|
sa.Column("client_id", sa.UUID(), nullable=False),
|
|
sa.Column("instance_id", sa.String(length=255), nullable=False),
|
|
# Licensing
|
|
sa.Column("license_key_hash", sa.String(length=64), nullable=False),
|
|
sa.Column("license_key_prefix", sa.String(length=12), nullable=False),
|
|
sa.Column("license_status", sa.String(length=50), nullable=False, server_default="active"),
|
|
sa.Column("license_issued_at", sa.DateTime(timezone=True), nullable=False),
|
|
sa.Column("license_expires_at", sa.DateTime(timezone=True), nullable=True),
|
|
# Activation state
|
|
sa.Column("activated_at", sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column("last_activation_at", sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column("activation_count", sa.Integer(), nullable=False, server_default="0"),
|
|
# Telemetry
|
|
sa.Column("hub_api_key_hash", sa.String(length=64), nullable=True),
|
|
# Metadata
|
|
sa.Column("region", sa.String(length=50), nullable=True),
|
|
sa.Column("version", sa.String(length=50), nullable=True),
|
|
sa.Column("last_seen_at", sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column("status", sa.String(length=50), nullable=False, server_default="pending"),
|
|
# Timestamps
|
|
sa.Column(
|
|
"created_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.text("now()"),
|
|
),
|
|
sa.Column(
|
|
"updated_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.text("now()"),
|
|
),
|
|
sa.ForeignKeyConstraint(
|
|
["client_id"],
|
|
["clients.id"],
|
|
ondelete="CASCADE",
|
|
),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
op.create_index(
|
|
op.f("ix_instances_instance_id"),
|
|
"instances",
|
|
["instance_id"],
|
|
unique=True,
|
|
)
|
|
|
|
# Create usage_samples table
|
|
op.create_table(
|
|
"usage_samples",
|
|
sa.Column("id", sa.UUID(), nullable=False),
|
|
sa.Column("instance_id", sa.UUID(), nullable=False),
|
|
# Time window
|
|
sa.Column("window_start", sa.DateTime(timezone=True), nullable=False),
|
|
sa.Column("window_end", sa.DateTime(timezone=True), nullable=False),
|
|
sa.Column("window_type", sa.String(length=20), nullable=False),
|
|
# Tool (ONLY name)
|
|
sa.Column("tool_name", sa.String(length=255), nullable=False),
|
|
# Counts
|
|
sa.Column("call_count", sa.Integer(), nullable=False, server_default="0"),
|
|
sa.Column("success_count", sa.Integer(), nullable=False, server_default="0"),
|
|
sa.Column("error_count", sa.Integer(), nullable=False, server_default="0"),
|
|
sa.Column("rate_limited_count", sa.Integer(), nullable=False, server_default="0"),
|
|
# Duration stats
|
|
sa.Column("total_duration_ms", sa.Integer(), nullable=False, server_default="0"),
|
|
sa.Column("min_duration_ms", sa.Integer(), nullable=False, server_default="0"),
|
|
sa.Column("max_duration_ms", sa.Integer(), nullable=False, server_default="0"),
|
|
sa.ForeignKeyConstraint(
|
|
["instance_id"],
|
|
["instances.id"],
|
|
ondelete="CASCADE",
|
|
),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
op.create_index(
|
|
op.f("ix_usage_samples_instance_id"),
|
|
"usage_samples",
|
|
["instance_id"],
|
|
unique=False,
|
|
)
|
|
op.create_index(
|
|
op.f("ix_usage_samples_tool_name"),
|
|
"usage_samples",
|
|
["tool_name"],
|
|
unique=False,
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_index(op.f("ix_usage_samples_tool_name"), table_name="usage_samples")
|
|
op.drop_index(op.f("ix_usage_samples_instance_id"), table_name="usage_samples")
|
|
op.drop_table("usage_samples")
|
|
op.drop_index(op.f("ix_instances_instance_id"), table_name="instances")
|
|
op.drop_table("instances")
|
|
op.drop_table("clients")
|