Skip to content

settings: catch IntegrityError and render error in output (Bug 2037991)#1159

Open
cgsheeh wants to merge 4 commits into
mozilla-conduit:mainfrom
cgsheeh:api-key-error-message
Open

settings: catch IntegrityError and render error in output (Bug 2037991)#1159
cgsheeh wants to merge 4 commits into
mozilla-conduit:mainfrom
cgsheeh:api-key-error-message

Conversation

@cgsheeh
Copy link
Copy Markdown
Member

@cgsheeh cgsheeh commented May 13, 2026

Catch the IntegrityError thrown when trying to add a Phab API
key to a profile where there is already an existing PHID associated
with a user profile.

We add a test for this case, and a test for the happy patch since
it is currently untested. Move the phabdouble fixture into the
top-level conftest.py so it can be accessed from the ui app.

Catch the `IntegrityError` thrown when trying to add a Phab API
key to a profile where there is already an existing PHID associated
with a user profile.

We add a test for this case, and a test for the happy patch since
it is currently untested. Move the `phabdouble` fixture into the
top-level `conftest.py` so it can be accessed from the `ui` app.
@cgsheeh cgsheeh requested a review from a team as a code owner May 13, 2026 16:29
@cgsheeh cgsheeh requested a review from Magnolia-Liu May 13, 2026 16:29
@github-actions
Copy link
Copy Markdown

View this pull request in Lando to land it once approved.

Comment thread src/lando/ui/legacy/user_settings.py Outdated

profile.save_phabricator_api_key(api_key, phid=phid)
try:
profile.save_phabricator_api_key(api_key, phid=phid)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not check for existing PHIDs here, avoiding the integrity error altogether?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could, but it would add another DB query on every API key update, and we'd still want to keep the IntegrityError handler to cover the potential race condition (unlikely but technically possible). Happy to change it, this just follows EAFP and is more efficient for the happy path. WDYT?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This endpoint is not used frequently, the extra DB query would be negligible.

The code flow would be more logical if we're explicit about detecting the error state, rather than working around the issue. The integrity error could also (in theory, though very unlikely) occur in a different situation, so here we'd be handling the expected error case that we already discovered.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a check for a duplicate PHID. Personally I don't think it's a meaningful improvement - we're still catching the IntegrityError to catch the race condition, so it's more code for the same functionality - but happy to move forward with it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm what's the point of catching the IntegrityError? We don't need to do that as long as we know there is no duplicate value. Otherwise it would be a misleading error since if triggered, it is some other issue that is causing that and not the PHID.

I would suggest removing the try/except altogether.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm what's the point of catching the IntegrityError? We don't need to do that as long as we know there is no duplicate value. Otherwise it would be a misleading error since if triggered, it is some other issue that is causing that and not the PHID.

The IntegrityError handler covers the race between our .exists() and .save() — without it, two concurrent requests linking the same PHID would 500 instead of returning a clean 400. And since phabricator_phid is the only unique field we touch here, an IntegrityError can't really come from anywhere else.

Yes, the race is unlikely — but the bug is specifically about an unhandled server error, and switching to just an exists() check doesn't actually resolve that; it just makes the window smaller.

This is why I preferred just the try/except version — it was less code, handled both cases, and required fewer DB lookups on the happy path.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To handle the (very unlikely) race condition we could do the check and the save with a lock, but I think that's overkill. This endpoint is infrequently used, I think the basic issue is to present a meaningful error to the user and avoid having a server issue.

I won't split more hairs here but I think preventing an integrity error is better than handling it when it happens.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TL;DR this should be handled as a validation problem, and not a database integrity problem.

@cgsheeh cgsheeh requested a review from zzzeid May 14, 2026 17:19
Copy link
Copy Markdown
Contributor

@zzzeid zzzeid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I won't block this PR on the outstanding details of the implementation, particularly since this endpoint is a legacy one, and requires a revamp/renovation anyway (it should go in lando.api, and should use class-based views, and have overall better validation.)


profile.save_phabricator_api_key(api_key, phid=phid)
try:
profile.save_phabricator_api_key(api_key, phid=phid)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TL;DR this should be handled as a validation problem, and not a database integrity problem.

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.

4 participants