Skip to content

feat: source caching#8291

Merged
olblak merged 6 commits into
updatecli:mainfrom
loispostula:lp/8071
Apr 10, 2026
Merged

feat: source caching#8291
olblak merged 6 commits into
updatecli:mainfrom
loispostula:lp/8071

Conversation

@loispostula

Copy link
Copy Markdown
Contributor

Summary

Fix #8071

Implements a two-layer in-memory caching system to reduce redundant API calls during pipeline execution, as proposed in #8071.

Layer 1: HTTP Response Cache (pkg/core/httpclient/)

A cachingTransport wrapping the existing HTTP transport chain caches successful (2xx) GET responses in memory. All plugins benefit automatically since they go through the centralized httpclient package — zero plugin changes required.

  • Enabled/disabled via EnableHTTPCache()/DisableHTTPCache() in Engine.Run()
  • Only caches GET requests with 2xx status codes
  • Thread-safe via sync.RWMutex

Layer 2: Source Result Cache (pkg/core/cache/)

A SourceCache shared across pipelines deduplicates source executions when the same Kind+Spec appears in multiple pipelines (or multiple times within one). The cache key is a SHA256 of only Kind + sanitized Spec (via ReportConfig()), so sources with the same plugin config but different names, transformers, or dependsOn share a cache entry.

  • Transformers are not cached — they are re-applied on cache hit
  • Only successful results are cached
  • Injected from Engine into each Pipeline before execution

How they complement each other

Scenario Layer hit
Same Kind+Spec across sources/pipelines Source cache — skips execution entirely
Different Spec but same underlying API URL HTTP cache — skips network call, plugin still filters locally
# Single manifest, three sources, one network call:

source: golang-1.23
  http cache store: https://go.dev/dl/?mode=json&include=all   # fresh API call

source: golang-1.22
  http cache hit: https://go.dev/dl/?mode=json&include=all     # different filter, same URL

source: golang-1.23-dup
  source cache hit for "Get Golang 1.23 duplicate"             # same Kind+Spec

Test

To test this pull request, you can run the following commands:

go test -race ./pkg/core/cache/ ./pkg/core/httpclient/ ./pkg/core/pipeline/ ./pkg/core/engine/

Additional Information

Checklist

  • I have updated the documentation via pull request in website repository.

Tradeoff

  • The cache.Key() function calls resource.New() to obtain ReportConfig(), which means the plugin is instantiated twice on a cache miss (once for key, once for execution). This is acceptable for now as plugin constructors are lightweight.
  • The shell resource kind is cached like any other resource. For sources with side effects, this may need an opt-out mechanism in a future iteration — pending maintainer input.
  • HTTP cache keys use the URL string only. Requests to the same URL with different auth headers would share a cache entry, which is correct for updatecli's usage patterns (consistent auth per endpoint within a run).

Potential improvement

  • Add a singleflight.Group to coalesce concurrent cache misses for the same key if pipeline execution is ever parallelized.
  • Add an opt-out config flag (nocache: true) per source for resources with side effects.
  • Optimize double resource.New() by threading the instantiated resource through the cache key computation.
  • Extend caching to conditions (second cache map as described in Feature Request: Cache result resource #8071).

Introduces a shared SourceCache that deduplicates source executions
across pipelines within a single updatecli run. Sources with identical
Kind+Spec (after sanitization via ReportConfig) share a cache entry,
regardless of Name, Transformers, or DependsOn differences.

Refs: updatecli#8071

Signed-off-by: Loïs Postula <[email protected]>
Adds a cachingTransport that wraps the existing HTTP transport chain,
caching successful GET responses in memory for the duration of one
updatecli execution. This complements the source-level cache by
deduplicating HTTP calls even when sources have different configs
but query the same API endpoint.

Refs: updatecli#8071

Signed-off-by: Loïs Postula <[email protected]>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Implements two in-memory caching layers to reduce redundant API calls and duplicate source executions during an updatecli run, addressing #8071 by caching HTTP GET responses centrally and deduplicating identical source executions across pipelines.

Changes:

  • Add an opt-in HTTP response cache via a cachingTransport in pkg/core/httpclient, toggled from Engine.Run().
  • Add a shared SourceCache keyed by a hash of Kind + sanitized Spec, injected from Engine into each Pipeline.
  • Update pipeline source execution to consult/populate the shared cache and add tests for both caching layers.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
pkg/core/pipeline/sources.go Pass shared SourceCache into source execution.
pkg/core/pipeline/sources_test.go Add pipeline-level cache miss/hit tests using a shared SourceCache.
pkg/core/pipeline/source/main.go Implement source result caching (skip execution on hit; cache on successful miss).
pkg/core/pipeline/main.go Add SourceCache field to Pipeline for engine injection.
pkg/core/httpclient/transport.go Add global enable/disable hook to swap in caching transport for new clients.
pkg/core/httpclient/caching.go New cachingTransport that caches successful GET responses in memory.
pkg/core/httpclient/caching_test.go Add coverage for caching behavior, enable/disable toggling, and concurrency safety.
pkg/core/engine/run.go Initialize/inject SourceCache and enable HTTP cache during engine execution.
pkg/core/engine/main.go Add sourceCache field to Engine.
pkg/core/cache/source.go New SourceCache implementation and keying via ReportConfig() hashing.
pkg/core/cache/source_test.go Add unit tests for SourceCache and Key() behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pkg/core/cache/source_test.go
Comment thread pkg/core/cache/source_test.go
Comment thread pkg/core/httpclient/caching.go
Comment thread pkg/core/httpclient/caching.go
Comment thread pkg/core/httpclient/transport.go Outdated
Comment thread pkg/core/engine/run.go Outdated
Comment thread pkg/core/pipeline/source/main.go
loispostula and others added 3 commits April 3, 2026 20:01
- Populate Status and ContentLength on cached HTTP responses
- Reinitialize sourceCache on each Engine.Run() to prevent stale data
- Fix DisableHTTPCache doc to accurately describe GC behavior

Signed-off-by: Loïs Postula <[email protected]>
@olblak olblak added enhancement New feature or request core All things related to Updatecli core engine labels Apr 9, 2026
Comment thread pkg/core/cache/source.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core All things related to Updatecli core engine enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Cache result resource

3 participants