Skip to content

Optimize GitHub app IssueNode - #4609

Merged
arkid15r merged 19 commits into
OWASP:feature/graphql-dataloadersfrom
ahmedxgouda:dataloaders/github-issue
Jun 21, 2026
Merged

arkid15r merged 19 commits into
OWASP:feature/graphql-dataloadersfrom
ahmedxgouda:dataloaders/github-issue

Conversation

@ahmedxgouda

@ahmedxgouda ahmedxgouda commented May 4, 2026 •

Copy link
Copy Markdown
Collaborator

Proposed change

Resolves #4598

  • Added a custom GraphQL context to preserve dataloaders per request (so not two users use the same dataloader instance which caches the results)
  • Added a custom Asynchronous GraphQL view
  • Converted synchronous ORM operations like count to Asynchronous to avoid SynchronousOnlyOperation exception
  • Used sync_to_async with methods that may be used across other parts in the app rather than the resolver
  • Added a DataLoader for interested_users which fixed N+1 queries problem for the resolver (see the video embedded)
  • Added a utils for DataLoaders to reuse the sort function
  • Added pytest-asyncio for asynchronous tests
  • Added/updated tests

The code to check the number of db commits:

select datname, xact_commit from pg_stat_database;
GitHub.IssueNode.mp4

Checklist

  • Required: I followed the contributing workflow
  • Required: I verified that my code works as intended and resolves the issue as described
  • Required: I ran make check-test locally: all warnings addressed, tests passed
  • I used AI for code, documentation, tests, or communication related to this PR

@coderabbitai

coderabbitai Bot commented May 4, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a generic async dataloader utility, implements an interested-users DataLoader, wires per-request dataloaders into GraphQL context via a custom AsyncGraphQLView, converts several Strawberry resolvers to async Django ORM calls, and updates tests and pytest config for async execution.

Changes

Dataloader Infrastructure & Async Resolver Migration

Layer / File(s) Summary
Shared Dataloader Utility
backend/apps/common/api/internal/dataloaders/utils.py
get_results_by_keys asynchronously iterates a QuerySet, groups items by a dynamic key_field, and returns lists of value_field values aligned to the provided keys (empty list for missing keys).
Interested-users DataLoader
backend/apps/github/api/internal/dataloaders/interested_users.py, backend/apps/github/api/internal/dataloaders/__init__.py
Adds load_interested_users(issue_ids) (queries IssueUserInterest, select_related("user__owasp_profile"), filter(issue_id__in=...), order_by("user__login")) and get_interested_users_loader(); exposes INTERESTED_USERS_LOADER key and get_github_dataloaders() registry.
IssueNode resolver wiring
backend/apps/github/api/internal/nodes/issue.py
Replaces the prefetch-based interested_users resolver with an async field that loads users via info.context.github_dataloaders[INTERESTED_USERS_LOADER].load(root.pk).
GraphQL Context & View
backend/settings/graphql_context.py, backend/settings/graphql.py, backend/settings/urls.py
Add NestGraphQLContext (initializes github_dataloaders per request), NestGraphQLView.get_context returning that context, and update the /graphql/ URL to use NestGraphQLView.
Async resolver conversions
backend/apps/github/api/internal/queries/organization.py, backend/apps/mentorship/api/internal/queries/module.py, backend/apps/mentorship/api/internal/queries/program.py, backend/apps/owasp/api/internal/queries/stats.py
Switch decorators to @strawberry_django.field, make resolvers async, and replace synchronous ORM calls (.get(), .count(), default-workspace lookup) with async variants (.aget(), .acount(), .afirst()); add explicit OWASP workspace lookup via OWASP_WORKSPACE_ID in stats.
Tests & pytest config
backend/tests/unit/..., backend/pyproject.toml
Add/convert unit tests to async using pytest-asyncio and AsyncMock; add tests for get_results_by_keys and interested-users dataloader; enable pytest asyncio mode and add pytest-asyncio to test deps.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • OWASP/Nest#3788: Related optimization of IssueNode.interested_users via nested prefetch patterns; overlaps with the dataloader approach introduced here.

Suggested reviewers

  • kasya
  • arkid15r
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes out-of-scope changes beyond the linked issue #4598, converting synchronous ORM operations to async in multiple unrelated modules (organization.py, module.py, program.py, stats.py) that are not required by the issue. Remove or defer async conversions unrelated to the IssueNode optimization, or update the linked issue to reflect the expanded scope of work.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Optimize GitHub app IssueNode' directly summarizes the main change: optimizing the IssueNode resolver by implementing dataloaders and converting to async operations.
Description check ✅ Passed The description is directly related to the changeset, providing context about dataloaders, async conversions, N+1 query fixes, and test additions that match the file modifications.
Linked Issues check ✅ Passed The PR successfully implements the DataLoader for interested_users resolver as required by issue #4598, with proper batching, database optimization, and supporting infrastructure for async GraphQL operations.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

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

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.

@coderabbitai

coderabbitai Bot commented May 4, 2026 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Added batch data loading infrastructure for GitHub issue interested users queries to enhance performance.
  • Refactor

    • Refactored interested users field resolution on GitHub issues to use async dataloaders for improved efficiency.
    • Updated GraphQL context and view configuration to support dataloader-based data resolution.
  • Tests

    • Updated unit tests to validate async dataloader functionality for interested users queries.

Walkthrough

This PR implements a DataLoader optimization for the IssueNode.interested_users GraphQL field. A shared async utility groups batch query results by key, a GitHub-specific dataloader batches issue-to-interested-users lookups, and the GraphQL context is extended to inject dataloaders per request. The resolver switches from eager-loaded prefetch to async dataloader-based resolution.

Changes

DataLoader Implementation for Interested Users

Layer / File(s) Summary
Shared Utility
backend/apps/common/api/internal/dataloaders/utils.py
results_by_keys groups QuerySet results by a dynamic key field and returns value lists ordered to match input keys.
Dataloader Factory & Batch Logic
backend/apps/github/api/internal/dataloaders/__init__.py, backend/apps/github/api/internal/dataloaders/interested_users.py
make_github_dataloaders() constructs a dataloader dict; load_interested_users batch-fetches IssueUserInterest records, eager-loads related user profiles, and groups users by issue ID via results_by_keys.
GraphQL Context & View
backend/settings/graphql_context.py, backend/settings/graphql.py
NestGraphQLContext initializes github_dataloaders on each context instance; NestGraphQLView overrides get_context to instantiate and return the context with request/response parameters.
URL & View Wiring
backend/settings/urls.py
GraphQL endpoint switched to use NestGraphQLView instead of the default GraphQLView, preserving CSRF protection and schema.
Resolver Integration
backend/apps/github/api/internal/nodes/issue.py
IssueNode.interested_users refactored to async resolution using info.context.github_dataloaders["interested_users_loader"].load(root.pk), removing prefetch-based queryset logic and IssueUserInterest import.
Test Updates
backend/tests/unit/apps/github/api/internal/nodes/issue_test.py
test_interested_users updated to mock async dataloader, verify load is awaited with the issue PK, and assert returned users; test imports updated for asyncio and AsyncMock.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Optimize GitHub app IssueNode' is clear and directly related to the main change—optimizing the IssueNode by implementing a DataLoader for the interested_users resolver.
Description check ✅ Passed The description mentions resolving #4598 and includes a checklist, which relates to the changeset, though it contains placeholder text and incomplete items.
Linked Issues check ✅ Passed The PR fully implements the requirements from issue #4598: a DataLoader for interested_users resolver [4598] is implemented, and it loads interested users based on issue id [4598].
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the DataLoader optimization for interested_users. Supporting infrastructure (context, view, utils) is necessary for the core objective.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ 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
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

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

@codecov

codecov Bot commented May 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 25.00000% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 98.87%. Comparing base (82a8651) to head (9c8e4ef).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...ithub/api/internal/dataloaders/interested_users.py 0.00% 9 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4609      +/-   ##
==========================================
- Coverage   98.92%   98.87%   -0.06%     
==========================================
  Files         527      528       +1     
  Lines       16956    16964       +8     
  Branches     2360     2360              
==========================================
- Hits        16774    16773       -1     
- Misses         97      106       +9     
  Partials       85       85              
