Skip to content

feat(sourcemap-issues): Add ensure_sourcemap_detector() provisioning function#109749

Merged
wedamija merged 2 commits intomasterfrom
danf/sourcemap-config-issues/pr3-provisioning
Mar 5, 2026
Merged

feat(sourcemap-issues): Add ensure_sourcemap_detector() provisioning function#109749
wedamija merged 2 commits intomasterfrom
danf/sourcemap-config-issues/pr3-provisioning

Conversation

@wedamija
Copy link
Member

@wedamija wedamija commented Mar 2, 2026

Lazily provisions a Detector with DataConditionGroup, DataConditions, and DetectorState for sourcemap configuration issue detection.

@wedamija wedamija requested review from a team March 2, 2026 23:39
@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Mar 2, 2026
Copy link
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Test doesn't actually verify cache usage
    • Added a third call to ensure_sourcemap_detector and changed mock from objects.filter to objects.get to properly verify cache usage.

Create PR

Or push these changes by commenting:

@cursor push aafa4e3840
Preview (aafa4e3840)
diff --git a/tests/sentry/processing_errors/test_provisioning.py b/tests/sentry/processing_errors/test_provisioning.py
--- a/tests/sentry/processing_errors/test_provisioning.py
+++ b/tests/sentry/processing_errors/test_provisioning.py
@@ -52,10 +52,11 @@
 
     def test_uses_cache_on_second_call(self) -> None:
         ensure_sourcemap_detector(self.project)
+        ensure_sourcemap_detector(self.project)
 
-        with patch.object(Detector.objects, "filter", wraps=Detector.objects.filter) as mock_filter:
+        with patch.object(Detector.objects, "get", wraps=Detector.objects.get) as mock_get:
             ensure_sourcemap_detector(self.project)
-            mock_filter.assert_not_called()
+            mock_get.assert_not_called()
 
     def test_separate_detectors_per_project(self) -> None:
         other_project = self.create_project()
This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

Backend Test Failures

Failures on 9eb1b92 in this run:

tests/snuba/api/endpoints/test_organization_events_timeseries_spans.py::OrganizationEventsStatsSpansMetricsEndpointTest::test_handle_nans_from_snuba_top_nlog
tests/snuba/api/endpoints/test_organization_events_timeseries_spans.py:212: in test_handle_nans_from_snuba_top_n
    assert timeseries["values"] == build_expected_timeseries(
E   AssertionError: assert [{'confidence...ne, ...}, ...] == [{'confidence...Y>, ...}, ...]
E     
E     At index 6 diff: {'timestamp': 1772409600000, 'value': 2.0, 'incomplete': True, 'incompleteReason': 'INCOMPLETE_BUCKET', 'sampleCount': 1, 'sampleRate': 1.0, 'confidence': 'low'} != {'incomplete': False, 'timestamp': 1772409600000.0, 'value': 2, 'sampleCount': <ANY>, 'sampleRate': <ANY>, 'confidence': <ANY>}
E     
E     Full diff:
E       [
E           {
E     -         'confidence': <ANY>,
E     ?                       -- ^^
E     +         'confidence': None,
E     ?                        ^^^
E               'incomplete': False,
E     -         'sampleCount': <ANY>,
E     ?                        ^^^^^
E     +         'sampleCount': 0,
E     ?                        ^
E     -         'sampleRate': <ANY>,
E     ?                       -- ^^
E     +         'sampleRate': None,
E     ?                        ^^^
E     -         'timestamp': 1771891200000.0,
E     ?                                   --
E     +         'timestamp': 1771891200000,
E     -         'value': 0,
E     +         'value': 0.0,
E     ?                  ++
E           },
E           {
E     -         'confidence': <ANY>,
E     ?                       -- ^^
E     +         'confidence': None,
E     ?                        ^^^
E               'incomplete': False,
E     -         'sampleCount': <ANY>,
E     ?                        ^^^^^
E     +         'sampleCount': 0,
E     ?                        ^
E     -         'sampleRate': <ANY>,
E     ?                       -- ^^
E     +         'sampleRate': None,
E     ?                        ^^^
E     -         'timestamp': 1771977600000.0,
E     ?                                   --
E     +         'timestamp': 1771977600000,
E     -         'value': 0,
E     +         'value': 0.0,
E     ?                  ++
E           },
... (110 more lines)

@wedamija wedamija changed the title Add ensure_sourcemap_detector() provisioning function feat(sourcemap-issues): Add ensure_sourcemap_detector() provisioning function Mar 3, 2026
Base automatically changed from danf/sourcemap-config-issues/pr2-detector-handler to master March 5, 2026 00:00
Lazily provisions a Detector with DataConditionGroup, DataConditions, and DetectorState for sourcemap configuration issue detection.
@wedamija wedamija force-pushed the danf/sourcemap-config-issues/pr3-provisioning branch from 0d4bb29 to e9a3ebe Compare March 5, 2026 00:01
…x cache test

The cache was never populated after creating a new detector, so the
second call always hit the DB. Populate the cache after creation.

Also fix test_uses_cache_on_second_call which was mocking
Detector.objects.filter but get_default_detector_for_project uses
objects.get, so the assertion passed vacuously.
Copy link
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

)

cache_key = get_detector_project_type_cache_key(project.id, slug)
cache.set(cache_key, detector, Detector.CACHE_TTL)
Copy link
Contributor

Choose a reason for hiding this comment

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

Cache set before DB transaction commits risks inconsistency

Medium Severity

The cache.set call happens inside the transaction.atomic() block, meaning the cache write (to Redis) executes immediately while the DB transaction hasn't committed yet. If the DB commit subsequently fails, the cache will reference a Detector that doesn't exist in the database. Additionally, a concurrent caller could read from cache between cache.set and transaction commit, receiving a detector whose related objects (condition group, conditions, state) aren't yet visible in the DB. The comparable ensure_default_anomaly_detector function avoids this by not setting cache inside the transaction. The cache write could be moved after the with block or use transaction.on_commit, consistent with patterns seen in sentry/workflow_engine/receivers/detector.py.

Fix in Cursor Fix in Web

@wedamija wedamija merged commit 41cb41f into master Mar 5, 2026
77 checks passed
@wedamija wedamija deleted the danf/sourcemap-config-issues/pr3-provisioning branch March 5, 2026 17:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants