Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 6, 2026

In distributed setups with multiple Casbin instances using watchers to synchronize policy changes, calling policy modification methods within watcher callbacks creates infinite loops: policy update → DB write → watcher notification → policy update → ...

Changes

Modified InternalEnforcer methods (src/internalEnforcer.ts)

  • Added optional useAdapter parameter (default: true) to all *Internal methods
  • Adapter calls now gated by if (useAdapter && this.adapter && this.autoSave)
  • Affects: addPolicyInternal, addPoliciesInternal, addPoliciesInternalEx, updatePolicyInternal, removePolicyInternal, removePoliciesInternal, removeFilteredPolicyInternal

Updated ManagementEnforcer self methods* (src/managementEnforcer.ts)

  • All self* methods now pass useAdapter=false and useWatcher=false
  • Added JSDoc explaining their use in distributed watcher callbacks
  • Affects: selfAddPolicy, selfRemovePolicy, selfUpdatePolicy, selfAddPolicies, selfRemovePolicies, selfRemoveFilteredPolicy

Added comprehensive test coverage (test/selfMethods.test.ts)

  • Verifies self* methods bypass both adapter and watcher
  • Confirms regular methods maintain existing behavior
  • 17 new tests covering all policy operation types

Usage

In a watcher callback, use self* methods to update local cache without triggering DB writes or notifications:

watcher.setUpdateCallback(async () => {
  // Updates in-memory model only - no DB write, no watcher notification
  await enforcer.selfAddPolicy('p', 'p', ['alice', 'data1', 'read']);
});

Backward compatible - existing calls to *Internal methods use default useAdapter=true.

Original prompt

This section details on the original issue you should resolve

<issue_title>Prevent infinite loops in distributed watchers by bypassing adapter in self* methods</issue_title>
<issue_description>Goal: Modify the Enforcer to allow updating the policy in memory without triggering the Adapter (database write) or the Watcher (notification), even when autoSave is enabled.

Detailed Implementation Plan:

Modify InternalEnforcer methods:

Update all internal modification methods (e.g., addPolicyInternal, removePolicyInternal, updatePolicyInternal, addPoliciesInternal, etc.).

Add a new optional parameter useAdapter: boolean to these methods.

Set the default value of useAdapter to true to ensure backward compatibility.

In the method body, wrap the adapter call logic (e.g., this.adapter.addPolicy(...)) with a check: if (useAdapter && this.adapter && this.autoSave).

Update ManagementEnforcer (self* methods):

Locate all self* methods (e.g., selfAddPolicy, selfRemovePolicy, selfUpdatePolicy, etc.).

Update their implementation to call the corresponding *Internal method passing false for the new useAdapter parameter (along with false for the existing useWatcher parameter).

This ensures that calling self* methods will strictly update the memory model only, bypassing both the database adapter and the watcher notification.

Documentation:

Add JSDoc comments to these self* methods explaining that they are intended for in-memory updates in distributed setups (e.g., inside a Watcher callback).

Expected Outcome: Users can call enforcer.selfAddPolicy(...) in a Watcher callback. This will update the local cache but prevent the dead-loop caused by writing back to the DB and triggering the Watcher again.</issue_description>

Comments on the Issue (you are @copilot in this section)

@hsluoyz The generated Pull request from this issue should fix this issue: https://github.com//issues/506

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@hsluoyz hsluoyz marked this pull request as ready for review January 6, 2026 07:21
@coveralls
Copy link

Pull Request Test Coverage Report for Build 20741224807

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 78.257%

Totals Coverage Status
Change from base Build 20679550322: 0.0%
Covered Lines: 1645
Relevant Lines: 2001

💛 - Coveralls

Copilot AI changed the title [WIP] Modify Enforcer to bypass adapter in self methods Prevent infinite loops in distributed watchers by bypassing adapter in self* methods Jan 6, 2026
Copilot AI requested a review from hsluoyz January 6, 2026 07:32
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.

Prevent infinite loops in distributed watchers by bypassing adapter in self* methods

4 participants