Skip to content

Migrare BSUID scheme to whatsapp#6727

Open
norkans7 wants to merge 4 commits into
mainfrom
dev-n7/whatsapp_bsuid
Open

Migrare BSUID scheme to whatsapp#6727
norkans7 wants to merge 4 commits into
mainfrom
dev-n7/whatsapp_bsuid

Conversation

@norkans7

Copy link
Copy Markdown

No description provided.

norkans7 added 2 commits July 15, 2026 11:59
…coped id

Adds a bsuid_to_whatsapp management command that migrates existing contact URNs
from the bsuid scheme to the whatsapp scheme, keeping the path unchanged:
bsuid:<CC.alphanumeric> -> whatsapp:<CC.alphanumeric>. Phone URNs are never
touched - no tel URNs are created and legacy all-digit whatsapp URNs are left
as-is. Runs in id-ordered batches, bumps modified_on so flipped contacts
reindex, skips a batch on a concurrent-write IntegrityError, and is safe to
re-run.

A bsuid whose whatsapp target already exists on a different contact in the org
is left untouched (uniqueness collision); one that duplicates a whatsapp URN the
same contact already has is redundant, so its message/call/event references are
moved onto the existing whatsapp URN and the bsuid is dropped.

URN.validate/format/normalize now accept a business-scoped user id under the
whatsapp scheme in addition to a legacy phone number, so a contact can carry a
whatsapp URN holding a BSUID value as a valid URN.
Wire Contact._full_release's URN cleanup through the new ContactURN.has_content()
helper instead of hand-rolling the msgs/calls/channel_events check, so the two
can't drift. In the bsuid_to_whatsapp command, compute each URN's target whatsapp
identity once and reuse it for both the collision lookup and the flip.
@claude

claude Bot commented Jul 15, 2026

Copy link
Copy Markdown

Claude finished @norkans7's task in 6m 31s —— View job


Claude PR Review

  • Read changed files and understand context
  • Analyze correctness, security, perf, test coverage
  • Post inline comments
  • Post overall summary

Summary

Overall this is a clean, well-scoped migration: the URN model changes correctly split "legacy digit whatsapp" from "business-scoped whatsapp id" without touching phone flows, has_content() / reassign_content_to() are a nice extract, and the migration command is thoughtfully re-run-safe (cursor advances past collisions, same-contact duplicates reassign message/call/event refs onto the survivor before deleting).

Non-blocking observations (see inline comments):

  • _flip skips a batch on IntegrityError without naming the offending URNs. last_id has already advanced, so the operator only knows "a batch was skipped" and has to re-run + query the DB to find what. Consider logging the id range and/or wrapping the batch in transaction.atomic() so a partial batch never lands.
  • existing lookup is a cross-product on org_id IN (...) AND identity IN (...). Fine at BATCH_SIZE=1000 because the (identity, org) unique index handles it, but noting for future scaling. More substantively: the identity is built via URN.from_parts(WHATSAPP_SCHEME, u.path) with no normalization, so any legacy bsuid row with a lowercase CC path would silently miss its whatsapp collision and later produce a whatsapp: URN that fails URN.validate() (the DB check constraint would still pass). A one-off sanity query before running should confirm none exist.
  • Test coverage gap on modified_on for the redundant-drop pathtest_redundant_bsuid_dropped_and_content_moved verifies the content move but not that the contact gets reindexed. Worth a single assertGreater to lock in that behavior.

Nothing here is a blocker. The behavior around the whatsapp scheme now accepting both digit and business-scoped paths is a transitional widening that will need a follow-up to tighten once callers stop writing the digit form — the comment in models.py already notes this.
· Branch: dev-n7/whatsapp_bsuid

Comment thread temba/contacts/management/commands/bsuid_to_whatsapp.py Outdated
Comment thread temba/contacts/management/commands/bsuid_to_whatsapp.py Outdated
Comment thread temba/contacts/management/commands/tests.py
norkans7 added 2 commits July 15, 2026 12:29
…ex on drop

Apply each bsuid_to_whatsapp batch inside a transaction.atomic() so a concurrent-
write IntegrityError rolls the whole batch back instead of leaving redundant-drop
deletes applied while the flips are skipped. On collision, log the bsuid id range
that was skipped so it can be investigated without a DB query. Also assert the
redundant-drop path reindexes the contact (modified_on bump).
Address remaining PR feedback on bsuid_to_whatsapp:
- Normalize the whatsapp target path (uppercasing the country code) instead of
  carrying the bsuid path across verbatim, so a legacy lowercase-CC bsuid still
  collides with its canonical whatsapp id and the flipped URN passes URN.validate.
- Build the collision lookup as per-org identity sets (Q(org_id=, identity__in=))
  rather than org_id IN ... AND identity IN ..., which is a cross-product that
  could match another org's identical identity.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant