-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
ref(db): Refactor EnvironmentProject to reduce rollbacks #89265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
fc5bb36 to
1cd823c
Compare
src/sentry/models/environment.py
Outdated
| if in_random_rollout("environmentproject.new_add_project.rollout"): | ||
| _, created = EnvironmentProject.objects.get_or_create( | ||
| project=project, environment=self, defaults={"is_hidden": is_hidden} | ||
| ) | ||
| if not created: | ||
| # We've already created the object, should still cache the action. | ||
| cache.set(cache_key, 1, 3600) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just a refactor without changing any logic that was being done before:
is_hiddenis only set during creation - same as it was before- if the EnvironmentProject already exists, we write to cache - same as it was before (assumption is that this is a protection on db to not overload it with to many write requests, we keep it as cache lookup is less expensive than DB lookup)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we also write to cache when the EnvironmentProject record is first created? I know that is a change in logic, but it would help reduce the number of queries we're running.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's not a change in logic to cache both paths. Previously, we'd cache immediately after create and inside the exception. So it's more correct to remove if not created and just cache both
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, edited the code to always cache the value
Codecov ReportAll modified and coverable lines are covered by tests ✅ ✅ All tests successful. No failed tests found. Additional details and impacted files@@ Coverage Diff @@
## master #89265 +/- ##
==========================================
+ Coverage 87.73% 87.75% +0.01%
==========================================
Files 10172 10138 -34
Lines 574129 573043 -1086
Branches 22612 22425 -187
==========================================
- Hits 503728 502863 -865
+ Misses 69985 69743 -242
- Partials 416 437 +21 |
src/sentry/models/environment.py
Outdated
| if in_random_rollout("environmentproject.new_add_project.rollout"): | ||
| _, created = EnvironmentProject.objects.get_or_create( | ||
| project=project, environment=self, defaults={"is_hidden": is_hidden} | ||
| ) | ||
| if not created: | ||
| # We've already created the object, should still cache the action. | ||
| cache.set(cache_key, 1, 3600) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we also write to cache when the EnvironmentProject record is first created? I know that is a change in logic, but it would help reduce the number of queries we're running.
…90042) After rolling out to 100% last week, we can now safely remove old code which is no longer used/ Continuation of getsentry/sentry-options-automator#3597 and #89265
Similar to how it was done in: #88885 Refactor of `add_project` method of `Environment` model, preparing it for gradual rollout and to decrease the number of rollbacks it does since almost every attempt of insertions for this model results in a rollback. In this method `EnvironmentProject` was doing overly optimistic inserts leading to us having almost 100 rollbacks/second coming just from this model ## Why are we doing this Currently we are doing around 300 rollbacks per second, mostly caused by overly optimistic writes - almost all of the writes result in the rollback because the data already exists in the table, and for those occasions `get_or_create` is more suitable since SELECT statement is more performant than ROLLBACK when they happen most of the times. [Datadog notebok with investagtion](https://app.datadoghq.com/notebook/12067672/postgres-rollback-investigation?range=604800000&start=1743184480708&live=true), where 3 problematic models where detected: - ~GroupRelease~ - `Commit` - `EnvironmentProject` Models will be refactored one at the time, and the refactor will be rolled out gradually: 10% - 50% - 100%
…90042) After rolling out to 100% last week, we can now safely remove old code which is no longer used/ Continuation of getsentry/sentry-options-automator#3597 and #89265
Similar to how it was done in: #88885
Refactor of
add_projectmethod ofEnvironmentmodel, preparing it for gradual rollout and to decrease the number of rollbacks it does since almost every attempt of insertions for this model results in a rollback.In this method
EnvironmentProjectwas doing overly optimistic inserts leading to us having almost 100 rollbacks/second coming just from this modelWhy are we doing this
Currently we are doing around 300 rollbacks per second, mostly caused by overly optimistic writes - almost all of the writes result in the rollback because the data already exists in the table, and for those occasions
get_or_createis more suitable since SELECT statement is more performant than ROLLBACK when they happen most of the times.Datadog notebok with investagtion, where 3 problematic models where detected:
GroupReleaseCommitEnvironmentProjectModels will be refactored one at the time, and the refactor will be rolled out gradually: 10% - 50% - 100%