Flag Coverage Δ
backend 99.43% <25.00%> (-0.08%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
backend/apps/github/api/internal/nodes/issue.py 100.00% <100.00%> (ø)
...ithub/api/internal/dataloaders/interested_users.py 0.00% <0.00%> (ø)

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 82a8651...9c8e4ef. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codecov

codecov Bot commented May 4, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.74%. Comparing base (3cd6960) to head (4936af0).
⚠️ Report is 1 commits behind head on feature/graphql-dataloaders.

Additional details and impacted files

Impacted file tree graph

@@                     Coverage Diff                      @@
##           feature/graphql-dataloaders    #4609   +/-   ##
============================================================
  Coverage                        98.74%   98.74%           
============================================================
  Files                              538      540    +2     
  Lines                            17068    17095   +27     
  Branches                          2421     2422    +1     
============================================================
+ Hits                             16853    16880   +27     
  Misses                             123      123           
  Partials                            92       92           
Flag Coverage Δ
backend 99.45% <100.00%> (+<0.01%) ⬆️
frontend 96.71% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...kend/apps/common/api/internal/dataloaders/utils.py 100.00% <100.00%> (ø)
backend/apps/github/api/internal/nodes/issue.py 100.00% <100.00%> (ø)
...d/apps/github/api/internal/queries/organization.py 100.00% <100.00%> (ø)
...rship/api/internal/dataloaders/interested_users.py 100.00% <100.00%> (ø)
...end/apps/mentorship/api/internal/queries/module.py 94.02% <100.00%> (+0.18%) ⬆️
...nd/apps/mentorship/api/internal/queries/program.py 100.00% <100.00%> (ø)
backend/apps/owasp/api/internal/queries/stats.py 100.00% <100.00%> (ø)

Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0e01430...4936af0. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes May 4, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

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.

No issues found across 9 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

@coderabbitai coderabbitai Bot left a comment

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.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/apps/github/api/internal/dataloaders/__init__.py`:
- Around line 8-10: Extract the literal loader key into a module-level constant
(e.g., INTERESTED_USERS_LOADER) in
backend/apps/github/api/internal/dataloaders/__init__.py and use it as the dict
key when returning {"INTERESTED_USERS_LOADER": make_interested_users_loader()}
(replace the quoted literal with the constant); then update any consumers
(notably the use in issue.py where the string "interested_users_loader" is
referenced) to import INTERESTED_USERS_LOADER from the dataloaders package and
use that constant instead of the bare string to avoid brittle duplicates/typos.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 821bc7cd-9a33-42f3-89e2-b7fc6e6722a9

📥 Commits

Reviewing files that changed from the base of the PR and between 87daa87 and 9c8e4ef.

📒 Files selected for processing (9)
  • backend/apps/common/api/internal/dataloaders/__init__.py
  • backend/apps/common/api/internal/dataloaders/utils.py
  • backend/apps/github/api/internal/dataloaders/__init__.py
  • backend/apps/github/api/internal/dataloaders/interested_users.py
  • backend/apps/github/api/internal/nodes/issue.py
  • backend/settings/graphql.py
  • backend/settings/graphql_context.py
  • backend/settings/urls.py
  • backend/tests/unit/apps/github/api/internal/nodes/issue_test.py

@ahmedxgouda
ahmedxgouda changed the base branch from main to feature/graphql-dataloaders May 6, 2026 03:48
@ahmedxgouda
ahmedxgouda dismissed cubic-dev-ai[bot]’s stale review May 6, 2026 03:48

The base branch was changed.

@coderabbitai coderabbitai Bot left a comment

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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
backend/tests/unit/apps/owasp/api/internal/queries/stats_test.py (1)

17-37: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Assert the workspace lookup uses OWASP_WORKSPACE_ID.

Both tests stub the filtered queryset, but neither verifies the resolver actually calls Workspace.objects.filter(slack_workspace_id=OWASP_WORKSPACE_ID). A regression to the wrong filter would still pass here.

Suggested test hardening
 import asyncio
 from unittest.mock import AsyncMock, MagicMock, patch

+from apps.slack.constants import OWASP_WORKSPACE_ID
 from apps.owasp.api.internal.queries.stats import StatsQuery
             query = StatsQuery()
             result = asyncio.run(query.stats_overview())

+            mock_workspace_cls.objects.filter.assert_called_once_with(
+                slack_workspace_id=OWASP_WORKSPACE_ID
+            )
             assert result.active_projects_stats == 270
             assert result.active_chapters_stats == 340
             assert result.contributors_stats == 15000
             assert result.countries_stats == 90
             assert result.slack_workspace_stats == 5000
             query = StatsQuery()
             result = asyncio.run(query.stats_overview())
+
+            mock_workspace_cls.objects.filter.assert_called_once_with(
+                slack_workspace_id=OWASP_WORKSPACE_ID
+            )
             assert result.slack_workspace_stats == 0

Also applies to: 47-65

🤖 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/tests/unit/apps/owasp/api/internal/queries/stats_test.py` around
lines 17 - 37, The workspace lookup in the StatsQuery tests must be asserted to
ensure Workspace.objects.filter is called with the constant OWASP_WORKSPACE_ID;
update the test(s) in stats_test.py (where StatsQuery().stats_overview() is
invoked) to assert that mock_workspace_cls.objects.filter was called with
slack_workspace_id=OWASP_WORKSPACE_ID (e.g. assert_called_once_with or
assert_called_with), and add the same assertion in the second test block
referenced (lines ~47-65) so the resolver’s filter argument is validated for
regressions.
backend/apps/mentorship/api/internal/queries/module.py (1)

28-31: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Wrap program.user_has_access with sync_to_async in async context.

user_has_access performs synchronous ORM queries (self.admins.filter(nest_user=user).exists() and self.modules.filter(...).exists()), but is called synchronously from the async get_program_modules resolver. This will raise SynchronousOnlyOperation. Use sync_to_async to safely call it from async context:

from asgiref.sync import sync_to_async

if program.status != Program.ProgramStatus.PUBLISHED and not await sync_to_async(
    program.user_has_access
)(info.context.request.user):
    return []
🤖 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/apps/mentorship/api/internal/queries/module.py` around lines 28 - 31,
The async resolver get_program_modules calls the synchronous method
program.user_has_access which performs ORM queries and will raise
SynchronousOnlyOperation; wrap the call with asgiref.sync.sync_to_async and
await it instead of calling directly (import sync_to_async and replace the
direct program.user_has_access(...) call with await
sync_to_async(program.user_has_access)(info.context.request.user)), keeping the
existing conditional logic intact so the published-status check still
short-circuits.
backend/apps/mentorship/api/internal/queries/program.py (1)

36-39: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Wrap program.user_has_access with sync_to_async in this async resolver.

This async resolver calls program.user_has_access(...), which synchronously performs ORM operations (.filter().exists()). This will raise SynchronousOnlyOperation at runtime. The same issue exists in module.py:get_program_modules (line 28).

Fix
+from asgiref.sync import sync_to_async
 
         if program.status != Program.ProgramStatus.PUBLISHED and not await sync_to_async(
             program.user_has_access
         )(info.context.request.user):
             return None
🤖 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/apps/mentorship/api/internal/queries/program.py` around lines 36 -
39, The async resolver in program.py calls the synchronous method
program.user_has_access(...) which performs ORM work and must be awaited via an
async wrapper; import sync_to_async (from asgiref.sync), replace direct calls to
program.user_has_access(...) with await
sync_to_async(program.user_has_access)(info.context.request.user) (and do the
same fix in module.py's get_program_modules around the call at line 28),
ensuring you await the wrapper so no SynchronousOnlyOperation is raised.
🤖 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.

Outside diff comments:
In `@backend/apps/mentorship/api/internal/queries/module.py`:
- Around line 28-31: The async resolver get_program_modules calls the
synchronous method program.user_has_access which performs ORM queries and will
raise SynchronousOnlyOperation; wrap the call with asgiref.sync.sync_to_async
and await it instead of calling directly (import sync_to_async and replace the
direct program.user_has_access(...) call with await
sync_to_async(program.user_has_access)(info.context.request.user)), keeping the
existing conditional logic intact so the published-status check still
short-circuits.

In `@backend/apps/mentorship/api/internal/queries/program.py`:
- Around line 36-39: The async resolver in program.py calls the synchronous
method program.user_has_access(...) which performs ORM work and must be awaited
via an async wrapper; import sync_to_async (from asgiref.sync), replace direct
calls to program.user_has_access(...) with await
sync_to_async(program.user_has_access)(info.context.request.user) (and do the
same fix in module.py's get_program_modules around the call at line 28),
ensuring you await the wrapper so no SynchronousOnlyOperation is raised.

In `@backend/tests/unit/apps/owasp/api/internal/queries/stats_test.py`:
- Around line 17-37: The workspace lookup in the StatsQuery tests must be
asserted to ensure Workspace.objects.filter is called with the constant
OWASP_WORKSPACE_ID; update the test(s) in stats_test.py (where
StatsQuery().stats_overview() is invoked) to assert that
mock_workspace_cls.objects.filter was called with
slack_workspace_id=OWASP_WORKSPACE_ID (e.g. assert_called_once_with or
assert_called_with), and add the same assertion in the second test block
referenced (lines ~47-65) so the resolver’s filter argument is validated for
regressions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 67c4fc5f-36be-4207-a7e3-d5c848bbb9e3

📥 Commits

Reviewing files that changed from the base of the PR and between 9c8e4ef and e2c05fa.

📒 Files selected for processing (11)
  • backend/apps/github/api/internal/dataloaders/__init__.py
  • backend/apps/github/api/internal/nodes/issue.py
  • backend/apps/github/api/internal/queries/organization.py
  • backend/apps/mentorship/api/internal/queries/module.py
  • backend/apps/mentorship/api/internal/queries/program.py
  • backend/apps/owasp/api/internal/queries/stats.py
  • backend/tests/unit/apps/github/api/internal/nodes/issue_test.py
  • backend/tests/unit/apps/github/api/internal/queries/organization_test.py
  • backend/tests/unit/apps/mentorship/api/internal/queries/api_queries_module_test.py
  • backend/tests/unit/apps/mentorship/api/internal/queries/api_queries_program_test.py
  • backend/tests/unit/apps/owasp/api/internal/queries/stats_test.py

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 6, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

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.

1 issue found across 11 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="backend/apps/mentorship/api/internal/queries/module.py">

<violation number="1" location="backend/apps/mentorship/api/internal/queries/module.py:19">
P1: This resolver is now async, but it still calls `program.user_has_access(...)`, which performs synchronous ORM `.exists()` queries and can raise `SynchronousOnlyOperation` in async execution.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 6, 2026
@sonarqubecloud

sonarqubecloud Bot commented May 6, 2026

Copy link
Copy Markdown

@ahmedxgouda
ahmedxgouda marked this pull request as ready for review May 6, 2026 17:41
@ahmedxgouda
ahmedxgouda requested review from arkid15r and kasya as code owners May 6, 2026 17:41
@ahmedxgouda ahmedxgouda added the gsoc2026:ahmedxgouda ahmedxgouda's GSoC 2026 related work label May 17, 2026
cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes Jun 20, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

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.

0 issues found across 1 file (changes from recent commits).

Re-trigger cubic

@ahmedxgouda
ahmedxgouda requested a review from arkid15r June 20, 2026 03:14
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 20, 2026
cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes Jun 21, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

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.

0 issues found across 8 files (changes from recent commits).

Re-trigger cubic

cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes Jun 21, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

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.

0 issues found across 5 files (changes from recent commits).

Re-trigger cubic

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 21, 2026
from apps.github.models.pull_request import PullRequest
from apps.mentorship.models.issue_user_interest import IssueUserInterest
from apps.mentorship.api.internal.dataloaders.interested_users import (
INTERESTED_USERS_BY_ISSUE_ID_LOADER,

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.

I think "INTERESTED_USERS_LOADER" should just be fine here; the class or function will clearly indicate it's been done by issue ID

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

There will be a new loader soon for loading the interested users based on issue_number

@@ -0,0 +1,30 @@
"""DataLoaders for interested users."""

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.

Here you can clearly indicate that it's using the issue ID. Then rename INTERESTED_USERS_BY_ISSUE_ID_LOADER = "interested_users_by_issue_id" (L9)

@arkid15r
arkid15r enabled auto-merge (squash) June 21, 2026 22:19
@arkid15r
arkid15r disabled auto-merge June 21, 2026 22:20
@arkid15r
arkid15r enabled auto-merge (squash) June 21, 2026 22:20
@arkid15r
arkid15r disabled auto-merge June 21, 2026 22:20
@arkid15r
arkid15r merged commit 7e5ae19 into OWASP:feature/graphql-dataloaders Jun 21, 2026
30 of 31 checks passed
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend backend-tests gsoc2026:ahmedxgouda ahmedxgouda's GSoC 2026 related work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Optimize GitHub app IssueNode

3 participants