Skip to content

feat: custom module to propagate headers from subgraphs to federated response - #3121

Draft
alepane21 wants to merge 2 commits into
mainfrom
ale/eng-9894-custom-module-for-cache-tags
Draft

feat: custom module to propagate headers from subgraphs to federated response#3121
alepane21 wants to merge 2 commits into
mainfrom
ale/eng-9894-custom-module-for-cache-tags

Conversation

@alepane21

@alepane21 alepane21 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

This PR contains a module that allows to propagate cache tags from subgraph responses to the federated response.
The cache tags will be merged and the Cache-Control header will use the most restrictive settings from all the subgraph responses.
This module will disable the subgraph request deduplication (https://cosmo-docs.wundergraph.com/router/request-deduplication#layer-1-subgraph-request-deduplication).

Summary by CodeRabbit

  • New Features

    • Added support for collecting cache tags from subgraph responses and returning them in a configurable response header.
    • Aggregates cache-control directives across responses, including restrictive policies and the lowest available max-age.
    • Produces consistently sorted cache tags and safely isolates results between concurrent requests.
  • Bug Fixes

    • Ignores invalid or unrelated cache-tag headers and validates configured header names.

Checklist

Open Source AI Manifesto

This project follows the principles of the Open Source AI Manifesto. Please ensure your contribution aligns with its principles.

@alepane21 alepane21 changed the title feat: add a custom module to propagate headers from subgraphs to feat: custom module to propagate headers from subgraphs to federated response Jul 28, 2026
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Changes

Cache tag aggregation

Layer / File(s) Summary
Module configuration and router integration
router-tests/modules/cache-tags/module.go
Adds the cache_tags module, validates and normalizes its header configuration, initializes request-local state, and implements router lifecycle interfaces.
Tag and Cache-Control aggregation
router-tests/modules/cache-tags/module.go
Collects and deduplicates tags, merges restrictive cache directives using the lowest max-age, and writes sorted aggregated response headers.
Configuration and concurrent routing tests
router-tests/modules/cache_tags_test.go
Tests configuration errors, header aggregation, concurrent subgraph responses, singleflight behavior, request isolation, and supporting request helpers.

Estimated code review effort: 4 (Complex) | ~45 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: a custom module propagates subgraph headers into the federated response.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown

Router-nonroot image scan passed

✅ No security vulnerabilities found in image:

ghcr.io/wundergraph/cosmo/router:sha-cd2137240d02920f1762a35b8f5a85f006186b9d-nonroot

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (2)
router-tests/modules/cache_tags_test.go (1)

281-301: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer sync.WaitGroup.Go for the completion group.

done can drop the manual Add/defer Done bookkeeping (ready still needs manual handling as a start barrier).

Based on learnings: "In Go code (Go 1.25+), prefer using sync.WaitGroup.Go(func()) to run a function in a new goroutine, letting the WaitGroup manage Add/Done automatically."

♻️ Proposed refactor
 	var ready, done sync.WaitGroup
 	ready.Add(requestCount)
-	done.Add(requestCount)
 
 	trigger := make(chan struct{})
 	errs := make(chan error, requestCount)
 	responses := make([]*testenv.TestResponse, requestCount)
 	for i := range requestCount {
-		go func() {
-			defer done.Done()
+		done.Go(func() {
 			ready.Done()
 			<-trigger
 
 			response, err := xEnv.MakeGraphQLRequest(testenv.GraphQLRequest{Query: query})
 			if err != nil {
 				errs <- err
 				return
 			}
 			responses[i] = response
-		}()
+		})
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@router-tests/modules/cache_tags_test.go` around lines 281 - 301, Update the
goroutine launch in this test to use sync.WaitGroup.Go for the done completion
group, removing done.Add and the corresponding defer done.Done bookkeeping. Keep
the manual ready WaitGroup handling and start barrier unchanged.

Source: Learnings

router-tests/modules/cache-tags/module.go (1)

161-189: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Consider s-maxage / must-revalidate in the restrictive merge.

A subgraph sending s-maxage=30, must-revalidate currently contributes nothing, so the federated policy ends up less restrictive than the subgraph asked for. Fine if intentionally out of scope for this test module — otherwise fold them in.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@router-tests/modules/cache-tags/module.go` around lines 161 - 189, Extend
parseCacheControl to recognize s-maxage and must-revalidate during restrictive
policy merging, ensuring their values contribute to the returned
cacheControlPolicy rather than being ignored. Reuse the existing max-age parsing
and restrictive-minimum behavior for s-maxage, and update the policy
representation as needed for must-revalidate while preserving current directives
and return semantics.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@router-tests/modules/cache_tags_test.go`:
- Around line 281-301: Update the goroutine launch in this test to use
sync.WaitGroup.Go for the done completion group, removing done.Add and the
corresponding defer done.Done bookkeeping. Keep the manual ready WaitGroup
handling and start barrier unchanged.

In `@router-tests/modules/cache-tags/module.go`:
- Around line 161-189: Extend parseCacheControl to recognize s-maxage and
must-revalidate during restrictive policy merging, ensuring their values
contribute to the returned cacheControlPolicy rather than being ignored. Reuse
the existing max-age parsing and restrictive-minimum behavior for s-maxage, and
update the policy representation as needed for must-revalidate while preserving
current directives and return semantics.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 45c5cbfa-9df2-4a39-bc5a-111f24d4ddd0

📥 Commits

Reviewing files that changed from the base of the PR and between 1453866 and b1e1a5f.

📒 Files selected for processing (2)
  • router-tests/modules/cache-tags/module.go
  • router-tests/modules/cache_tags_test.go

@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 62.20%. Comparing base (1d3a296) to head (13ba4c5).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3121      +/-   ##
==========================================
+ Coverage   61.34%   62.20%   +0.86%     
==========================================
  Files         279      262      -17     
  Lines       32328    30868    -1460     
==========================================
- Hits        19831    19201     -630     
+ Misses      10924    10158     -766     
+ Partials     1573     1509      -64     

see 30 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.

1 participant