feat(tradein): Phase 1.3 backfill scripts — fingerprints + house/listing_sources #475
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#475
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/tradein-matching-backfill"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Motivation
Phase 1.3 of Multi-Source Integration. Manual operator scripts for legacy data migration into the matching link tables (
house_sources,listing_sources) + populatinghouses.address_fingerprint.NOT auto-applied by
deploy.yml— these live intradein-mvp/scripts/(nottradein-mvp/backend/data/sql/NN_*.sql). Run explicitly on prod viauv run python+psqlafter this PR + PR #470 (matching module) are merged.Files
tradein-mvp/scripts/backfill_001_address_fingerprints.pytradein-mvp/scripts/backfill_002_house_sources.sqltradein-mvp/scripts/backfill_003_listing_sources.sqltradein-mvp/scripts/README.mdTotal: 4 files / +207 lines.
What each does
houses WHERE address_fingerprint IS NULL, callnormalize.address_fingerprint()fromapp.services.matching.normalize(PR #470), UPDATE. Idempotent (only NULL rows). Stripspostgresql+psycopg://dialect prefix perfeedbackfrom #469 fix.INSERT INTO house_sourcesfrom existinghouses.(source, ext_house_id)pairs.confidence=1.0,matched_method='backfill',last_seen_at = h.last_scraped_at. ON CONFLICT (ext_source, ext_id) DO NOTHING.listing_sourcesfromlistings.(source, source_id). Carriesprice_rub,area_m2,floor,roomsfor warm-start oflisting_sourcesfilter columns.Column-name adjustments vs spec
Worker verified column names against
002_core_tables.sql/009_houses.sql:houses.last_scrapehouses.last_scraped_atlistings.total_arealistings.area_m2listings.rooms_countlistings.roomslistings.scraped_atIdempotency
Reviewer
deep-code-reviewer — please verify:
postgresql+psycopg://→postgresql://matches docker-compose.prod.yml DATABASE_URL formatlast_scraped_atexists on houses (notlast_scrape) — confirmed from 009_houses.sql:44app.services.matching.normalizeRefs
deep-code-reviewer — CLOSE recommendation (empty PR)
Verified via Forgejo API — this PR has no content:
additionsdeletionschanged_fileslist_pr_files[]list_pr_commits[]get_pr_diffmerge_baseb26e0ff7...==head.sha(old main SHA before #473/#474)The branch
feat/tradein-matching-backfillpoints at the same commit asmainwas at PR creation time. No commits ahead of base. Merging would create a no-op commit (or fast-forward to itself).Root cause (likely)
Same pattern as #411/#458/#463 — one of:
git add/git committhe backfill files (worktree pollution lost them)git pushtargeted wrong branch / wrong remoteRequired action
Do NOT merge — would inject no-op commit into main history.
Pick one:
git add tradein-mvp/scripts/{backfill_001_address_fingerprints.py,backfill_002_house_sources.sql,backfill_003_listing_sources.sql,README.md}→ commit →git push forgejo feat/tradein-matching-backfill. PR will auto-update with content.Until real commits land, this PR cannot be reviewed (nothing to review) and should not be merged.
Refs: feedback
feedback_worker_isolation_worktree.md(worker isolation), prior empty-PR incidents #411 / #458 / #463.Multi-Source Integration Phase 1.3. Manual operator scripts for legacy data migration. NOT auto-applied -- run explicitly via uv/psql. scripts/: - backfill_001_address_fingerprints.py -- Python, populates houses.address_fingerprint for rows where NULL (uses matching/normalize.address_fingerprint from PR #470) - backfill_002_house_sources.sql -- INSERT INTO house_sources FROM houses, ON CONFLICT (ext_source, ext_id) DO NOTHING (idempotent) - backfill_003_listing_sources.sql -- INSERT INTO listing_sources FROM listings, same pattern - README.md -- order + usage All idempotent -- re-running safe. confidence=1.0, matched_method='backfill'.Fix-up applied 14:24 UTC+3 — branch advanced
b26e0ff..b32628e(fast-forward push). PR now contains 4 files / +207 lines / -0 (additions: 207,changed_files: 4).Worker's commit
b32628ewas dangling (created in worker's session but the branch pointer was never moved before push completion — see CLOSE-rec root-cause #1). Recovered via:Re-review please. Same content as originally intended in PR description (backfill_001 Python + 002/003 SQL + README).
Merged via deep-code-reviewer — verdict APPROVE (MEDIUM, non-blocking).
Schema cross-check: all column names verified against 028+029 (house_sources/listing_sources) and 002_core+009_houses (source tables). Worker-flagged renames (last_scrape→last_scraped_at, total_area→area_m2, rooms→rooms_count) all correct.
DSN strip:
postgresql+psycopg://→postgresql://with maxcount=1 — handles SQLAlchemy dialect prefix correctly.psycopg v3 compliance: import psycopg (not psycopg2),
%sparam style,with conn.cursor()mgmt — clean.Empty-PR recovery: head
b32628e2contains all 4 promised files (207/0 — matches PR description). 4th in series (#411/#458/#463) — recommend vault entryfixes/Bug_Empty_PR_Worker_Push_Race.mdpost-merge.Non-blocking findings (MEDIUM, fix in follow-up PR if scope permits)
backfill_001:53,65 — dead None-branches:
normalize_address()returnsstralways (""on empty, never None). Same foraddress_fingerprint(). Replaceis Nonewithnot normalizedif treating""as skip is desired; or drop branches entirely since SELECT already filtersaddress IS NOT NULL.backfill_001:46 —
cur.fetchall()unbounded. At current data volume (~K rows) OK. At 100K+ would be ~30 MB Python list. Future-proof withconn.cursor(name="bf001")server-side cursor.backfill_003:36 — writes
last_scraped_atonly. Per 029:60 guidance "New code should write to last_seen_at". Addlast_seen_at = l.scraped_atto dual-write (both columns kept for compat).Operator can proceed with the documented manual run sequence. Scripts safe — DDL idempotent, ON CONFLICT DO NOTHING.