fix(realism): synthetic_files path fits MySQL utf8mb4 index cap
The (decky_uuid VARCHAR(64), path VARCHAR(1024)) UNIQUE constraint
generated a 4352-byte composite key under utf8mb4 (4 bytes/char),
busting MySQL's 3072-byte cap and crashing decnet api on init with:
Specified key was too long; max key length is 3072 bytes
Tighten path to VARCHAR(512) — (64+512)*4 = 2304 bytes, well under
the cap. Real realism + canary placement paths are short
(/home/<persona>/Documents/<file>, ~70 chars); 512 keeps headroom
without the index hassle. Pre-v1, no migration helper.
Adds a regression test pinning the (decky_uuid + path) byte budget so
a future widening fails loudly in CI rather than at MySQL deploy
time.
This commit is contained in:
@@ -58,7 +58,11 @@ class SyntheticFile(SQLModel, table=True):
|
||||
)
|
||||
uuid: str = Field(default_factory=lambda: str(uuid4()), primary_key=True)
|
||||
decky_uuid: str = Field(index=True, max_length=64)
|
||||
path: str = Field(max_length=1024)
|
||||
# Capped at 512 so the (decky_uuid, path) unique index fits MySQL's
|
||||
# 3072-byte utf8mb4 limit: (64+512)*4 = 2304 bytes. Real realism +
|
||||
# canary paths are well under (longest is
|
||||
# ``/home/<persona>/Documents/Q3-Operations-Review.docx``, ~70 chars).
|
||||
path: str = Field(max_length=512)
|
||||
persona: str = Field(max_length=128) # EmailPersona.name
|
||||
content_class: str = Field(max_length=32, index=True) # ContentClass enum value
|
||||
created_at: datetime = Field(
|
||||
|
||||
@@ -150,3 +150,18 @@ async def test_get_synthetic_file_returns_row(repo):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_synthetic_file_returns_none_when_missing(repo):
|
||||
assert await repo.get_synthetic_file("does-not-exist") is None
|
||||
|
||||
|
||||
def test_path_max_length_fits_mysql_utf8mb4_index_limit():
|
||||
"""The unique (decky_uuid, path) index has to fit MySQL's 3072-byte
|
||||
utf8mb4 cap: (decky_uuid_len + path_len) * 4 <= 3072. A regression
|
||||
that widens path past this triggers
|
||||
``Specified key was too long`` on MySQL DB init."""
|
||||
from decnet.web.db.models.realism import SyntheticFile
|
||||
fields = SyntheticFile.model_fields
|
||||
decky_len = fields["decky_uuid"].metadata[0].max_length # type: ignore[attr-defined]
|
||||
path_len = fields["path"].metadata[0].max_length # type: ignore[attr-defined]
|
||||
assert (decky_len + path_len) * 4 <= 3072, (
|
||||
f"(decky_uuid={decky_len} + path={path_len}) * 4 = "
|
||||
f"{(decky_len + path_len) * 4} exceeds MySQL utf8mb4 index cap"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user