Skip to content

[fix] Fix duplicate check creation in auto_create_check_receiver#769

Open
855princekumar wants to merge 11 commits intoopenwisp:masterfrom
855princekumar:master
Open

[fix] Fix duplicate check creation in auto_create_check_receiver#769
855princekumar wants to merge 11 commits intoopenwisp:masterfrom
855princekumar:master

Conversation

@855princekumar
Copy link
Copy Markdown

Checklist

  • I have read the OpenWISP Contributing Guidelines
  • I have manually tested the changes proposed in this pull request.
  • I have written new test cases for new code and/or updated existing tests for changes to existing code.
  • I have updated the documentation.

Reference to Existing Issue

Closes #649

Description of Changes

Fixed duplicate monitoring check creation by ensuring idempotent behavior.

Previously, checks were created multiple times because validation was missing for each check type.
This resulted in duplicate entries and failing tests.

This fix:

  • Adds per-check-type existence validation before creating checks
  • Preserves async task execution using Celery
  • Keeps the signal handler lightweight and aligned with project architecture

As a result, duplicate-check creation is prevented, and related test failures are resolved.

Screenshot

Test results after applying the fix:

  • All core tests pass successfully
  • Remaining 4 errors are related to Selenium/WebDriver environment and are not related to this fix
image

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 26, 2026

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

Walkthrough

The signal handler signature for AbstractCheck.auto_create_check_receiver was changed to accept Django signal arguments (sender, instance, created, **kwargs). The transaction_on_commit callback now invokes _auto_check_receiver with sender and instance. _auto_check_receiver resolves the Check model via swapper.load_model, computes the ContentType for the instance, prefetches existing check_type values for the same (content_type, object_id), and during iteration over app_settings.CHECK_CLASSES it skips scheduling auto_create_check.delay(...) when a Check with the matching check_type already exists. Non-functional docstring/comment lines were removed.

Sequence Diagram

sequenceDiagram
    participant Signal as Django Signal
    participant Handler as auto_create_check_receiver
    participant Tx as transaction_on_commit
    participant Receiver as _auto_check_receiver
    participant Swapper as swapper.load_model
    participant CT as ContentType
    participant DB as Database (Check)
    participant Celery as Celery Task Queue

    Signal->>Handler: Emit signal (sender, instance, created, **kwargs)
    Handler->>Tx: Register callback with sender and instance
    Tx->>Receiver: Invoke callback (sender, instance) after commit
    Receiver->>Swapper: Resolve Check model
    Swapper-->>Receiver: Return Check model
    Receiver->>CT: Get ContentType for instance
    CT-->>Receiver: Return ContentType
    Receiver->>DB: Query existing Checks for (content_type, object_id) and prefetch check_type
    DB-->>Receiver: Return existing check_type list
    loop for each check_class in CHECK_CLASSES
        alt matching check_type found
            Receiver-->>DB: Skip scheduling (exists)
        else no matching check_type
            Receiver->>Celery: Schedule auto_create_check.delay(check_class, content_type, object_id)
            Celery-->>Receiver: Task queued
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error)

