fix(etl): clear out 6 failing entity_manager tests (4 code bugs + 2 test bugs) - #307
Closed
raymondjacobson wants to merge 1 commit into
Closed
fix(etl): clear out 6 failing entity_manager tests (4 code bugs + 2 test bugs)#307raymondjacobson wants to merge 1 commit into
raymondjacobson wants to merge 1 commit into
Conversation
The entity_manager package had six db-backed tests failing on a working
ETL_TEST_DB_URL setup. Per-test triage (patch-code / patch-test):
1. TestAssociatedWalletCreate_SOL_Success — code bug. The create handler
unconditionally lowercased the wallet address. Lowercasing destroys
Solana base58 addresses (capital L → lowercase l, which is not in the
bitcoin base58 alphabet), so the signature verifier rejected with
"invalid base58 character: l". Introduce canonicalizeWallet that
lowercases ETH (hex, case-insensitive) and preserves SOL case.
2. TestAssociatedWalletDelete_Success — code bug. The delete UPDATE
filtered by `chain = $4`, but the delete tx doesn't include `chain`
in metadata, so chain was empty and the row was never updated.
validateAssociatedWalletDelete's own existence check already uses
`(user_id, wallet)` as the lookup key with no chain; bring the
UPDATE's WHERE in line with it.
3. & 4. TestDashboardWalletCreate_Success / TestDashboardWalletDelete_Success
— test bug. The handler canonicalizes ETH wallet addresses to
lowercase for storage (correct); the assertion query used the
original cased address and missed the row. Lowercase the address
in the test query to match the canonical form.
5. TestSave_Album_Success — code bug. Save/Repost/Unsave/Unrepost
handlers preferred the chain-level entity_type ("Playlist") over the
metadata `type` ("album") when deriving save_type. The chain
entity_type can't distinguish playlist vs album (albums are stored
as playlists with is_album=true), so a Playlist entity_type was
silently coercing album saves to playlist saves. New resolve helpers:
metadata `type` wins; if entity_type is the ambiguous "playlist",
defer to DB inference (which reads is_album).
6. TestTrackUpdate_NotFound — test bug. The test seeded a user with
wallet "0xo" but signed with "0xOwner", so ValidateSigner fired
before the existence check the test means to exercise. Seed the
user with a wallet matching the signer.
All six tests now pass. Same suite (`go test ./...`) verified clean
end-to-end across multiple runs against a fresh Postgres.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
Contributor
Author
|
Closing in favor of #308 |
raymondjacobson
added a commit
that referenced
this pull request
May 22, 2026
Findings from running the indexer against a production database clone for ~3h and diffing the result against a live production read replica. This PR includes the corrected versions of #307's test fixes (one had a regression we caught in the diff) plus four new prod-only bugs. 1. save_type/repost_type mistyped on entity-id collisions (REGRESSION from PR #307). When chain entity_type was "Playlist", #307 fell through to inferSaveType, which ranks tracks first. Whenever a track existed with the same numeric id as the playlist being saved (track_id and playlist_id are independent namespaces — collisions are real), the save was written with save_type='track' instead of 'playlist'. Observed against prod: ~1% of saves mistyped. Fix: resolveSaveType / resolveRepostType only disambiguate "Playlist" via playlists.is_album; never cross over to "track". New TestSave_Playlist_WhenTrackIdCollides locks this in. 2. mergeNullStr treats "" as "clear field" instead of "no change". Chain User Update txs commonly include "handle":"" when the client doesn't want to change handle; our handler was wiping users.handle to NULL while leaving handle_lc populated. Real data corruption observed against prod (e.g. user_id=169901003 'richard627'). Fix: empty string now preserves the existing value, matching the prod indexer. 3. PRIMARY KEY violations on re-delivered txs (shares_pkey, reposts_pkey, saves_pkey, follows_pkey, subscriptions_pkey). Bare INSERTs into row-versioned (entity_keys..., txhash) PKs hit 23505 when the prefetcher re-delivers a chain tx (root cause deferred). All five domain inserts now have ON CONFLICT (...) DO NOTHING — txhash is content-addressable, so re-delivered data is identical. 4. blockhash NOT NULL on prod schema. Our migrations declare `blockhash ... NOT NULL DEFAULT ''` (so omitting the column locally silently writes ''), but prod schemas have no default — every INSERT must include it. Observed events.blockhash 23502 violation in prod-clone run. Added blockhash to INSERTs into events, associated_wallets, muted_users. Also folded in from #307 (the five non-regression fixes): 5. AssociatedWalletCreate: SOL base58 case preservation. ETH addresses lowercase; SOL preserve case (uppercase `L` → invalid base58 `l`). New `canonicalizeWallet` helper handles both based on chain or `0x` prefix. 6. AssociatedWalletDelete: drop bogus `chain = $4` filter from the UPDATE — delete tx doesn't include chain, so the filter was always matching empty string and updating nothing. Validation already keys on (user_id, wallet); UPDATE now matches. 7. dashboard_wallet_test.go: lowercase wallet address in test queries to match handler's canonical storage form. 8. track_update_test.go: seed user wallet matching the signer so the test reaches the existence check it means to exercise. Closes #307 (superseded). Deferred: "no rows in result set" raw error (needs context attribution), TCP "can't assign requested address" (environmental). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The entity_manager package had six db-backed tests failing on a working
ETL_TEST_DB_URLsetup — long called out as out-of-scope in prior PRs. Walked each one and split into real code bugs vs. test bugs. Four of the six were genuine handler bugs that would have produced wrong/missing rows in production; two were test sloppiness.Per-test triage
TestAssociatedWalletCreate_SOL_Successstrings.ToLoweron the wallet destroys Solana base58 (capitalL→ invalidl). Now: lowercase only ETH, preserve SOL case.TestAssociatedWalletDelete_SuccessUPDATEfiltered bychain = $4, but delete tx has nochainfield in metadata, so the WHERE never matched. Bring the UPDATE in line with the validation's(user_id, wallet)key.TestDashboardWalletCreate_SuccessTestDashboardWalletDelete_SuccessTestSave_Album_Successentity_type("Playlist") over metadatatype("album"). But chain entity_type can't distinguish playlist from album (albums are playlists withis_album=true), so album saves were silently coerced to playlist saves. NewresolveSaveType/resolveRepostType: metadatatypewins; if entity_type is the ambiguous"playlist", defer to DB inference (is_album).TestTrackUpdate_NotFound0xobut signed with0xOwner, soValidateSignerrejected before the existence check the test means to exercise. Seed with matching wallet.Test plan
go build ./...andgo vet ./...cleango test ./pkg/etl/...clean against fresh PostgresKnown intermittent
TestTrackCreate_AppliesAccessNormalizationflakes ~10-20% of full-suite runs withcolumn "access_authorities" of relation "tracks" does not exist, even thoughmigrate.Up()returned without error and the migration'sALTER TABLE ... ADD COLUMN IF NOT EXISTSis in place at0024_tracks_access_authorities.up.sql. Passes deterministically in isolation. Predates this PR — looks like a golang-migrate down/up cycle anomaly. Tracked separately; not blocking here.🤖 Generated with Claude Code