feat(db): add M2 schema — play_sessions, play_events, skip_events
Tables and indexes per spec §5. session_vector_at_play ships nullable so M3 doesn't need a follow-up migration. Table is named play_sessions to avoid collision with the existing sessions (HTTP auth) table from migration 0004.
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
DROP TABLE IF EXISTS skip_events;
|
||||
DROP TABLE IF EXISTS play_events;
|
||||
DROP TABLE IF EXISTS play_sessions;
|
||||
@@ -0,0 +1,46 @@
|
||||
-- M2 listening telemetry: play_sessions, play_events, skip_events.
|
||||
-- Note the table is named play_sessions (not sessions — that table already
|
||||
-- exists from migration 0004 and holds HTTP auth sessions). Listening
|
||||
-- sessions are an entirely separate concept driven by spec §6.
|
||||
--
|
||||
-- session_vector_at_play and contextual_likes ship as nullable now even
|
||||
-- though M2 writes NULL; M3 will populate them without a follow-up
|
||||
-- migration.
|
||||
|
||||
CREATE TABLE play_sessions (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
started_at timestamptz NOT NULL,
|
||||
ended_at timestamptz,
|
||||
last_event_at timestamptz NOT NULL,
|
||||
track_count integer NOT NULL DEFAULT 0,
|
||||
client_id text
|
||||
);
|
||||
CREATE INDEX play_sessions_user_last_event_idx ON play_sessions (user_id, last_event_at DESC);
|
||||
|
||||
CREATE TABLE play_events (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
track_id uuid NOT NULL REFERENCES tracks(id) ON DELETE CASCADE,
|
||||
session_id uuid NOT NULL REFERENCES play_sessions(id) ON DELETE CASCADE,
|
||||
started_at timestamptz NOT NULL,
|
||||
ended_at timestamptz,
|
||||
duration_played_ms integer,
|
||||
completion_ratio double precision,
|
||||
was_skipped boolean NOT NULL DEFAULT false,
|
||||
client_id text,
|
||||
session_vector_at_play jsonb,
|
||||
scrobbled_at timestamptz
|
||||
);
|
||||
CREATE INDEX play_events_user_started_idx ON play_events (user_id, started_at DESC);
|
||||
CREATE INDEX play_events_user_track_idx ON play_events (user_id, track_id);
|
||||
|
||||
CREATE TABLE skip_events (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
track_id uuid NOT NULL REFERENCES tracks(id) ON DELETE CASCADE,
|
||||
session_id uuid NOT NULL REFERENCES play_sessions(id) ON DELETE CASCADE,
|
||||
skipped_at timestamptz NOT NULL,
|
||||
position_ms integer NOT NULL
|
||||
);
|
||||
CREATE INDEX skip_events_user_skipped_idx ON skip_events (user_id, skipped_at DESC);
|
||||
Reference in New Issue
Block a user