Skip to content

perf: skip unnecessary shared user queries#1968

Open
boxford-icci wants to merge 4 commits into
Zipstack:mainfrom
boxford-icci:perf/skip-shared-user-queries
Open

perf: skip unnecessary shared user queries#1968
boxford-icci wants to merge 4 commits into
Zipstack:mainfrom
boxford-icci:perf/skip-shared-user-queries

Conversation

@boxford-icci
Copy link
Copy Markdown

Summary

  • skip shared_users lookups in shareable resource partial_update handlers unless the request actually updates sharing
  • reuse the adapter pre-update shared_users snapshot instead of querying the same M2M relation twice before the update
  • add regression tests for the non-sharing update path and the adapter query reuse path

Why

This was the highest-impact, lowest-effort performance win from the audit: these endpoints were paying for M2M reads on every partial update, even when the request changed unrelated fields, and adapters were issuing the same pre-update query twice.

Validation

  • python3 -m py_compile backend/adapter_processor_v2/views.py backend/workflow_manager/workflow_v2/views.py backend/pipeline_v2/views.py backend/connector_v2/views.py backend/prompt_studio/prompt_studio_core_v2/views.py backend/api_v2/api_deployment_views.py backend/utils/tests/test_shared_user_query_optimizations.py
  • uv run ... local lint/test execution is currently blocked by repository uv.lock parse errors (banks wheel version mismatch and ambiguous office365-rest-python-client source)

Avoid loading shared_users during partial updates unless the request actually changes sharing, and reuse the pre-update shared user snapshot in adapter updates instead of querying it twice. Add regression tests covering the non-sharing update path and the adapter query reuse path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented May 14, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 14, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c236c060-3aec-4027-bc4e-806e836694be

📥 Commits

Reviewing files that changed from the base of the PR and between 3b9a507 and 2c552a3.

📒 Files selected for processing (2)
  • backend/adapter_processor_v2/views.py
  • backend/utils/tests/test_shared_user_query_optimizations.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/adapter_processor_v2/views.py

Summary by CodeRabbit

  • Refactor

    • Optimized shared-user query handling during resource updates; unnecessary database queries are now skipped when sharing settings remain unchanged.
    • Enhanced notification logic for sharing updates, ensuring email notifications are delivered more reliably.
  • Tests

    • Added test coverage validating shared-user query optimization behavior.

Walkthrough

Viewset partial_update handlers were refactored to compute a single shared_users_updated boolean from the presence of "shared_users" in the request, and to only fetch/compare current shared users when that flag is true. Tests added to assert unnecessary shared-user queries are avoided.

Changes

Shared-user update gating and query optimization

Layer / File(s) Summary
Shared-users flag and conditional snapshot
backend/adapter_processor_v2/views.py, backend/api_v2/api_deployment_views.py, backend/connector_v2/views.py, backend/pipeline_v2/views.py, backend/workflow_manager/workflow_v2/views.py
Each partial_update now sets shared_users_updated = "shared_users" in request.data and only computes current_shared_users (and related pre-update sets) when that flag is true. Notification gating after update now checks response.status_code == 200 and shared_users_updated and notification_plugin.
Prompt Studio custom tool sharing
backend/prompt_studio/prompt_studio_core_v2/views.py
Same shared_users_updated pattern applied to custom_tool.shared_users: snapshot only when updating shared_users and gate notification logic on the flag.
Tests validating query behaviour
backend/utils/tests/test_shared_user_query_optimizations.py
Adds tests: one ensures WorkflowViewSet.partial_update does not call workflow.shared_users.all() when shared_users is not in the request; another ensures AdapterInstanceViewSet.partial_update queries shared_users.all() exactly once when shared_users is provided and the notification plugin is disabled.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description includes a clear Summary section explaining what was changed and why, plus validation steps. However, most required sections from the template (What, How, Can this PR break existing features, Database Migrations, Env Config, etc.) are missing or not filled out. Fill out the missing template sections: provide detailed What/How sections, explicitly address whether existing features could break, confirm no database migrations needed, and complete other required fields.
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main performance optimization: skipping unnecessary shared user database queries during partial updates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 14, 2026

Greptile Summary

