Skip to content

Commit 4b4124b

Browse files
committed
test+docs: add extra test and update README
1 parent 75db3f6 commit 4b4124b

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ docker run -d \
2424
- `AUTHZCACHE_INDIRECT_RELATION_CACHE_SIZE_PER_PROJECT` - Indirect relation cache size per project (default: 1,000,000)
2525
- `AUTHZCACHE_REMOTE_POLLING_INTERVAL_IN_MILLIS` - Remote polling interval in milliseconds (default: 15,000)
2626
- `AUTHZCACHE_PURGE_COOLDOWN_WINDOW_IN_MINUTES` - Cooldown window in minutes before purging cache on refresh error (default: 0, meaning immediate purge). When set to a positive value, the cache will wait for the specified duration after the first error before purging. If a successful response is received during the cooldown window, the purge is cancelled. This provides a balance between data freshness and availability during temporary service disruptions. During this window, the cache continues serving stale and potentially invalid authorization data, which may not reflect current permissions.
27+
- `AUTHZCACHE_METRICS_REPORT_ENABLED` - Whether to periodically report cache performance metrics (hit/miss rates, latency) to Descope (TRUE/FALSE, default: TRUE)
28+
- `AUTHZCACHE_METRICS_REPORT_INTERVAL_IN_SECONDS` - How often to report metrics, in seconds (default: 60, minimum: 10)
2729

2830
## Ports
2931
- **8189** - HTTP REST API endpoint

internal/services/authz_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,38 @@ func TestWhatCanTargetAccess_MetricsRecorded_CacheMiss(t *testing.T) {
629629
require.Equal(t, int64(1), agg.SumResultSize)
630630
}
631631

632+
func TestWhatCanTargetAccess_MetricsRecorded_CacheHit(t *testing.T) {
633+
ac, _, mockCache, collector := injectAuthzMocksWithCollector(t)
634+
ctx := cctx.AddProjectID(context.TODO(), "proj1")
635+
candidates := []*descope.AuthzRelation{
636+
{Resource: "doc1", RelationDefinition: "viewer", Namespace: "docs", Target: "u1"},
637+
{Resource: "doc2", RelationDefinition: "editor", Namespace: "docs", Target: "u1"},
638+
{Resource: "doc3", RelationDefinition: "viewer", Namespace: "docs", Target: "u1"},
639+
}
640+
mockCache.GetWhatCanTargetAccessCachedFunc = func(_ context.Context, _ string) ([]*descope.AuthzRelation, bool) {
641+
return candidates, true
642+
}
643+
mockCache.SetWhatCanTargetAccessCachedFunc = func(_ context.Context, _ string, _ []*descope.AuthzRelation) {
644+
require.Fail(t, "should not update cache on hit")
645+
}
646+
mockCache.CheckRelationFunc = func(_ context.Context, r *descope.FGARelation) (bool, bool, bool) {
647+
return r.Resource != "doc2", true, true // doc2 filtered out
648+
}
649+
mockCache.UpdateCacheWithChecksFunc = func(_ context.Context, _ []*descope.FGACheck) {}
650+
_, err := ac.WhatCanTargetAccess(ctx, "u1")
651+
require.NoError(t, err)
652+
snapshot := collector.SnapshotAndReset()
653+
require.Contains(t, snapshot, "proj1")
654+
agg := snapshot["proj1"][metrics.APIWhatCanTargetAccess]
655+
require.NotNil(t, agg)
656+
require.Equal(t, int64(1), agg.TotalCalls)
657+
require.Equal(t, int64(1), agg.HitCount)
658+
require.Equal(t, int64(0), agg.MissCount)
659+
require.Equal(t, int64(3), agg.SumCandidates)
660+
require.Equal(t, int64(1), agg.SumFiltered) // doc2 filtered out
661+
require.Equal(t, int64(2), agg.SumResultSize)
662+
}
663+
632664
func BenchmarkCheck(b *testing.B) {
633665
for _, numRelations := range []int{500, 1000, 5000} {
634666
name := fmt.Sprintf("relations=%d", numRelations)

0 commit comments

Comments
 (0)