0.1.38 gateway
This commit is contained in:
@@ -539,3 +539,121 @@ CREATE TABLE IF NOT EXISTS media_requests (
|
||||
|
||||
CREATE INDEX IF NOT EXISTS media_requests_user_requested_idx
|
||||
ON media_requests (emby_user_id, requested_at DESC);
|
||||
|
||||
-- Every sign-in attempt, successful or not.
|
||||
--
|
||||
-- The sessions table above holds one row per television and is overwritten by the next
|
||||
-- sign-in, replaced when a device id moves and deleted when a set is removed — so it can
|
||||
-- say what is true now and nothing at all about what happened. This is the history: how
|
||||
-- often a set has connected, at what times, from which addresses, on which build, and
|
||||
-- whether the attempt got in. Every column records what was true at the moment of the
|
||||
-- attempt, including the ones that later change, which is why device_name and
|
||||
-- client_version are copied here rather than joined from the session.
|
||||
--
|
||||
-- A failed attempt has no emby_user_id: Emby refused the credentials, so there is no
|
||||
-- verified identity to attribute it to. The username is what was typed, and it is kept
|
||||
-- precisely because a run of failures against one name is the thing worth noticing.
|
||||
CREATE TABLE IF NOT EXISTS login_events (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
occurred_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
emby_user_id TEXT NOT NULL DEFAULT '',
|
||||
username TEXT NOT NULL DEFAULT '',
|
||||
device_id TEXT NOT NULL DEFAULT '',
|
||||
device_name TEXT NOT NULL DEFAULT '',
|
||||
client_version TEXT NOT NULL DEFAULT '',
|
||||
client_protocol TEXT NOT NULL DEFAULT '',
|
||||
ip_address TEXT NOT NULL DEFAULT '',
|
||||
success BOOLEAN NOT NULL,
|
||||
method TEXT NOT NULL DEFAULT 'password',
|
||||
failure_reason TEXT NOT NULL DEFAULT '',
|
||||
new_device BOOLEAN NOT NULL DEFAULT false
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS login_events_time_idx ON login_events (occurred_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS login_events_device_time_idx
|
||||
ON login_events (device_id, occurred_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS login_events_user_time_idx
|
||||
ON login_events (emby_user_id, occurred_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS login_events_ip_idx ON login_events (ip_address);
|
||||
|
||||
-- Administrative events: the operational feed behind the console's notification bell.
|
||||
--
|
||||
-- Deliberately generic. A publisher supplies a type, a severity, who or what it concerns
|
||||
-- and a sentence; nothing here knows about sign-ins, devices or scheduled tasks
|
||||
-- specifically. That is what lets a service added later publish into the same feed, and
|
||||
-- what lets one integration deliver every kind of event without a case per kind.
|
||||
--
|
||||
-- read_at is a single operator's read state rather than a per-account one: the console is
|
||||
-- guarded by one shared admin token, so there is one reader by construction.
|
||||
CREATE TABLE IF NOT EXISTS admin_events (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
occurred_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
type TEXT NOT NULL,
|
||||
severity TEXT NOT NULL DEFAULT 'info',
|
||||
title TEXT NOT NULL DEFAULT '',
|
||||
summary TEXT NOT NULL DEFAULT '',
|
||||
actor TEXT NOT NULL DEFAULT '',
|
||||
target TEXT NOT NULL DEFAULT '',
|
||||
link TEXT NOT NULL DEFAULT '',
|
||||
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
read_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS admin_events_time_idx ON admin_events (occurred_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS admin_events_unread_idx
|
||||
ON admin_events (occurred_at DESC) WHERE read_at IS NULL;
|
||||
CREATE INDEX IF NOT EXISTS admin_events_type_time_idx ON admin_events (type, occurred_at DESC);
|
||||
|
||||
-- One row per run of a scheduled task.
|
||||
--
|
||||
-- The scheduler keeps its next-run time in memory because it is derived from the schedule
|
||||
-- and the clock, but what *happened* has to outlive the process: an operator asking why
|
||||
-- the overnight housekeeping did not run is asking about a container that has since been
|
||||
-- replaced. Duration is stored rather than derived so a run killed by a restart, which
|
||||
-- has a start and no finish, is distinguishable from one that took no time.
|
||||
CREATE TABLE IF NOT EXISTS scheduled_task_runs (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
task_id TEXT NOT NULL,
|
||||
trigger TEXT NOT NULL DEFAULT 'schedule', -- schedule | manual | startup
|
||||
status TEXT NOT NULL, -- running | success | failed | skipped
|
||||
started_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
finished_at TIMESTAMPTZ,
|
||||
duration_ms BIGINT NOT NULL DEFAULT 0,
|
||||
detail TEXT NOT NULL DEFAULT '',
|
||||
error TEXT NOT NULL DEFAULT ''
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS scheduled_task_runs_task_idx
|
||||
ON scheduled_task_runs (task_id, started_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS scheduled_task_runs_time_idx
|
||||
ON scheduled_task_runs (started_at DESC);
|
||||
|
||||
-- An operator's per-task overrides. A task that has never been touched has no row, and
|
||||
-- absence is "run as the code declares" — reading it the other way would leave every task
|
||||
-- disabled on the day this shipped.
|
||||
CREATE TABLE IF NOT EXISTS scheduled_task_settings (
|
||||
task_id TEXT PRIMARY KEY,
|
||||
enabled BOOLEAN NOT NULL DEFAULT true,
|
||||
interval_seconds INT NOT NULL DEFAULT 0, -- 0 keeps the task's declared interval
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- What an integration actually managed to deliver.
|
||||
--
|
||||
-- Kept because the two questions an operator has about a webhook are "is it working" and
|
||||
-- "why did that one not arrive", and neither is answerable from configuration. The body
|
||||
-- is not stored: it is reconstructible from the event, and a webhook payload is the one
|
||||
-- place a URL containing a secret would otherwise come to rest in the database.
|
||||
CREATE TABLE IF NOT EXISTS integration_deliveries (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
integration_id TEXT NOT NULL,
|
||||
event_type TEXT NOT NULL DEFAULT '',
|
||||
attempted_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
success BOOLEAN NOT NULL,
|
||||
status_code INT NOT NULL DEFAULT 0,
|
||||
duration_ms BIGINT NOT NULL DEFAULT 0,
|
||||
error TEXT NOT NULL DEFAULT ''
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS integration_deliveries_idx
|
||||
ON integration_deliveries (integration_id, attempted_at DESC);
|
||||
|
||||
Reference in New Issue
Block a user