This PR optimizes partial_update handlers across six shareable-resource viewsets by skipping M2M shared_users snapshot queries when the request does not include a shared_users field, and eliminates a duplicate pre-update query in AdapterInstanceViewSet by reusing the snapshot instead of re-fetching it.

  • Six views updated (AdapterInstanceViewSet, WorkflowViewSet, ConnectorInstanceViewSet, PipelineViewSet, PromptStudioCoreView, APIDeploymentViewSet): a shared_users_updated flag gates the snapshot fetch, so non-sharing partial updates no longer pay for an M2M read.
  • Bonus fix in AdapterInstanceViewSet: the original notification block had no guard for notification_plugin being None, which would crash with a TypeError if the plugin was absent and users were newly shared; the PR adds bool(notification_plugin) to the outer condition.
  • Two regression tests added in test_shared_user_query_optimizations.py: one asserts shared_users.all() is never called for a non-sharing workflow update; the other asserts the adapter path calls it exactly once (not twice) when notification_plugin is None.

Confidence Score: 5/5

All six view changes are mechanically equivalent guard additions; no notification or removal logic is altered.

The refactoring is narrow and consistent: a boolean flag replaces an inline membership test, and the downstream notification and removed-user logic is untouched. The adapter view gets a meaningful bonus fix preventing a potential TypeError when notification_plugin is absent. All code paths that previously ran continue to run; only the unconditional M2M reads on non-sharing updates are eliminated.

No files require special attention; the changes are low-risk and symmetric across all six views.

Important Files Changed

Filename Overview
backend/adapter_processor_v2/views.py Skips M2M snapshot when shared_users not in request; reuses snapshot to avoid duplicate query for current_users; adds notification_plugin guard (bug-fix side-effect)
backend/workflow_manager/workflow_v2/views.py Guards M2M snapshot behind shared_users_updated flag; no other logic changes
backend/connector_v2/views.py Mirrors the same shared_users_updated guard pattern; no other logic changes
backend/pipeline_v2/views.py Mirrors the same shared_users_updated guard pattern with minor formatting cleanup on the outer if condition
backend/prompt_studio/prompt_studio_core_v2/views.py Applies the same skip guard; notification_plugin is lazily loaded inside the block (different pattern but correct)
backend/api_v2/api_deployment_views.py Applies the same skip guard; notification_plugin reformatted inline but semantically unchanged
backend/utils/tests/test_shared_user_query_optimizations.py New regression tests covering skip-path for WorkflowViewSet and query-reuse for AdapterInstanceViewSet; four other changed views lack skip-path coverage

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[partial_update called] --> B{shared_users in request.data}
    B -- No --> C[Skip M2M query]
    B -- Yes --> D[Fetch current_shared_users from DB]
    D --> E[Compute removed_users from snapshot]
    C --> F[Call super partial_update]
    E --> F
    F --> G{status 200 AND shared_users_updated AND notification_plugin}
    G -- No --> H[Return response]
    G -- Yes --> I[refresh_from_db and fetch new_shared_users]
    I --> J[Send sharing notifications]
    J --> H
Loading

Reviews (2): Last reviewed commit: "[pre-commit.ci] auto fixes from pre-comm..." | Re-trigger Greptile

Comment on lines +1 to +9
from types import SimpleNamespace
from unittest.mock import MagicMock, patch

from rest_framework import status, viewsets
from rest_framework.response import Response

from adapter_processor_v2.views import AdapterInstanceViewSet
from workflow_manager.workflow_v2.views import WorkflowViewSet

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.

P2 Missing skip-path coverage for four changed views

The test file only exercises WorkflowViewSet and AdapterInstanceViewSet, but ConnectorInstanceViewSet, PipelineViewSet, PromptStudioCoreView, and APIDeploymentViewSet all received the same guard change. A regression in any of those four (e.g. accidentally removing the shared_users_updated guard) would go undetected. The skip-path test for WorkflowViewSet is a single-function template that could be copy-adapted for each missing view in a few lines.

Prompt To Fix With AI
This is a comment left during a code review.
Path: backend/utils/tests/test_shared_user_query_optimizations.py
Line: 1-9