Check name Status Explanation Resolution
Bug Fixes ❌ Error PR fixes duplicate check creation via prefetch logic but lacks an explicit regression test validating the fix prevents duplicate check creation. Add a regression test demonstrating duplicate check creation bug and validating the fix prevents creating duplicate checks per check_type.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the required format [fix] and accurately describes the main change: fixing duplicate check creation in auto_create_check_receiver.
Description check ✅ Passed The description covers all required template sections including checklist completion, issue reference (#649), and detailed change description with test results.
Linked Issues check ✅ Passed The PR addresses the flaky test in #649 by implementing per-check-type existence validation to prevent duplicate check creation, which causes non-deterministic test behavior.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing duplicate check creation by updating auto_create_check_receiver signature and implementing idempotent validation logic, directly addressing issue #649.
✨ 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.

Copy link
Copy Markdown

@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.

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 `@openwisp_monitoring/check/base/models.py`:
- Around line 125-134: The import of Check inside the loop is inefficient and
should be moved outside the loop (e.g., import
openwisp_monitoring.check.models.Check before iterating) and then use that local
reference inside the loop; also change the filter to use check_type (i.e.,
filter(content_type=ct, object_id=object_id, check_type=check_type)) instead of
name so the existence check aligns with CHECK_CLASSES mapping and the
receiver/task consistency.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a522819d-7193-4e4a-b6eb-be8e9a520da8

📥 Commits

Reviewing files that changed from the base of the PR and between 8a28ddf and a4727fd.

📒 Files selected for processing (1)
  • openwisp_monitoring/check/base/models.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Python==3.12 | django~=5.1.0
  • GitHub Check: Python==3.13 | django~=5.2.0
  • GitHub Check: Python==3.10 | django~=5.2.0
  • GitHub Check: Python==3.13 | django~=5.1.0
  • GitHub Check: Python==3.12 | django~=5.2.0
  • GitHub Check: Python==3.11 | django~=4.2.0
  • GitHub Check: Python==3.12 | django~=4.2.0
  • GitHub Check: Python==3.10 | django~=5.1.0
  • GitHub Check: Python==3.11 | django~=5.1.0
  • GitHub Check: Python==3.11 | django~=5.2.0
  • GitHub Check: Python==3.10 | django~=4.2.0
🧰 Additional context used
📓 Path-based instructions (1)
{**/*.sh,**/*.{js,ts,tsx,jsx},**/*.py,**/*.rb,**/*.go,**/*.java,**/*.cs,**/*.cpp,**/*.c}

📄 CodeRabbit inference engine (Custom checks)

Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

Files:

  • openwisp_monitoring/check/base/models.py
🧠 Learnings (3)
📚 Learning: 2026-02-21T18:44:28.852Z
Learnt from: dee077
Repo: openwisp/openwisp-monitoring PR: 738
File: openwisp_monitoring/device/api/views.py:263-281
Timestamp: 2026-02-21T18:44:28.852Z
Learning: In openwisp-monitoring, MonitoringIndoorCoordinatesList inherits organization scoping from the parent IndoorCoordinatesList (from openwisp-controller), which uses FilterByParentManaged mixin and filters by location_id in get_queryset(). The child class only overrides the queryset attribute to add monitoring-specific select_related fields; this pattern is safe as long as get_queryset() from the parent is not bypassed. During reviews, verify that MonitoringIndoorCoordinatesList continues to rely on the parent's get_queryset() and that any added select_related fields in the child do not alter the parent's filtering logic.

Applied to files:

  • openwisp_monitoring/check/base/models.py
📚 Learning: 2026-03-14T18:39:04.626Z
Learnt from: UltraBot05
Repo: openwisp/openwisp-monitoring PR: 766
File: openwisp_monitoring/utils.py:59-68
Timestamp: 2026-03-14T18:39:04.626Z
Learning: In this repository (openwisp/openwisp-monitoring), the project targets Python 3.10–3.13 as defined by CI. Do not flag backports.zoneinfo as a missing dependency; zoneinfo is a built-in module in all supported Python versions. When reviewing Python code, assume zoneinfo is available and avoid suggesting installation of backports.zoneinfo. If a file imports zoneinfo or uses it for time zone handling, treat it as standard library usage compatible with the supported CI matrix.

Applied to files:

  • openwisp_monitoring/check/base/models.py
📚 Learning: 2026-03-14T18:39:04.626Z
Learnt from: UltraBot05
Repo: openwisp/openwisp-monitoring PR: 766
File: openwisp_monitoring/utils.py:59-68
Timestamp: 2026-03-14T18:39:04.626Z
Learning: In the openwisp-monitoring project, targets are Linux-based environments. Do not flag a Windows-specific tzdata package as a missing dependency in code reviews for Python files (e.g., openwisp_monitoring/utils.py). If a platform-specific dependency is truly required, document the exception in review guidelines and ensure CI/packaging checks enforce platform constraints rather than manual review.

Applied to files:

  • openwisp_monitoring/check/base/models.py
🔇 Additional comments (1)
openwisp_monitoring/check/base/models.py (1)

106-112: LGTM!

The updated signature correctly matches Django's post_save signal convention, and the transaction_on_commit callback properly defers the check creation logic until after the transaction commits.

Comment thread openwisp_monitoring/check/base/models.py
@openwisp-companion
Copy link
Copy Markdown

CI Failures: Code Style, Commit Message, and Test Errors

Hello @855princekumar,
(Analysis for commit a4727fd)

  1. Code Style/QA:
  • Black check failed due to whitespace issues and too many blank lines.
  • Flake8 check failed due to whitespace issues and too many blank lines.
  • Fix: Run openwisp-qa-format to automatically fix these issues.
  1. Commit Message:
  • The commit message format is incorrect.
  • Fix: Ensure your commit message follows this structure:
[tag] Capitalized short title #<issue>

<description>

Fixes #<issue>

For example:

[fix] Corrected typo in documentation #123

The documentation had a typo in the installation guide. This commit
corrects it.

Fixes #123
  1. Test Failure:
  • RuntimeError: Model class openwisp_monitoring.check.models.Check doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.

  • This error indicates that the Check model is not properly registered in INSTALLED_APPS or lacks an app_label.

  • Fix: Review openwisp_monitoring/check/apps.py and tests/openwisp2/settings.py to ensure the check app and its models are correctly configured and included in INSTALLED_APPS. Specifically, check the SampleCheckConfig in tests/openwisp2/sample_check/apps.py and its name and label attributes.

  • Multiple tests failed with RuntimeError: Model class openwisp_monitoring.check.models.Check doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS. This is the same issue as described above, affecting various tests.

  • Fix: Address the Check model registration issue as described above.

@855princekumar 855princekumar changed the title Fix duplicate check creation in auto_create_check_receiver [fix] Fix duplicate check creation in auto_create_check_receiver Mar 26, 2026
Moved the import of Check to the top-level for better performance and safety.
Moved import statement for Check to top-level for safety.
@openwisp-companion
Copy link
Copy Markdown

QA and Commit Message Failures

Hello @855princekumar,
(Analysis for commit 35c6c4f)

  • Code Style/QA Failures:

  • The CI failed due to incorrect import sorting and formatting in openwisp_monitoring/check/base/models.py.

  • Fix: Run openwisp-qa-format to automatically fix these issues.

  • There's also a W293 blank line contains whitespace error in openwisp_monitoring/check/base/models.py.

  • Fix: Manually remove the whitespace from the blank line.

  • Commit Message Failure:

  • The commit message "Refactor import statement for Check model" is missing the required format.

  • Fix: Ensure your commit messages follow the convention: [tag] Capitalized short title #<issue> followed by a blank line and a detailed description, and a closing keyword like Fixes #<issue> in the footer.

Example:

[refactor] Update CI configuration #123

Updated the CI configuration to use a new caching strategy.

Fixes #123
  • Circular Import Error:
  • The runtests.py script failed with an ImportError: cannot import name 'Check' from partially initialized module 'openwisp_monitoring.check.models' (most likely due to a circular import).
  • This indicates a potential circular dependency issue between openwisp_monitoring/check/models.py and openwisp_monitoring/check/base/models.py related to the Check model.
  • Fix: Review the import statements in both files to break the circular dependency. Ensure that openwisp_monitoring/check/base/models.py does not import Check from openwisp_monitoring/check/models.py if openwisp_monitoring/check/models.py imports from openwisp_monitoring/check/base/models.py. The current logs suggest openwisp_monitoring/check/base/models.py imports Check from openwisp_monitoring.check.models, which might be the source of the circular import.

…wisp#649  Moved Check import inside function to avoid circular import issues while keeping it outside the loop for efficiency.  Also fixed code style issues to comply with QA checks.  Fixes openwisp#649

Moved Check import inside function to avoid circular import issues while
keeping it outside the loop for efficiency.

Also ensured code style compliance.

Fixes openwisp#649
@openwisp-companion
Copy link
Copy Markdown

Multiple Test Failures Detected

Hello @855princekumar,
(Analysis for commit 7238130)

  • Test Failure: The test_url_fragment_actions_on_indoor_map in TestDashboardMap failed because the Firefox browser could not establish a connection to the server. This is likely a transient issue or a problem with the test environment setup.

  • Fix: No code change is needed. This appears to be a transient infrastructure issue. The CI has been restarted automatically.

  • Build/Infrastructure Failure: The tests test_passive_metric_alert and others failed with a RuntimeError: Model class openwisp_monitoring.check.models.Check doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS. This indicates a configuration issue where the check app is not correctly registered in INSTALLED_APPS for the test environment.

  • Fix: Ensure that openwisp_monitoring.check is included in the INSTALLED_APPS list within the test settings. Based on tests/openwisp2/settings.py, it seems openwisp_monitoring.check is already present. This might be an issue with how the test environment is set up or a subtle configuration problem. Double-check the INSTALLED_APPS in tests/openwisp2/settings.py and ensure openwisp_monitoring.check and openwisp2.sample_check are correctly listed.

…wisp#649  Ensure idempotency by validating existing checks using check_type instead of name.  Fixes openwisp#649
Copy link
Copy Markdown

@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.

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 `@openwisp_monitoring/check/base/models.py`:
- Around line 130-135: The loop currently issues a database exists() call per
check class using Check.objects.filter(..., check_type=class_string).exists();
instead, query once for all existing check_type values for the given content
type and object id (use Check.objects.filter(content_type=ct,
object_id=object_id).values_list('check_type', flat=True)), build an in-memory
set, and replace the per-class exists() check with a membership test like "if
class_string in existing_check_types: continue" to avoid N queries.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 04393f18-3dbd-4f1c-8f74-3cd5f84527b6

📥 Commits

Reviewing files that changed from the base of the PR and between 7238130 and e45aa94.

📒 Files selected for processing (1)
  • openwisp_monitoring/check/base/models.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Python==3.10 | django~=5.1.0
  • GitHub Check: Python==3.11 | django~=4.2.0
  • GitHub Check: Python==3.12 | django~=5.1.0
  • GitHub Check: Python==3.12 | django~=5.2.0
  • GitHub Check: Python==3.11 | django~=5.1.0
  • GitHub Check: Python==3.13 | django~=5.2.0
  • GitHub Check: Python==3.12 | django~=4.2.0
  • GitHub Check: Python==3.11 | django~=5.2.0
  • GitHub Check: Python==3.10 | django~=4.2.0
  • GitHub Check: Python==3.10 | django~=5.2.0
  • GitHub Check: Python==3.13 | django~=5.1.0
🧰 Additional context used
📓 Path-based instructions (1)
{**/*.sh,**/*.{js,ts,tsx,jsx},**/*.py,**/*.rb,**/*.go,**/*.java,**/*.cs,**/*.cpp,**/*.c}

📄 CodeRabbit inference engine (Custom checks)

Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

Files:

  • openwisp_monitoring/check/base/models.py
🧠 Learnings (3)
📚 Learning: 2026-02-21T18:44:28.852Z
Learnt from: dee077
Repo: openwisp/openwisp-monitoring PR: 738
File: openwisp_monitoring/device/api/views.py:263-281
Timestamp: 2026-02-21T18:44:28.852Z
Learning: In openwisp-monitoring, MonitoringIndoorCoordinatesList inherits organization scoping from the parent IndoorCoordinatesList (from openwisp-controller), which uses FilterByParentManaged mixin and filters by location_id in get_queryset(). The child class only overrides the queryset attribute to add monitoring-specific select_related fields; this pattern is safe as long as get_queryset() from the parent is not bypassed. During reviews, verify that MonitoringIndoorCoordinatesList continues to rely on the parent's get_queryset() and that any added select_related fields in the child do not alter the parent's filtering logic.

Applied to files:

  • openwisp_monitoring/check/base/models.py
📚 Learning: 2026-03-14T18:39:04.626Z
Learnt from: UltraBot05
Repo: openwisp/openwisp-monitoring PR: 766
File: openwisp_monitoring/utils.py:59-68
Timestamp: 2026-03-14T18:39:04.626Z
Learning: In this repository (openwisp/openwisp-monitoring), the project targets Python 3.10–3.13 as defined by CI. Do not flag backports.zoneinfo as a missing dependency; zoneinfo is a built-in module in all supported Python versions. When reviewing Python code, assume zoneinfo is available and avoid suggesting installation of backports.zoneinfo. If a file imports zoneinfo or uses it for time zone handling, treat it as standard library usage compatible with the supported CI matrix.

Applied to files:

  • openwisp_monitoring/check/base/models.py
📚 Learning: 2026-03-14T18:39:04.626Z
Learnt from: UltraBot05
Repo: openwisp/openwisp-monitoring PR: 766
File: openwisp_monitoring/utils.py:59-68
Timestamp: 2026-03-14T18:39:04.626Z
Learning: In the openwisp-monitoring project, targets are Linux-based environments. Do not flag a Windows-specific tzdata package as a missing dependency in code reviews for Python files (e.g., openwisp_monitoring/utils.py). If a platform-specific dependency is truly required, document the exception in review guidelines and ensure CI/packaging checks enforce platform constraints rather than manual review.

Applied to files:

  • openwisp_monitoring/check/base/models.py
🔇 Additional comments (2)
openwisp_monitoring/check/base/models.py (2)

107-113: Signal receiver signature and deferred dispatch look correct.

This aligns with Django post_save arguments and keeps scheduling deferred to transaction commit, which is the right pattern here.


123-124: Good handling of circular dependency.

Keeping the import local with an explicit rationale makes this non-obvious dependency edge clear and maintainable.

As per coding guidelines, "Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable."

Comment thread openwisp_monitoring/check/base/models.py Outdated
@openwisp-companion
Copy link
Copy Markdown

Model class openwisp_monitoring.check.models.Check not in INSTALLED_APPS

Hello @855princekumar,
(Analysis for commit e45aa94)

The CI build failed because the openwisp_monitoring.check.models.Check model class was not properly registered in the INSTALLED_APPS setting. This is causing a RuntimeError when Django tries to access this model.

Fix:

Ensure that openwisp_monitoring.check is included in the INSTALLED_APPS list in your settings.py file. If you are using sample apps, ensure that openwisp2.sample_check is also correctly configured.

Specifically, check the tests/openwisp2/settings.py file. The openwisp_monitoring.check app should be listed under INSTALLED_APPS. If you are testing with sample apps, openwisp2.sample_check should also be present.

…wisp#649  Ensure idempotent check creation by validating existing checks using check_type.  Use swapper.load_model to avoid app registry issues and circular imports.  Fixes openwisp#649
@855princekumar
Copy link
Copy Markdown
Author

Updated the implementation to use swapper.load_model instead of direct model import
to avoid app registry and circular import issues in the test environment.

The existing test test_no_duplicate_check_created already validates that duplicate
checks are not created when auto_create_check is triggered multiple times.

This fix ensures idempotency by checking existing checks using check_type,
aligning with the current test behavior.

Copy link
Copy Markdown

@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.

♻️ Duplicate comments (1)
openwisp_monitoring/check/base/models.py (1)

116-144: 🧹 Nitpick | 🔵 Trivial

Avoid per-check-type existence queries in the loop.

The current implementation issues one exists() query per check class. With a small number of check classes this is acceptable, but you can optimize by fetching existing check_types once and performing in-memory set membership checks.

 def _auto_check_receiver(sender, instance, **kwargs):
     from swapper import load_model

     Check = load_model("check", "Check")

     model = sender.__name__.lower()
     app_label = sender._meta.app_label
     object_id = str(instance.pk)

     ct = ContentType.objects.get_for_model(instance)

+    # Fetch all existing check_types for this object in a single query
+    existing_check_types = set(
+        Check.objects.filter(content_type=ct, object_id=object_id).values_list(
+            "check_type", flat=True
+        )
+    )
+
     for class_string, name, auto_create_setting in app_settings.CHECK_CLASSES:
         if not getattr(app_settings, auto_create_setting):
             continue

-        if Check.objects.filter(
-            content_type=ct,
-            object_id=object_id,
-            check_type=class_string,
-        ).exists():
+        if class_string in existing_check_types:
             continue

         auto_create_check.delay(
             model=model,
             app_label=app_label,
             object_id=object_id,
             check_type=class_string,
             check_name=name,
         )

,

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openwisp_monitoring/check/base/models.py` around lines 116 - 144, The
_auto_check_receiver currently calls Check.objects.filter(...).exists() for
every entry in app_settings.CHECK_CLASSES; instead, query existing checks once
and use an in-memory set to avoid N queries: load the Check model (Check),
compute ct and object_id as now, then fetch existing_types =
set(Check.objects.filter(content_type=ct,
object_id=object_id).values_list("check_type", flat=True)); then iterate
app_settings.CHECK_CLASSES and for each (class_string, name,
auto_create_setting) skip if not getattr(app_settings, auto_create_setting) or
if class_string in existing_types, otherwise call auto_create_check.delay(...)
as before. Ensure you keep the same arguments to auto_create_check.delay and
preserve model/app_label determination logic in _auto_check_receiver.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@openwisp_monitoring/check/base/models.py`:
- Around line 116-144: The _auto_check_receiver currently calls
Check.objects.filter(...).exists() for every entry in
app_settings.CHECK_CLASSES; instead, query existing checks once and use an
in-memory set to avoid N queries: load the Check model (Check), compute ct and
object_id as now, then fetch existing_types =
set(Check.objects.filter(content_type=ct,
object_id=object_id).values_list("check_type", flat=True)); then iterate
app_settings.CHECK_CLASSES and for each (class_string, name,
auto_create_setting) skip if not getattr(app_settings, auto_create_setting) or
if class_string in existing_types, otherwise call auto_create_check.delay(...)
as before. Ensure you keep the same arguments to auto_create_check.delay and
preserve model/app_label determination logic in _auto_check_receiver.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: cb21b8c1-76bf-4c2f-9951-34618b4cc93b

📥 Commits

Reviewing files that changed from the base of the PR and between e45aa94 and 07a2a1e.

📒 Files selected for processing (1)
  • openwisp_monitoring/check/base/models.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Python==3.12 | django~=4.2.0
  • GitHub Check: Python==3.12 | django~=5.2.0
  • GitHub Check: Python==3.12 | django~=5.1.0
  • GitHub Check: Python==3.13 | django~=5.1.0
  • GitHub Check: Python==3.10 | django~=4.2.0
  • GitHub Check: Python==3.13 | django~=5.2.0
  • GitHub Check: Python==3.10 | django~=5.1.0
  • GitHub Check: Python==3.11 | django~=5.2.0
  • GitHub Check: Python==3.10 | django~=5.2.0
  • GitHub Check: Python==3.11 | django~=5.1.0
  • GitHub Check: Python==3.11 | django~=4.2.0
🧰 Additional context used
📓 Path-based instructions (1)
{**/*.sh,**/*.{js,ts,tsx,jsx},**/*.py,**/*.rb,**/*.go,**/*.java,**/*.cs,**/*.cpp,**/*.c}

📄 CodeRabbit inference engine (Custom checks)

Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

Files:

  • openwisp_monitoring/check/base/models.py
🧠 Learnings (3)
📚 Learning: 2026-02-21T18:44:28.852Z
Learnt from: dee077
Repo: openwisp/openwisp-monitoring PR: 738
File: openwisp_monitoring/device/api/views.py:263-281
Timestamp: 2026-02-21T18:44:28.852Z
Learning: In openwisp-monitoring, MonitoringIndoorCoordinatesList inherits organization scoping from the parent IndoorCoordinatesList (from openwisp-controller), which uses FilterByParentManaged mixin and filters by location_id in get_queryset(). The child class only overrides the queryset attribute to add monitoring-specific select_related fields; this pattern is safe as long as get_queryset() from the parent is not bypassed. During reviews, verify that MonitoringIndoorCoordinatesList continues to rely on the parent's get_queryset() and that any added select_related fields in the child do not alter the parent's filtering logic.

Applied to files:

  • openwisp_monitoring/check/base/models.py
📚 Learning: 2026-03-14T18:39:04.626Z
Learnt from: UltraBot05
Repo: openwisp/openwisp-monitoring PR: 766
File: openwisp_monitoring/utils.py:59-68
Timestamp: 2026-03-14T18:39:04.626Z
Learning: In this repository (openwisp/openwisp-monitoring), the project targets Python 3.10–3.13 as defined by CI. Do not flag backports.zoneinfo as a missing dependency; zoneinfo is a built-in module in all supported Python versions. When reviewing Python code, assume zoneinfo is available and avoid suggesting installation of backports.zoneinfo. If a file imports zoneinfo or uses it for time zone handling, treat it as standard library usage compatible with the supported CI matrix.

Applied to files:

  • openwisp_monitoring/check/base/models.py
📚 Learning: 2026-03-14T18:39:04.626Z
Learnt from: UltraBot05
Repo: openwisp/openwisp-monitoring PR: 766
File: openwisp_monitoring/utils.py:59-68
Timestamp: 2026-03-14T18:39:04.626Z
Learning: In the openwisp-monitoring project, targets are Linux-based environments. Do not flag a Windows-specific tzdata package as a missing dependency in code reviews for Python files (e.g., openwisp_monitoring/utils.py). If a platform-specific dependency is truly required, document the exception in review guidelines and ensure CI/packaging checks enforce platform constraints rather than manual review.

Applied to files:

  • openwisp_monitoring/check/base/models.py
🔇 Additional comments (1)
openwisp_monitoring/check/base/models.py (1)

106-113: LGTM!

The method signature now correctly accepts Django's post_save signal arguments (sender, instance, created). The transaction_on_commit callback properly passes these to _auto_check_receiver, ensuring the existence check runs after the transaction commits. This is the correct pattern for signal handlers that need to query the database for the just-saved instance.

@openwisp-companion
Copy link
Copy Markdown

Commit Message Format Failure

Hello @855princekumar,
(Analysis for commit 07a2a1e)

The CI failed because the commit message does not follow the required format. Specifically, the issue number #649 is referenced in the title but not in the body with a closing keyword like Fixes.

To fix this, please ensure your commit message follows this structure:

[tag] Capitalized short title #<issue>

<blank line>

Detailed description of the changes.
This section should also include the issue reference with a closing keyword.
Fixes #<issue>

For example:

[fix] Fix duplicate check creation #649

Ensure idempotent check creation by validating existing checks using check_type.
Use swapper.load_model to avoid app registry issues and circular imports.
Fixes #649

…wisp#649

Ensure idempotent check creation by validating existing checks using check_type.

Use swapper.load_model to avoid app registry issues and circular imports.
Optimize query by fetching existing check types once.
@855princekumar
Copy link
Copy Markdown
Author

Updated implementation to use swapper.load_model to avoid app registry
and circular import issues.

Optimized duplicate detection by fetching existing check_types once instead
of querying per iteration.

The existing test test_no_duplicate_check_created already validates
duplicate prevention, so no additional test was required.

This ensures idempotent behavior aligned with current test coverage.

Copy link
Copy Markdown

@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.

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 `@openwisp_monitoring/check/base/models.py`:
- Around line 117-132: Add concise inline comments explaining why
swapper.load_model("check", "Check") is used (dynamic model loading to avoid
import-time circular dependencies and to support swappable Check models) and why
the code builds existing_check_types via
ContentType.objects.get_for_model(instance) followed by
Check.objects.filter(...).values_list(...) (prefetching existing check_type
values into a set for fast membership checks to ensure idempotent
creation/deduplication of checks). Place the comments near the load_model call
and the existing_check_types assignment and reference the symbols load_model,
Check, ContentType.objects.get_for_model, existing_check_types, sender, and
instance so future readers understand the intent.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f763f147-7183-4aa2-9f87-741afea87af1

📥 Commits

Reviewing files that changed from the base of the PR and between 07a2a1e and 85467b3.

📒 Files selected for processing (1)
  • openwisp_monitoring/check/base/models.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Python==3.10 | django~=5.2.0
  • GitHub Check: Python==3.11 | django~=5.2.0
  • GitHub Check: Python==3.13 | django~=5.1.0
  • GitHub Check: Python==3.12 | django~=4.2.0
  • GitHub Check: Python==3.10 | django~=4.2.0
  • GitHub Check: Python==3.12 | django~=5.1.0
  • GitHub Check: Python==3.11 | django~=4.2.0
  • GitHub Check: Python==3.11 | django~=5.1.0
  • GitHub Check: Python==3.10 | django~=5.1.0
  • GitHub Check: Python==3.13 | django~=5.2.0
  • GitHub Check: Python==3.12 | django~=5.2.0
🧰 Additional context used
📓 Path-based instructions (1)
{**/*.sh,**/*.{js,ts,tsx,jsx},**/*.py,**/*.rb,**/*.go,**/*.java,**/*.cs,**/*.cpp,**/*.c}

📄 CodeRabbit inference engine (Custom checks)

Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

Files:

  • openwisp_monitoring/check/base/models.py
🧠 Learnings (3)
📚 Learning: 2026-02-21T18:44:28.852Z
Learnt from: dee077
Repo: openwisp/openwisp-monitoring PR: 738
File: openwisp_monitoring/device/api/views.py:263-281
Timestamp: 2026-02-21T18:44:28.852Z
Learning: In openwisp-monitoring, MonitoringIndoorCoordinatesList inherits organization scoping from the parent IndoorCoordinatesList (from openwisp-controller), which uses FilterByParentManaged mixin and filters by location_id in get_queryset(). The child class only overrides the queryset attribute to add monitoring-specific select_related fields; this pattern is safe as long as get_queryset() from the parent is not bypassed. During reviews, verify that MonitoringIndoorCoordinatesList continues to rely on the parent's get_queryset() and that any added select_related fields in the child do not alter the parent's filtering logic.

Applied to files:

  • openwisp_monitoring/check/base/models.py
📚 Learning: 2026-03-14T18:39:04.626Z
Learnt from: UltraBot05
Repo: openwisp/openwisp-monitoring PR: 766
File: openwisp_monitoring/utils.py:59-68
Timestamp: 2026-03-14T18:39:04.626Z
Learning: In this repository (openwisp/openwisp-monitoring), the project targets Python 3.10–3.13 as defined by CI. Do not flag backports.zoneinfo as a missing dependency; zoneinfo is a built-in module in all supported Python versions. When reviewing Python code, assume zoneinfo is available and avoid suggesting installation of backports.zoneinfo. If a file imports zoneinfo or uses it for time zone handling, treat it as standard library usage compatible with the supported CI matrix.

Applied to files:

  • openwisp_monitoring/check/base/models.py
📚 Learning: 2026-03-14T18:39:04.626Z
Learnt from: UltraBot05
Repo: openwisp/openwisp-monitoring PR: 766
File: openwisp_monitoring/utils.py:59-68
Timestamp: 2026-03-14T18:39:04.626Z
Learning: In the openwisp-monitoring project, targets are Linux-based environments. Do not flag a Windows-specific tzdata package as a missing dependency in code reviews for Python files (e.g., openwisp_monitoring/utils.py). If a platform-specific dependency is truly required, document the exception in review guidelines and ensure CI/packaging checks enforce platform constraints rather than manual review.

Applied to files:

  • openwisp_monitoring/check/base/models.py
🔇 Additional comments (1)
openwisp_monitoring/check/base/models.py (1)

107-113: Good idempotency guard flow in receiver/task dispatch path.

The created gate plus pre-fetched existing_check_types membership check before enqueueing looks correct and keeps the signal handler lightweight.

Also applies to: 127-139

Comment thread openwisp_monitoring/check/base/models.py
@openwisp-companion
Copy link
Copy Markdown

Commit Message Format Failure

Hello @855princekumar,
(Analysis for commit 85467b3)

The CI failed because the commit message does not follow the required format. Specifically, the issue number #649 is present in the title but not in the body with a closing keyword like Fixes, Closes, or Related to.

To fix this, please update your commit message to include the issue in the body.

Correct Format Example:

[fix] Fix duplicate check creation in auto_create_check_receiver #649

Ensure idempotent check creation by validating existing checks using check_type.
Use swapper.load_model to avoid app registry issues and circular imports.
Optimize query by fetching existing check types once.

Fixes #649

Ensure idempotent check creation by validating existing checks using check_type.
Use swapper.load_model to support swappable models and avoid app registry issues.
Optimize duplicate detection by prefetching existing check types.

Fixes openwisp#649
@openwisp-companion
Copy link
Copy Markdown

Commit Message Format Failure

Hello @855princekumar,
(Analysis for commit 707e233)

The commit message failed validation because the issue number (#649) was not included in the commit title.

Fix:
Ensure the commit message follows this format:

[prefix] Short title referencing issue #<issue_number>

Body of the commit message.

Fixes #<issue_number>

For example: [fix] Fix duplicate check creation #649

…wisp#649

Ensure idempotent check creation by validating existing checks using check_type.
Use swapper.load_model to support swappable models and avoid app registry issues.
Optimize duplicate detection by prefetching existing check types.

Fixes openwisp#649
@atif09
Copy link
Copy Markdown
Contributor

atif09 commented Apr 11, 2026

please address the code rabbit comments either by:

Applying the changes in your next push if you think they're worth addressing
(or)
Replying to it saying why you don't agree with what it suggested

@855princekumar
Copy link
Copy Markdown
Author

855princekumar commented Apr 11, 2026 via email

@855princekumar
Copy link
Copy Markdown
Author

Added inline comments explaining the dynamic model loading and idempotent deduplication logic as suggested.

@openwisp-companion
Copy link
Copy Markdown

Test Failure in Monitoring Notifications

Hello @855princekumar,
(Analysis for commit 76aa144)

There is one test failure:

  • Test Failure: The test test_object_check_threshold_crossed_for_long_time in openwisp_monitoring.monitoring.tests.test_monitoring_notifications failed with an AssertionError: True != False. This indicates that the is_healthy_tolerant attribute was expected to be False but was True.

Fix: Review the logic in the test_object_check_threshold_crossed_for_long_time test case and the corresponding code that sets the is_healthy_tolerant attribute to ensure it behaves as expected under the tested conditions.

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.

[bug:tests] Flaky test: TestWifiClient.test_store_result

2 participants