Every other thing in this product a person refers to already had a readable reference: a shop is chennai, a camera cam1, a customer V-42, a person their email. An audit of every list response found exactly one gap, and it was the row people look at most - the arrivals feed showed a visit as 36 hex characters. 012 argued no route takes a visit id so none was needed. That is true of routing and false of everything else: it is what the feed shows, what a support conversation quotes, and what somebody reading an API response judges the product by. Migration 014 mirrors the visitor scheme exactly - per client, so it discloses no platform-wide volume, and beside the uuid rather than instead of it. A stored counter is affordable on the busiest table because visits from one tenant are already serialised by the consumer's SetOrderMatters(true), so it adds no contention that was not already there. A derived reference was the alternative and does not work: several people through one door share occurred_at to the microsecond, which is the collision 004 exists to handle. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KGcjxF1cNLcuwc3DAPcnfj
53 lines
2.4 KiB
SQL
53 lines
2.4 KiB
SQL
-- A visit reference a person can use, beside the key a machine uses.
|
|
--
|
|
-- Every other thing in this product a person refers to already has one: a shop
|
|
-- is `chennai`, a camera is `cam1`, a customer is `V-42`, a person is their
|
|
-- email. A visit had only its uuid:
|
|
--
|
|
-- "visit_id": "4cc216ca-dad3-4958-bb96-5f5a82022cf8"
|
|
--
|
|
-- 012 argued that this was acceptable because no route takes a visit id and
|
|
-- nobody says one out loud. That is true of routing and false of everything
|
|
-- else: it is what the arrivals feed shows, what a support conversation has to
|
|
-- quote, and what somebody reading an API response judges the product by. The
|
|
-- owner asked for it twice.
|
|
--
|
|
-- `#1042`, per client, mirroring `V-42` exactly and for the same three reasons
|
|
-- (speakable, per-tenant so it discloses no platform-wide volume, and a
|
|
-- reference beside the key rather than a replacement for it - eleven tables
|
|
-- reference visits.id).
|
|
--
|
|
-- Why a stored counter is affordable on the hottest table in the schema:
|
|
-- allocating it row-locks the client for the length of one insert, and visits
|
|
-- from one tenant are ALREADY serialised - the MQTT consumer sets
|
|
-- SetOrderMatters(true) precisely so that `seq` is a commit order. So this
|
|
-- adds no contention a tenant did not already have, and tenants never block
|
|
-- each other. A derived reference was the alternative and does not work:
|
|
-- several people through one door share occurred_at to the microsecond, which
|
|
-- is the very collision 004 exists to handle.
|
|
|
|
ALTER TABLE clients ADD COLUMN IF NOT EXISTS visit_seq bigint NOT NULL DEFAULT 0;
|
|
ALTER TABLE visits ADD COLUMN IF NOT EXISTS number bigint;
|
|
|
|
-- Existing rows get their numbers in the order the server learned of them,
|
|
-- which is what `seq` means - not occurred_at, which is the camera's clock and
|
|
-- arrives out of order after a site has been offline.
|
|
WITH numbered AS (
|
|
SELECT id, row_number() OVER (PARTITION BY client_id ORDER BY seq) AS n
|
|
FROM visits
|
|
)
|
|
UPDATE visits v SET number = numbered.n
|
|
FROM numbered
|
|
WHERE v.id = numbered.id AND v.number IS NULL;
|
|
|
|
UPDATE clients c
|
|
SET visit_seq = GREATEST(c.visit_seq, COALESCE(
|
|
(SELECT max(number) FROM visits WHERE client_id = c.id), 0));
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS visits_client_number_idx
|
|
ON visits (client_id, number);
|
|
|
|
COMMENT ON COLUMN visits.number IS
|
|
'Per-client visit number, shown as #1042. A public reference beside the '
|
|
'uuid key, never a replacement for it.';
|