4fcf2c9616
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.
47 lines
2.3 KiB
SQL
47 lines
2.3 KiB
SQL
-- 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);
|