Add operational schema and identity roles
This commit is contained in:
1 parent
f5af75f305
commit
f181482463
11 files changed
+2068
-284
No files matched your search
@@ -0,0 +1,478 @@
|
||||
"""capture the operational schema baseline
|
||||
|
||||
Revision ID: 0006_operational_schema_baseline
|
||||
Revises: 0005_miner_inventory
|
||||
Create Date: 2026-07-27
|
||||
|
||||
This migration adopts tables that older MinerOps builds created at runtime.
|
||||
The IF NOT EXISTS clauses allow it to run against both an existing deployment
|
||||
and a new database.
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
|
||||
|
||||
revision: str = "0006_operational_schema_baseline"
|
||||
down_revision: Union[str, None] = "0005_miner_inventory"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.execute(
|
||||
"""
|
||||
ALTER TABLE miners
|
||||
ADD COLUMN IF NOT EXISTS manual_details JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
ADD COLUMN IF NOT EXISTS manual_details_updated_at TIMESTAMPTZ,
|
||||
ADD COLUMN IF NOT EXISTS manual_details_updated_by TEXT,
|
||||
ADD COLUMN IF NOT EXISTS psu_model TEXT,
|
||||
ADD COLUMN IF NOT EXISTS customer_sn TEXT,
|
||||
ADD COLUMN IF NOT EXISTS api3_supported BOOLEAN,
|
||||
ADD COLUMN IF NOT EXISTS api3_api_version TEXT,
|
||||
ADD COLUMN IF NOT EXISTS api3_api_switch TEXT,
|
||||
ADD COLUMN IF NOT EXISTS api3_last_seen_at TIMESTAMPTZ,
|
||||
ADD COLUMN IF NOT EXISTS api3_last_error TEXT,
|
||||
ADD COLUMN IF NOT EXISTS configured_performance_mode TEXT,
|
||||
ADD COLUMN IF NOT EXISTS configured_performance_mode_source TEXT,
|
||||
ADD COLUMN IF NOT EXISTS configured_performance_mode_updated_at TIMESTAMPTZ;
|
||||
|
||||
ALTER TABLE miner_status_snapshots
|
||||
ADD COLUMN IF NOT EXISTS ip_address INET,
|
||||
ADD COLUMN IF NOT EXISTS mac_address TEXT,
|
||||
ADD COLUMN IF NOT EXISTS fan_speed_in DOUBLE PRECISION,
|
||||
ADD COLUMN IF NOT EXISTS fan_speed_out DOUBLE PRECISION,
|
||||
ADD COLUMN IF NOT EXISTS elapsed_seconds DOUBLE PRECISION;
|
||||
"""
|
||||
)
|
||||
|
||||
op.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS miner_maintenance_events (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
miner_id UUID NOT NULL REFERENCES miners(id) ON DELETE CASCADE,
|
||||
event_type TEXT NOT NULL,
|
||||
event_status TEXT NOT NULL DEFAULT 'completed',
|
||||
event_title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
event_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
old_mac TEXT,
|
||||
new_mac TEXT,
|
||||
old_ip INET,
|
||||
new_ip INET,
|
||||
component_type TEXT,
|
||||
component_slot TEXT,
|
||||
component_serial TEXT,
|
||||
cost_amount NUMERIC(12, 2),
|
||||
downtime_minutes INTEGER,
|
||||
created_by_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_miner_maintenance_events_miner_id
|
||||
ON miner_maintenance_events(miner_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_miner_maintenance_events_event_at
|
||||
ON miner_maintenance_events(event_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_miner_maintenance_events_event_type
|
||||
ON miner_maintenance_events(event_type);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS location_positions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
room_id UUID REFERENCES rooms(id) ON DELETE SET NULL,
|
||||
room_name TEXT NOT NULL,
|
||||
rack_name TEXT NOT NULL,
|
||||
shelf_name TEXT NOT NULL,
|
||||
shelf_index INTEGER,
|
||||
position_index INTEGER NOT NULL,
|
||||
position_label TEXT,
|
||||
position_kind TEXT NOT NULL DEFAULT 'miner_slot',
|
||||
position_status TEXT NOT NULL DEFAULT 'available',
|
||||
expected_mac TEXT,
|
||||
miner_id UUID REFERENCES miners(id) ON DELETE SET NULL,
|
||||
equipment_label TEXT,
|
||||
notes TEXT,
|
||||
source_file TEXT,
|
||||
source_sheet TEXT,
|
||||
source_cell TEXT,
|
||||
raw_value TEXT,
|
||||
conflict_reason TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
ALTER TABLE location_positions
|
||||
ADD CONSTRAINT uq_location_positions_slot
|
||||
UNIQUE (room_name, rack_name, shelf_name, position_index);
|
||||
EXCEPTION
|
||||
WHEN duplicate_object OR duplicate_table THEN NULL;
|
||||
END $$;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_location_positions_room
|
||||
ON location_positions(room_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_location_positions_rack
|
||||
ON location_positions(room_name, rack_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_location_positions_expected_mac
|
||||
ON location_positions(expected_mac);
|
||||
CREATE INDEX IF NOT EXISTS idx_location_positions_miner_id
|
||||
ON location_positions(miner_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS miner_location_states (
|
||||
miner_id UUID PRIMARY KEY REFERENCES miners(id) ON DELETE CASCADE,
|
||||
asset_state TEXT NOT NULL DEFAULT 'waiting_placement',
|
||||
location_position_id UUID REFERENCES location_positions(id) ON DELETE SET NULL,
|
||||
state_notes TEXT,
|
||||
updated_by_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_miner_location_states_asset_state
|
||||
ON miner_location_states(asset_state);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS location_import_issues (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
import_batch_id UUID NOT NULL,
|
||||
issue_type TEXT NOT NULL,
|
||||
severity TEXT NOT NULL DEFAULT 'warning',
|
||||
message TEXT NOT NULL,
|
||||
mac_address TEXT,
|
||||
room_name TEXT,
|
||||
rack_name TEXT,
|
||||
shelf_name TEXT,
|
||||
position_index INTEGER,
|
||||
source_file TEXT,
|
||||
source_cell TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
resolved_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_location_import_issues_batch
|
||||
ON location_import_issues(import_batch_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_location_import_issues_mac
|
||||
ON location_import_issues(mac_address);
|
||||
"""
|
||||
)
|
||||
|
||||
op.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS miner_command_events (
|
||||
id TEXT PRIMARY KEY,
|
||||
miner_id TEXT NOT NULL,
|
||||
command_type TEXT NOT NULL,
|
||||
command_status TEXT NOT NULL,
|
||||
dry_run BOOLEAN NOT NULL DEFAULT true,
|
||||
requested_by_user_id TEXT,
|
||||
requested_by_username TEXT,
|
||||
target_ip TEXT,
|
||||
target_mac TEXT,
|
||||
request_payload JSONB,
|
||||
response_payload JSONB,
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
completed_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_miner_command_events_miner_id_created
|
||||
ON miner_command_events(miner_id, created_at DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS miner_api_credentials (
|
||||
miner_id TEXT PRIMARY KEY,
|
||||
api_account TEXT NOT NULL DEFAULT 'super',
|
||||
api_password TEXT NOT NULL,
|
||||
password_source TEXT NOT NULL DEFAULT 'minerops',
|
||||
updated_by_username TEXT,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS minerops_site_agents (
|
||||
agent_id TEXT PRIMARY KEY,
|
||||
site_name TEXT NOT NULL,
|
||||
hostname TEXT,
|
||||
version TEXT,
|
||||
ip_address TEXT,
|
||||
last_checkin_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
last_payload JSONB NOT NULL DEFAULT '{}'::jsonb
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS minerops_agent_snapshots (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
agent_id TEXT NOT NULL,
|
||||
site_name TEXT NOT NULL,
|
||||
snapshot_kind TEXT NOT NULL DEFAULT 'miner_poll',
|
||||
received_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
miner_count INTEGER NOT NULL DEFAULT 0,
|
||||
payload JSONB NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_minerops_agent_snapshots_received
|
||||
ON minerops_agent_snapshots(received_at DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS minerops_agent_command_results (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
agent_id TEXT NOT NULL,
|
||||
site_name TEXT NOT NULL,
|
||||
command_id TEXT,
|
||||
received_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
status TEXT NOT NULL,
|
||||
payload JSONB NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_minerops_agent_command_results_received
|
||||
ON minerops_agent_command_results(received_at DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS minerops_agent_command_queue (
|
||||
id TEXT PRIMARY KEY,
|
||||
agent_id TEXT NOT NULL,
|
||||
command_type TEXT NOT NULL,
|
||||
command_status TEXT NOT NULL DEFAULT 'pending',
|
||||
requested_by_user_id TEXT,
|
||||
requested_by_username TEXT,
|
||||
request_payload JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
result_payload JSONB,
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
claimed_at TIMESTAMPTZ,
|
||||
completed_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_minerops_agent_command_queue_agent_status
|
||||
ON minerops_agent_command_queue(agent_id, command_status, created_at);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS minerops_agent_discoveries (
|
||||
id TEXT PRIMARY KEY,
|
||||
agent_id TEXT NOT NULL,
|
||||
site_name TEXT NOT NULL,
|
||||
room_name TEXT,
|
||||
ip_address INET,
|
||||
mac_address TEXT,
|
||||
model TEXT,
|
||||
hostname TEXT,
|
||||
miner_sn TEXT,
|
||||
raw_payload JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
discovery_status TEXT NOT NULL DEFAULT 'new',
|
||||
matched_miner_id UUID,
|
||||
first_seen_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
last_seen_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_minerops_agent_discoveries_mac
|
||||
ON minerops_agent_discoveries(mac_address);
|
||||
CREATE INDEX IF NOT EXISTS idx_minerops_agent_discoveries_ip
|
||||
ON minerops_agent_discoveries(ip_address);
|
||||
"""
|
||||
)
|
||||
|
||||
op.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS minerops_scheduled_bulk_actions (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT,
|
||||
target_type TEXT NOT NULL,
|
||||
target_value TEXT,
|
||||
action TEXT NOT NULL DEFAULT 'performance_mode',
|
||||
performance_mode TEXT,
|
||||
repeat_rule TEXT NOT NULL DEFAULT 'once',
|
||||
scheduled_for TIMESTAMPTZ NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
agent_id TEXT NOT NULL DEFAULT 'plexus-windows-agent',
|
||||
requested_by_user_id TEXT,
|
||||
requested_by_username TEXT,
|
||||
queued_command_count INTEGER NOT NULL DEFAULT 0,
|
||||
last_queued_command_count INTEGER NOT NULL DEFAULT 0,
|
||||
run_count INTEGER NOT NULL DEFAULT 0,
|
||||
last_error TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
processed_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_minerops_scheduled_bulk_actions_due
|
||||
ON minerops_scheduled_bulk_actions(status, scheduled_for);
|
||||
CREATE INDEX IF NOT EXISTS idx_minerops_scheduled_bulk_actions_created
|
||||
ON minerops_scheduled_bulk_actions(created_at DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS miner_pool_snapshots (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
miner_id UUID,
|
||||
ip_address INET,
|
||||
mac_address TEXT,
|
||||
model TEXT,
|
||||
pool_index INTEGER,
|
||||
url TEXT,
|
||||
worker_user TEXT,
|
||||
pool_status TEXT,
|
||||
stratum_active BOOLEAN,
|
||||
accepted DOUBLE PRECISION,
|
||||
rejected DOUBLE PRECISION,
|
||||
stale DOUBLE PRECISION,
|
||||
get_failures DOUBLE PRECISION,
|
||||
remote_failures DOUBLE PRECISION,
|
||||
pool_rejected_percent DOUBLE PRECISION,
|
||||
pool_stale_percent DOUBLE PRECISION,
|
||||
last_share_time_epoch DOUBLE PRECISION,
|
||||
raw_pool_json JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
agent_id TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
ALTER TABLE miner_pool_snapshots
|
||||
ADD COLUMN IF NOT EXISTS model TEXT,
|
||||
ADD COLUMN IF NOT EXISTS pool_index INTEGER,
|
||||
ADD COLUMN IF NOT EXISTS url TEXT,
|
||||
ADD COLUMN IF NOT EXISTS worker_user TEXT,
|
||||
ADD COLUMN IF NOT EXISTS pool_status TEXT,
|
||||
ADD COLUMN IF NOT EXISTS stratum_active BOOLEAN,
|
||||
ADD COLUMN IF NOT EXISTS accepted DOUBLE PRECISION,
|
||||
ADD COLUMN IF NOT EXISTS rejected DOUBLE PRECISION,
|
||||
ADD COLUMN IF NOT EXISTS stale DOUBLE PRECISION,
|
||||
ADD COLUMN IF NOT EXISTS get_failures DOUBLE PRECISION,
|
||||
ADD COLUMN IF NOT EXISTS remote_failures DOUBLE PRECISION,
|
||||
ADD COLUMN IF NOT EXISTS pool_rejected_percent DOUBLE PRECISION,
|
||||
ADD COLUMN IF NOT EXISTS pool_stale_percent DOUBLE PRECISION,
|
||||
ADD COLUMN IF NOT EXISTS last_share_time_epoch DOUBLE PRECISION,
|
||||
ADD COLUMN IF NOT EXISTS raw_pool_json JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
ADD COLUMN IF NOT EXISTS agent_id TEXT;
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
id_type TEXT;
|
||||
BEGIN
|
||||
SELECT data_type INTO id_type
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = current_schema()
|
||||
AND table_name = 'miner_pool_snapshots'
|
||||
AND column_name = 'id';
|
||||
|
||||
IF id_type = 'text' THEN
|
||||
ALTER TABLE miner_pool_snapshots
|
||||
ALTER COLUMN id SET DEFAULT (gen_random_uuid())::text;
|
||||
ELSIF id_type = 'uuid' THEN
|
||||
ALTER TABLE miner_pool_snapshots
|
||||
ALTER COLUMN id SET DEFAULT gen_random_uuid();
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_miner_pool_snapshots_miner_created
|
||||
ON miner_pool_snapshots(miner_id, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_miner_pool_snapshots_ip_created
|
||||
ON miner_pool_snapshots(ip_address, created_at DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS miner_api3_enrichment_snapshots (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
miner_id UUID,
|
||||
agent_id TEXT,
|
||||
site_name TEXT,
|
||||
ip_address INET,
|
||||
mac_address TEXT,
|
||||
api_supported BOOLEAN,
|
||||
api_error TEXT,
|
||||
api_version TEXT,
|
||||
api_switch TEXT,
|
||||
model TEXT,
|
||||
miner_sn TEXT,
|
||||
power_sn TEXT,
|
||||
psu_model TEXT,
|
||||
device_info JSONB,
|
||||
miner_setting JSONB,
|
||||
miner_status JSONB,
|
||||
fan_setting JSONB,
|
||||
custom_data JSONB,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_miner_api3_enrichment_miner_created
|
||||
ON miner_api3_enrichment_snapshots(miner_id, created_at DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS miner_api3_hashboard_snapshots (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
miner_id UUID,
|
||||
ip_address INET,
|
||||
mac_address TEXT,
|
||||
slot INTEGER,
|
||||
pcb_sn TEXT,
|
||||
hash_average_ths DOUBLE PRECISION,
|
||||
factory_hash_ths DOUBLE PRECISION,
|
||||
freq DOUBLE PRECISION,
|
||||
effective_chips INTEGER,
|
||||
chip_temp_min_c DOUBLE PRECISION,
|
||||
chip_temp_avg_c DOUBLE PRECISION,
|
||||
chip_temp_max_c DOUBLE PRECISION,
|
||||
raw_hashboard_json JSONB,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_miner_api3_hashboards_miner_created
|
||||
ON miner_api3_hashboard_snapshots(miner_id, created_at DESC);
|
||||
"""
|
||||
)
|
||||
|
||||
op.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS miner_status_hourly_rollups (
|
||||
miner_id UUID NOT NULL REFERENCES miners(id) ON DELETE CASCADE,
|
||||
bucket_at TIMESTAMPTZ NOT NULL,
|
||||
sample_count BIGINT NOT NULL,
|
||||
avg_mhs_av DOUBLE PRECISION,
|
||||
max_mhs_av DOUBLE PRECISION,
|
||||
avg_power_w DOUBLE PRECISION,
|
||||
max_chip_temp_c DOUBLE PRECISION,
|
||||
avg_chip_temp_c DOUBLE PRECISION,
|
||||
avg_pool_rejected_percent DOUBLE PRECISION,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (miner_id, bucket_at)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_miner_status_hourly_bucket
|
||||
ON miner_status_hourly_rollups(bucket_at);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS miner_status_daily_rollups (
|
||||
miner_id UUID NOT NULL REFERENCES miners(id) ON DELETE CASCADE,
|
||||
bucket_date DATE NOT NULL,
|
||||
sample_count BIGINT NOT NULL,
|
||||
avg_mhs_av DOUBLE PRECISION,
|
||||
max_mhs_av DOUBLE PRECISION,
|
||||
avg_power_w DOUBLE PRECISION,
|
||||
max_chip_temp_c DOUBLE PRECISION,
|
||||
avg_chip_temp_c DOUBLE PRECISION,
|
||||
avg_pool_rejected_percent DOUBLE PRECISION,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (miner_id, bucket_date)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_miner_status_daily_bucket
|
||||
ON miner_status_daily_rollups(bucket_date);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS minerops_retention_runs (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
mode TEXT NOT NULL,
|
||||
raw_status_retention_days INTEGER NOT NULL,
|
||||
hourly_rollup_rows_before BIGINT NOT NULL DEFAULT 0,
|
||||
hourly_rollup_rows_after BIGINT NOT NULL DEFAULT 0,
|
||||
daily_rollup_rows_before BIGINT NOT NULL DEFAULT 0,
|
||||
daily_rollup_rows_after BIGINT NOT NULL DEFAULT 0,
|
||||
raw_status_rows_before BIGINT NOT NULL DEFAULT 0,
|
||||
raw_status_rows_after BIGINT NOT NULL DEFAULT 0,
|
||||
raw_status_rows_eligible_delete BIGINT NOT NULL DEFAULT 0,
|
||||
raw_status_rows_deleted BIGINT NOT NULL DEFAULT 0,
|
||||
started_at TIMESTAMPTZ NOT NULL,
|
||||
finished_at TIMESTAMPTZ NOT NULL,
|
||||
notes TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_minerops_retention_runs_started
|
||||
ON minerops_retention_runs(started_at DESC);
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
raise RuntimeError(
|
||||
"0006 adopts pre-existing operational tables and is intentionally irreversible"
|
||||
)
|
||||
Reference in new issue
Block a user