Store the user-directory temp position as BIGINT

The `populate_user_directory` background update stored its stream position in a
`TEXT` column (`_temp_populate_user_directory_position.position`) but wrote an
int into it and read it back into the `BIGINT`
`user_directory_stream_pos.stream_id` — the one place in the storage layer that
bound an int to a text column (and a numeric string back to an int column). This
only worked because psycopg2 coerces such literals; the native Rust driver binds
typed parameters and rejects the mismatch.

Fix it at the source: make the temp column `BIGINT`, matching the value it holds
(and `update_user_directory_stream_pos`'s `int` type hint, which the `TEXT`
column had been quietly violating). The temp table is created and dropped within
the background update, so there's no migration.

Tested: user_directory storage + handler tests pass on all three backends
(psycopg2, sqlite, Rust).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W3G4M92AmwSSZCbmtMJU3d
This commit is contained in:
Erik Johnston
2026-07-11 09:04:57 +00:00
co-authored by Claude Opus 4.8
parent 3ff94428a7
commit 956ce20e63
2 changed files with 25 additions and 0 deletions
@@ -125,6 +125,10 @@ class UserDirectoryBackgroundUpdateStore(StateDeltasStore):
f"CREATE INDEX IF NOT EXISTS {TEMP_TABLE}_rooms_evs ON {TEMP_TABLE}_rooms (events)"
)
# NB: the `position` column used to be TEXT; `IF NOT EXISTS` keeps
# a table made by an older release, which the schema delta
# 94/05_temp_user_dir_position_bigint.sql.postgres upgrades in
# place.
sql = f"""
CREATE TABLE IF NOT EXISTS {TEMP_TABLE}_position (
position BIGINT NOT NULL
@@ -0,0 +1,21 @@
--
-- This file is licensed under the Affero General Public License (AGPL) version 3.
--
-- Copyright (C) 2026 Element Creations, Ltd
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Affero General Public License as
-- published by the Free Software Foundation, either version 3 of the
-- License, or (at your option) any later version.
--
-- See the GNU Affero General Public License for more details:
-- <https://www.gnu.org/licenses/agpl-3.0.html>.
-- The user-directory rebuild's staging table changed its `position` column
-- from TEXT to BIGINT, but the table is created with IF NOT EXISTS and only
-- dropped when the populate_user_directory background update completes, so a
-- server upgrading mid-rebuild keeps the old TEXT column — which the native
-- Rust driver's strictly-typed binding can neither read nor write. Upgrade it
-- in place; a no-op for servers without the table (i.e. almost all of them).
ALTER TABLE IF EXISTS _temp_populate_user_directory_position
ALTER COLUMN position TYPE BIGINT USING position::bigint;