Skip to content

feat: cache registry data in the adapter (#109) - #123

Closed
tdprajwal wants to merge 5 commits into
developmentfrom
feat/109-cache-registry-data
Closed

tdprajwal wants to merge 5 commits into
developmentfrom
feat/109-cache-registry-data

Conversation

@tdprajwal

@tdprajwal tdprajwal commented Nov 3, 2026 •

Copy link
Copy Markdown

Closes #109

What

  • Cache the agreement lookup (agreementWith), including "no agreement" for callers the registry knows. Registry errors are not cached.
  • Never refuse on cached data: re-check the registry before refusing.
  • Treat an empty cache read as a miss (fixes the false "unreadable cache entry" warning).
  • Enable caching in config/provider-adapter.yaml (cacheTTL: 30s).

Testing

  • go test ./... passes.
  • Quick-start, single- and multi-adapter: registry calls go from 18 to 4 cold and 0 warm.

Note

A suspension can take up to cacheTTL (30s) to take effect; reinstatement is immediate. For an instant effect, delete the registry_* keys in Redis. Instant barring is left for a follow-up.

A refusal based on a cached answer re-checks the registry, so a peer that keeps sending refused requests still reaches the registry once per request.

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

🛡️ Trivy security scan (CRITICAL,HIGH,MEDIUM,LOW)

View full run

Go dependencies

No findings at CRITICAL,HIGH,MEDIUM,LOW.

Container image

No findings at CRITICAL,HIGH,MEDIUM,LOW.

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

📊 Test Coverage: ✅ Passed — 96% of changed lines covered, min 80%

@tdprajwal tdprajwal left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Self-review notes for reviewers.

}
return model.Agreement{}, nil
// Unknown callers are not cached, so unsigned requests cannot fill Redis.
if len(records) > 0 {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Unknown callers aren't cached. This check runs before the signature is verified, so caching every name would let anyone fill Redis.

if refusal == nil || !fromCache {
return refusal
}
// Never refuse on a cached answer; recheck the registry first.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

A refusal is never served from cache, so a reinstated network gets in at once. The cost is one registry call per refused request (noted in the PR description)

}

// judgeRequester applies what we agreed with caller to one request.
func judgeRequester(ctx context.Context, caller, action string, schemaContexts []string, agreed model.Agreement) error {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

judgeRequester is the original logic moved out unchanged, so it can run twice.

@ameersohel45

Copy link
Copy Markdown
Collaborator

We don't need the changes in pkg/plugin/implementation/cache/.

  • prefix: we don't share Redis with another network, so keys can't collide.
  • required: "false": if the cache plugin is in the config, Redis is expected to be there. We'd rather the adapter fail to start than run without it.

Please drop that folder from this PR and remove required and prefix from config/provider-adapter.yaml. The agreement cache in sunbirdRegistry works without them.

@tdprajwal

Copy link
Copy Markdown
Author

Done: dropped the cache/ changes and removed required and prefix from the config. One note: if Redis goes down while the adapter is running, requests fall back to the go-redis default timeouts (about 4s per request) until it's back. Happy to raise that separately if it matters.

@ameersohel45

Copy link
Copy Markdown
Collaborator

Please add tests for the agreement cache in sunbirdRegistry:

  • A second request is served from Redis and doesn't call the registry.
  • A caller the registry knows, with no agreement, is cached. An unknown caller is not.
  • When the cache says refuse, the registry is asked again and the fresh answer wins.
  • A registry error is not cached.

@ameersohel45

Copy link
Copy Markdown
Collaborator

The cache needs Redis, and helmcharts has none for the adapter. Please carry the change there, as a separate PR:

  • quick-start/docker-compose.yml: add a Redis service, and the cache plugin and cacheTTL in the adapter configs.
  • charts/adapter-service: add Redis, or a value that points at an external one. Add the same cache plugin config. The plugin reads the password from REDIS_PASSWORD, so the chart must pass it in from a secret.

@tdprajwal

Copy link
Copy Markdown
Author

Added tests for the agreement cache in sunbirdRegistry/agreementcache_test.go, covering all four cases plus a failed recheck, cacheTTL 0, and an unreadable entry. I'll raise the helmcharts change as a separate PR.

@tdprajwal

Copy link
Copy Markdown
Author

The helmcharts change is up as a separate PR: OpenAgriNet/helmcharts#125 (Redis in quick-start, and cache.addr / cache.passwordSecret in charts/adapter-service).

@tdprajwal

Copy link
Copy Markdown
Author

Superseded by #132.

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.

2 participants