You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@casbin.apache.org by hs...@apache.org on 2026/04/25 09:25:52 UTC
(casbin) branch master updated (e85fcda -> 74322db)
This is an automated email from the ASF dual-hosted git repository.
hsluoyz pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/casbin.git
omit e85fcda fix: fix GitHub release notes (#1725)
omit 26288f9 fix: add gFunctionCache boolean option to enforcer
omit d60ee5e fix: improve snapshot publish (#1724)
new 74322db fix: add gFunctionCache boolean option to enforcer
This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version. This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:
* -- * -- B -- O -- O -- O (e85fcda)
\
N -- N -- N refs/heads/master (74322db)
You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.
Any revisions marked "omit" are not gone; other references still
refer to them. Any revisions marked "discard" are gone forever.
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.github/workflows/default.yml | 19 ++++
.github/workflows/source-release-draft.yml | 137 --------------------------
.github/workflows/source-snapshot.yml | 148 -----------------------------
.releaserc.json | 16 ++++
Makefile | 3 +
5 files changed, 38 insertions(+), 285 deletions(-)
delete mode 100644 .github/workflows/source-release-draft.yml
delete mode 100644 .github/workflows/source-snapshot.yml
create mode 100644 .releaserc.json
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@casbin.apache.org
For additional commands, e-mail: commits-help@casbin.apache.org
(casbin) 01/01: fix: add gFunctionCache boolean option to enforcer
Posted by hs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
hsluoyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/casbin.git
commit 74322db8ebd2fa7a9e15e7369db6add65498f83b
Author: Yang Luo <hs...@gmail.com>
AuthorDate: Fri Apr 24 21:52:57 2026 +0800
fix: add gFunctionCache boolean option to enforcer
---
enforcer.go | 12 +++++++++-
management_api.go | 2 +-
util/builtin_operators.go | 61 ++++++++++++++++++++++++++++++-----------------
3 files changed, 51 insertions(+), 24 deletions(-)
diff --git a/enforcer.go b/enforcer.go
index a6bf174..c78350c 100644
--- a/enforcer.go
+++ b/enforcer.go
@@ -56,6 +56,7 @@ type Enforcer struct {
autoNotifyWatcher bool
autoNotifyDispatcher bool
acceptJsonRequest bool
+ gFunctionCache bool
aiConfig AIConfig
}
@@ -193,6 +194,7 @@ func (e *Enforcer) initialize() {
e.autoBuildRoleLinks = true
e.autoNotifyWatcher = true
e.autoNotifyDispatcher = true
+ e.gFunctionCache = true
e.initRmMap()
// Initialize detectors with default detector if not already set
@@ -637,6 +639,14 @@ func (e *Enforcer) EnableAcceptJsonRequest(acceptJsonRequest bool) {
e.acceptJsonRequest = acceptJsonRequest
}
+// EnableGFunctionCache controls whether to cache g() function results.
+// Disable this when inputs are high-cardinality (e.g. UUIDs or dynamic paths)
+// to prevent unbounded memory growth.
+func (e *Enforcer) EnableGFunctionCache(enabled bool) {
+ e.gFunctionCache = enabled
+ e.invalidateMatcherMap()
+}
+
// BuildRoleLinks manually rebuild the role inheritance relations.
func (e *Enforcer) BuildRoleLinks() error {
e.invalidateMatcherMap()
@@ -704,7 +714,7 @@ func (e *Enforcer) enforce(matcher string, explains *[]string, rvals ...interfac
// or a conditional role definition (ast.CondRM != nil)
// ast.RM and ast.CondRM shouldn't be nil at the same time
if ast.RM != nil {
- functions[key] = util.GenerateGFunction(ast.RM)
+ functions[key] = util.GenerateGFunction(ast.RM, e.gFunctionCache)
}
if ast.CondRM != nil {
functions[key] = util.GenerateConditionalGFunction(ast.CondRM)
diff --git a/management_api.go b/management_api.go
index 7a8f768..d18536c 100644
--- a/management_api.go
+++ b/management_api.go
@@ -145,7 +145,7 @@ func (e *Enforcer) GetFilteredNamedPolicyWithMatcher(ptype string, matcher strin
// or a conditional role definition (ast.CondRM != nil)
// ast.RM and ast.CondRM shouldn't be nil at the same time
if ast.RM != nil {
- functions[key] = util.GenerateGFunction(ast.RM)
+ functions[key] = util.GenerateGFunction(ast.RM, e.gFunctionCache)
}
if ast.CondRM != nil {
functions[key] = util.GenerateConditionalGFunction(ast.CondRM)
diff --git a/util/builtin_operators.go b/util/builtin_operators.go
index 37d9cb5..066a0bd 100644
--- a/util/builtin_operators.go
+++ b/util/builtin_operators.go
@@ -402,34 +402,53 @@ func GlobMatchFunc(args ...interface{}) (interface{}, error) {
}
// GenerateGFunction is the factory method of the g(_, _[, _]) function.
-func GenerateGFunction(rm rbac.RoleManager) govaluate.ExpressionFunction {
+// If useCache is true, results are memoized per unique argument combination for performance.
+// Set useCache to false when inputs are high-cardinality (e.g. UUIDs) to avoid unbounded memory growth.
+func GenerateGFunction(rm rbac.RoleManager, useCache bool) govaluate.ExpressionFunction {
memorized := sync.Map{}
return func(args ...interface{}) (interface{}, error) {
// Like all our other govaluate functions, all args are strings.
- // Allocate and generate a cache key from the arguments...
- total := len(args)
- for _, a := range args {
- aStr := a.(string)
- total += len(aStr)
- }
- builder := strings.Builder{}
- builder.Grow(total)
- for _, arg := range args {
- builder.WriteByte(0)
- builder.WriteString(arg.(string))
- }
- key := builder.String()
-
- // ...and see if we've already calculated this.
- v, found := memorized.Load(key)
- if found {
+ if useCache {
+ // Allocate and generate a cache key from the arguments...
+ total := len(args)
+ for _, a := range args {
+ aStr := a.(string)
+ total += len(aStr)
+ }
+ builder := strings.Builder{}
+ builder.Grow(total)
+ for _, arg := range args {
+ builder.WriteByte(0)
+ builder.WriteString(arg.(string))
+ }
+ key := builder.String()
+
+ // ...and see if we've already calculated this.
+ if v, found := memorized.Load(key); found {
+ return v, nil
+ }
+
+ // If not, do the calculation.
+ // There are guaranteed to be exactly 2 or 3 arguments.
+ name1, name2 := args[0].(string), args[1].(string)
+ var v interface{}
+ if rm == nil {
+ v = name1 == name2
+ } else if len(args) == 2 {
+ v, _ = rm.HasLink(name1, name2)
+ } else {
+ domain := args[2].(string)
+ v, _ = rm.HasLink(name1, name2, domain)
+ }
+
+ memorized.Store(key, v)
return v, nil
}
- // If not, do the calculation.
- // There are guaranteed to be exactly 2 or 3 arguments.
+ // No caching path.
name1, name2 := args[0].(string), args[1].(string)
+ var v interface{}
if rm == nil {
v = name1 == name2
} else if len(args) == 2 {
@@ -438,8 +457,6 @@ func GenerateGFunction(rm rbac.RoleManager) govaluate.ExpressionFunction {
domain := args[2].(string)
v, _ = rm.HasLink(name1, name2, domain)
}
-
- memorized.Store(key, v)
return v, nil
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@casbin.apache.org
For additional commands, e-mail: commits-help@casbin.apache.org