Comment:
**Missing skip-path coverage for four changed views**

The test file only exercises `WorkflowViewSet` and `AdapterInstanceViewSet`, but `ConnectorInstanceViewSet`, `PipelineViewSet`, `PromptStudioCoreView`, and `APIDeploymentViewSet` all received the same guard change. A regression in any of those four (e.g. accidentally removing the `shared_users_updated` guard) would go undetected. The skip-path test for `WorkflowViewSet` is a single-function template that could be copy-adapted for each missing view in a few lines.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
backend/utils/tests/test_shared_user_query_optimizations.py (1)

1-60: ⚡ Quick win

Consider expanding test coverage to all refactored viewsets.

The tests verify the optimization for WorkflowViewSet and AdapterInstanceViewSet, but four other viewsets received the same refactor: PromptStudioCoreView, APIDeploymentViewSet, PipelineViewSet, and ConnectorInstanceViewSet. Adding similar test coverage for these would provide stronger regression protection.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/utils/tests/test_shared_user_query_optimizations.py` around lines 1 -
60, Add tests mirroring the two existing cases for the four refactored viewsets
(PromptStudioCoreView, APIDeploymentViewSet, PipelineViewSet,
ConnectorInstanceViewSet): for each viewset write one test like
test_workflow_partial_update_skips_shared_user_lookup_without_share_changes that
patches <View>.get_object to return a MagicMock whose shared_users.all raises an
AssertionError and asserts shared_users.all.assert_not_called() when
request.data has no shared_users, and another test like
test_adapter_partial_update_reuses_pre_update_shared_users that sets
shared_users.all to return the same list twice, patches <View>.get_object and
viewsets.ModelViewSet.partial_update, invokes <View>.partial_update(request)
with request.data containing shared_users, then asserts response.status_code is
HTTP_200_OK and that shared_users.all.call_count == 2 to verify reuse; follow
the same mocking/patch pattern used for WorkflowViewSet and
AdapterInstanceViewSet.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@backend/utils/tests/test_shared_user_query_optimizations.py`:
- Around line 1-60: Add tests mirroring the two existing cases for the four
refactored viewsets (PromptStudioCoreView, APIDeploymentViewSet,
PipelineViewSet, ConnectorInstanceViewSet): for each viewset write one test like
test_workflow_partial_update_skips_shared_user_lookup_without_share_changes that
patches <View>.get_object to return a MagicMock whose shared_users.all raises an
AssertionError and asserts shared_users.all.assert_not_called() when
request.data has no shared_users, and another test like
test_adapter_partial_update_reuses_pre_update_shared_users that sets
shared_users.all to return the same list twice, patches <View>.get_object and
viewsets.ModelViewSet.partial_update, invokes <View>.partial_update(request)
with request.data containing shared_users, then asserts response.status_code is
HTTP_200_OK and that shared_users.all.call_count == 2 to verify reuse; follow
the same mocking/patch pattern used for WorkflowViewSet and
AdapterInstanceViewSet.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: add5b873-feb1-4a4e-bc8b-7234cad3999f

📥 Commits

Reviewing files that changed from the base of the PR and between 993f676 and 3b9a507.

📒 Files selected for processing (7)
  • backend/adapter_processor_v2/views.py
  • backend/api_v2/api_deployment_views.py
  • backend/connector_v2/views.py
  • backend/pipeline_v2/views.py
  • backend/prompt_studio/prompt_studio_core_v2/views.py
  • backend/utils/tests/test_shared_user_query_optimizations.py
  • backend/workflow_manager/workflow_v2/views.py

boxford-icci and others added 2 commits May 14, 2026 14:38
The other 4 resource viewsets (workflow, pipeline, connector, api_deployment)
all gate their post-update shared_users comparison block on notification_plugin
being truthy. The adapter viewset was missing this check, causing an extra
refresh_from_db() + shared_users.all() round-trip on every share/unshare
even when no notification plugin is installed.

Update the test to patch notification_plugin=None explicitly and assert
call_count==1 (pre-update snapshot only), which precisely pins the
elimination of the old duplicate ID-extraction query.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@sonarqubecloud
Copy link
Copy Markdown

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.

2 participants