Files
Justin Maier 98f42aab65 fix(3d-models): correct the cutover constant and drop the superseded backfill (#4054)
* fix(3d-models): correct the cutover constant and drop the superseded backfill

The constant said 2026-08-18, picked by hand before the deploy. Tracking actually
started 2026-08-17 17:21:31 UTC, so the Creator Studio would have marked the
boundary a day late. Now read off production, with a note that the day is MIXED -
backfilled before 17:21:31, live beacons after - so a consumer marks that day and
not the one after it.

Removes scripts/oneoffs/backfill-model3d-views.{ts,helpers.ts} and its test. The
backfill now lives in civitai-scripts (backfill/model3d-views.js), and the copy
here still carried the design that shipped wrong: an --until DATE cannot express
the real boundary, because tracking starts mid-day. Any date either drops that
day's pre-deploy views or double-counts its post-deploy ones - measured on the
real cutover, 1,488 views before the first beacon and 296 after. The replacement
derives the boundary as min(time) of the first tracked day, so the two sources
abut exactly and there is no value left to typo.

Leaving a second, wrong copy in this repo is worse than having none: it is the
one a reader finds by grepping.

The DDL file is kept as the record of what ran, now marked applied.

Backfill result, verified independently: 11,336 rows / 175,964 views across 476
models, 2026-06-19 to the cutover. The boundary day reads 1,650 = 162 beacons +
1,488 backfilled.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0125bNeEK6nqERsbALjiDaUS

* refactor(3d-models): keep the cutover constant hardcoded, trim comments

The constant stays and stays hardcoded - the backfill derives its own boundary
from data and never reads it, so its only job is captioning the Studio chart,
and a hand-set date is fine for that.

Corrected to 2026-08-17, the day tracking actually began (17:21:31 UTC). The
comment now says the thing a reader needs and nothing else: the two spans are
different measurements, page loads ran ~1.5x the beacons that replaced them, so
a chart crossing that day steps down for reasons unrelated to the creator.

SQL comments cut 60 lines to 19, keeping only what a future editor would get
wrong without them - that MODIFY COLUMN replaces rather than appends, that
entityType is a sorting key so renumbering means a table rewrite, and why the
MV goes last.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0125bNeEK6nqERsbALjiDaUS

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 21:41:09 -06:00

63 lines
2.6 KiB
SQL

-- Model3D view tracking — ClickHouse enum widening. APPLIED TO PRODUCTION
-- 2026-08-17, after the comics DDL. Kept as the record of what ran.
--
-- `MODIFY COLUMN` on an Enum8 REPLACES the type rather than appending, which is
-- why every statement restates all twelve arms including comics' 10 and 11.
-- Dropping an arm invalidates rows already written with it, and renumbering one
-- turns this from a metadata change into a rewrite of 1.68B `daily_views` rows —
-- `entityType` is a sorting key in both tables.
--
-- Order matters twice over: `daily_views` before `views`, so no row can reach a
-- target that cannot represent it; and `daily_views_mv` LAST, because MODIFY
-- QUERY re-derives the MV's stored header from its SELECT's result types, and
-- that SELECT reads `views`.
-- Step 0 — expect all three to end at 'ComicChapter' = 11 / 'ComicChapterView' = 11.
-- Anything past 11 means another migration claimed indexes: STOP.
SELECT table, name, type FROM system.columns
WHERE database = 'default'
AND ((table = 'views' AND name IN ('type', 'entityType'))
OR (table = 'daily_views' AND name = 'entityType'))
ORDER BY table, name;
-- Step 1 — MV target first.
ALTER TABLE default.daily_views
MODIFY COLUMN entityType Enum8(
'User' = 1, 'Image' = 2, 'Post' = 3, 'Model' = 4, 'ModelVersion' = 5,
'Article' = 6, 'Collection' = 7, 'Bounty' = 8, 'BountyEntry' = 9,
'ComicProject' = 10, 'ComicChapter' = 11, 'Model3D' = 12
);
-- Step 2 — source table.
ALTER TABLE default.views
MODIFY COLUMN entityType Enum8(
'User' = 1, 'Image' = 2, 'Post' = 3, 'Model' = 4, 'ModelVersion' = 5,
'Article' = 6, 'Collection' = 7, 'Bounty' = 8, 'BountyEntry' = 9,
'ComicProject' = 10, 'ComicChapter' = 11, 'Model3D' = 12
);
ALTER TABLE default.views
MODIFY COLUMN type Enum8(
'ProfileView' = 1, 'ImageView' = 2, 'PostView' = 3, 'ModelView' = 4,
'ModelVersionView' = 5, 'ArticleView' = 6, 'CollectionView' = 7,
'BountyView' = 8, 'BountyEntryView' = 9,
'ComicProjectView' = 10, 'ComicChapterView' = 11, 'Model3DView' = 12
);
-- Step 3 — MV header, last. SELECT restated unchanged.
ALTER TABLE default.daily_views_mv
MODIFY QUERY
SELECT entityType, entityId, createdDate, count(*) AS views
FROM default.views
GROUP BY 1, 2, 3;
-- Step 4 — verify. Expect twelve arms on all three columns and on the MV's own header.
SELECT table, name, type FROM system.columns
WHERE database = 'default'
AND ((table = 'views' AND name IN ('type', 'entityType'))
OR (table = 'daily_views' AND name = 'entityType'))
ORDER BY table, name;
SELECT create_table_query FROM system.tables
WHERE database = 'default' AND name = 'daily_views_mv';