1+
2+
3+ -- Main shards table.
4+ CREATE TABLE IF NOT EXISTS shard (
5+ id BIGSERIAL PRIMARY KEY ,
6+ kind TEXT NOT NULL ,
7+ shard_key TEXT NOT NULL ,
8+ capacity INT NOT NULL DEFAULT 10000 ,
9+ next_slot INT NOT NULL DEFAULT 0 ,
10+ status TEXT NOT NULL DEFAULT ' active' , -- active|draining|disabled
11+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
12+ UNIQUE (kind, shard_key)
13+ );
14+
15+ -- Sparse slot rows: only the slots that have ever been used exist here.
16+ -- A "free" slot is a row with reservation_id NULL and resource_id NULL.
17+ CREATE TABLE IF NOT EXISTS shard_slots (
18+ shard_id BIGINT NOT NULL REFERENCES shard(id) ON DELETE CASCADE ,
19+ slot_no INT NOT NULL ,
20+ tenant_id TEXT ,
21+ resource_id TEXT , -- set when confirmed
22+ PRIMARY KEY (shard_id, slot_no)
23+ );
24+
25+ -- Reservations with short leases
26+ CREATE TABLE IF NOT EXISTS shard_reservation (
27+ id UUID PRIMARY KEY default gen_random_uuid(),
28+ kind text NOT NULL ,
29+ tenant_id TEXT ,
30+ resource_id TEXT NOT NULL , -- e.g. "vector::bucket::name"
31+ shard_id BIGINT NOT NULL ,
32+ slot_no INT NOT NULL ,
33+ status TEXT NOT NULL DEFAULT ' pending' , -- pending|confirmed|expired|cancelled
34+ lease_expires_at TIMESTAMPTZ NOT NULL ,
35+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
36+ UNIQUE (kind, resource_id),
37+ UNIQUE (shard_id, slot_no)
38+ );
39+
40+ -- Fast “used count” per shard
41+ CREATE INDEX IF NOT EXISTS shard_slots_used_idx
42+ ON shard_slots (shard_id)
43+ WHERE resource_id IS NOT NULL ;
44+
45+ ALTER TABLE shard
46+ ADD CONSTRAINT shard_capacity_not_less_than_minted
47+ CHECK (capacity >= next_slot);
48+
49+
50+ -- Create index for counting slots by tenant
51+ CREATE INDEX IF NOT EXISTS shard_slots_tenant_id_idx
52+ ON shard_slots (tenant_id);
53+
54+ -- Create index for counting reservations by tenant
55+ CREATE INDEX IF NOT EXISTS shard_reservation_tenant_id_idx
56+ ON shard_reservation (tenant_id);
57+
58+ -- Create index for counting used slots by tenant
59+ CREATE INDEX IF NOT EXISTS shard_slots_tenant_resource_idx
60+ ON shard_slots (tenant_id, shard_id)
61+ WHERE resource_id IS NOT NULL ;
62+
63+
64+ ALTER TABLE shard_reservation
65+ ADD CONSTRAINT fk_shard_slot
66+ FOREIGN KEY (shard_id, slot_no)
67+ REFERENCES shard_slots(shard_id, slot_no)
68+ ON DELETE RESTRICT;
69+
70+
71+ CREATE INDEX IF NOT EXISTS shard_slots_free_idx
72+ ON shard_slots (shard_id, slot_no)
73+ WHERE resource_id IS NULL ;
74+
75+ -- Add index for finding active reservations by slot
76+ CREATE INDEX IF NOT EXISTS shard_reservation_active_slot_idx
77+ ON shard_reservation (shard_id, slot_no, lease_expires_at)
78+ WHERE status = ' pending' ;
0 commit comments