Skip to content

Commit 4f4af69

Browse files
Milinda Diasclaude
authored andcommitted
feat(demo): entity caching demo subgraphs, cache-demo runner, and test subgraphs
Extracted from jensneuse/entity-caching-v2 (PR #2777) — demo layer, stacked on the composition+proto PR. - cachegraph / cachegraph_ext / viewer: demo subgraphs exercising the caching directives (mutable data store, latency injector, auth profiles) - cmd/cache-demo: standalone cache-only runner (ports 4012-4014) - pkg/subgraphs/cachetest: the six deterministic subgraphs consumed by the router-tests entity_caching suite (articles, articlesmeta, details, inventory, items, viewer) - graph-cache-only.yaml + config-cache-only.json + Makefile compose targets Builds and tests green against the base router (no router changes required). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 51f766e commit 4f4af69

119 files changed

Lines changed: 59445 additions & 12 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

demo/Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ plugin-build-ci: plugin-build-ci-go-binary plugin-build-ci-bun-binary
4444
cp -a pkg/subgraphs/projects/bin/* ../router/plugins/projects/bin/
4545
cp -a pkg/subgraphs/courses/bin/* ../router/plugins/courses/bin/
4646

47+
compose-cache:
48+
$(wgc_router_ci) compose -i ./graph-cache-only.yaml -o ./config-cache-only.json
49+
4750
standalone-compose:
4851
$(wgc_router) compose -i ./graph-with-standalone.yaml -o ./configWithStandalone.json
4952
pnpx prettier ./configWithStandalone.json -w
@@ -57,3 +60,11 @@ build-manifest:
5760

5861
build-manifest-integration:
5962
python3 build_manifest.py --router-config ./config.json --out ../router-tests/testenv/testdata/manifest --cleanup
63+
64+
generate-cachetest:
65+
cd pkg/subgraphs/cachetest/items && go run github.com/99designs/gqlgen generate
66+
cd pkg/subgraphs/cachetest/details && go run github.com/99designs/gqlgen generate
67+
cd pkg/subgraphs/cachetest/inventory && go run github.com/99designs/gqlgen generate
68+
cd pkg/subgraphs/cachetest/viewer && go run github.com/99designs/gqlgen generate
69+
cd pkg/subgraphs/cachetest/articles && go run github.com/99designs/gqlgen generate
70+
cd pkg/subgraphs/cachetest/articlesmeta && go run github.com/99designs/gqlgen generate

demo/cmd/all/main.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ var (
2020
mood = flag.Int("mood", 4008, "Port for mood subgraph")
2121
countries = flag.Int("countries", 4009, "Port for countries subgraph")
2222
productsFeatureSubgraph = flag.Int("products_fg", 4010, "Port for products feature subgraph")
23+
cacheGraph = flag.Int("cachegraph", 4012, "Port for cachegraph subgraph")
24+
cacheGraphExt = flag.Int("cachegraph_ext", 4013, "Port for cachegraph-ext subgraph")
25+
viewerSubgraph = flag.Int("viewer", 4014, "Port for viewer subgraph")
2326
)
2427

2528
func main() {
@@ -35,6 +38,9 @@ func main() {
3538
Mood: *mood,
3639
Countries: *countries,
3740
ProductsFG: *productsFeatureSubgraph,
41+
CacheGraph: *cacheGraph,
42+
CacheGraphExt: *cacheGraphExt,
43+
Viewer: *viewerSubgraph,
3844
},
3945
EnableDebug: *debug,
4046
GetPubSubName: func(name string) string {

demo/cmd/cache-demo/main.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// cache-demo runs only the cache-related subgraphs without requiring NATS.
2+
package main
3+
4+
import (
5+
"log"
6+
"net/http"
7+
"strconv"
8+
9+
"github.com/99designs/gqlgen/graphql"
10+
"github.com/99designs/gqlgen/graphql/handler"
11+
"github.com/99designs/gqlgen/graphql/handler/transport"
12+
"github.com/99designs/gqlgen/graphql/playground"
13+
"golang.org/x/sync/errgroup"
14+
15+
"github.com/wundergraph/cosmo/demo/pkg/injector"
16+
"github.com/wundergraph/cosmo/demo/pkg/subgraphs/cachegraph"
17+
"github.com/wundergraph/cosmo/demo/pkg/subgraphs/cachegraph_ext"
18+
"github.com/wundergraph/cosmo/demo/pkg/subgraphs/viewer"
19+
)
20+
21+
func main() {
22+
servers := []*http.Server{
23+
gqlServer("cachegraph", 4012, cachegraph.NewSchema()),
24+
gqlServer("cachegraph-ext", 4013, cachegraph_ext.NewSchema()),
25+
viewerServer(4014),
26+
}
27+
28+
log.Println("Cache demo subgraphs starting (no NATS required):")
29+
log.Println(" cachegraph: http://localhost:4012/")
30+
log.Println(" cachegraph-ext: http://localhost:4013/")
31+
log.Println(" viewer: http://localhost:4014/")
32+
33+
g := new(errgroup.Group)
34+
for _, srv := range servers {
35+
g.Go(srv.ListenAndServe)
36+
}
37+
log.Fatal(g.Wait())
38+
}
39+
40+
func gqlServer(name string, port int, schema graphql.ExecutableSchema) *http.Server {
41+
srv := handler.New(schema)
42+
srv.AddTransport(transport.POST{})
43+
srv.AddTransport(transport.GET{})
44+
mux := http.NewServeMux()
45+
mux.Handle("/", playground.Handler(name, "/graphql"))
46+
mux.Handle("/graphql", srv)
47+
return &http.Server{Addr: ":" + strconv.Itoa(port), Handler: injector.Latency(injector.HTTP(mux))}
48+
}
49+
50+
func viewerServer(port int) *http.Server {
51+
mux := http.NewServeMux()
52+
mux.Handle("/", playground.Handler("viewer", "/graphql"))
53+
mux.Handle("/graphql", viewer.NewHandler())
54+
return &http.Server{Addr: ":" + strconv.Itoa(port), Handler: injector.Latency(injector.HTTP(mux))}
55+
}

demo/config-cache-only.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

demo/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/nats-io/nats.go v1.35.0
1010
github.com/ravilushqa/otelgqlgen v0.13.1
1111
github.com/rs/cors v1.11.0
12+
github.com/stretchr/testify v1.11.1
1213
github.com/vektah/gqlparser/v2 v2.5.30
1314
github.com/wundergraph/cosmo/router v0.0.0-20260330183556-dc4388d100a4
1415
github.com/wundergraph/cosmo/router-tests v0.0.0-20260330183556-dc4388d100a4
@@ -128,7 +129,6 @@ require (
128129
github.com/sosodev/duration v1.3.1 // indirect
129130
github.com/spf13/cast v1.7.1 // indirect
130131
github.com/stretchr/objx v0.5.2 // indirect
131-
github.com/stretchr/testify v1.11.1 // indirect
132132
github.com/tidwall/gjson v1.18.0 // indirect
133133
github.com/tidwall/match v1.1.1 // indirect
134134
github.com/tidwall/pretty v1.2.1 // indirect

demo/graph-cache-only.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
version: 1
2+
subgraphs:
3+
- name: cachegraph
4+
routing_url: http://localhost:4012/graphql
5+
schema:
6+
file: ./pkg/subgraphs/cachegraph/subgraph/schema.graphqls
7+
- name: cachegraph-ext
8+
routing_url: http://localhost:4013/graphql
9+
schema:
10+
file: ./pkg/subgraphs/cachegraph_ext/subgraph/schema.graphqls
11+
- name: viewer
12+
routing_url: http://localhost:4014/graphql
13+
schema:
14+
file: ./pkg/subgraphs/viewer/subgraph/schema.graphqls

demo/graph.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ subgraphs:
4040
routing_url: http://localhost:4009/graphql
4141
schema:
4242
file: ./pkg/subgraphs/countries/subgraph/schema.graphqls
43+
- name: cachegraph
44+
routing_url: http://localhost:4012/graphql
45+
schema:
46+
file: ./pkg/subgraphs/cachegraph/subgraph/schema.graphqls
4347
- name: employeeupdated
4448
schema:
4549
file: ./pkg/subgraphs/employeeupdated/subgraph/schema.graphqls

demo/pkg/injector/latency.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package injector
2+
3+
import (
4+
"log"
5+
"net/http"
6+
"strconv"
7+
"time"
8+
)
9+
10+
// ArtificialLatencyHeader lets the playground or any client inject fake latency
11+
// into a demo subgraph response. Value is milliseconds as an integer, bounded
12+
// at 10000. Intended for demos where local subgraphs are too fast to make
13+
// caching benefits visible.
14+
const ArtificialLatencyHeader = "X-Artificial-Latency"
15+
16+
// Latency wraps a handler and sleeps for the number of milliseconds specified
17+
// in the X-Artificial-Latency request header before passing the request down.
18+
// Invalid values are silently ignored.
19+
func Latency(next http.Handler) http.Handler {
20+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
21+
if v := r.Header.Get(ArtificialLatencyHeader); v != "" {
22+
if ms, err := strconv.Atoi(v); err == nil && ms > 0 && ms <= 10000 {
23+
log.Printf("[latency] %s %s sleep %dms prefix=%q", r.Method, r.Host, ms, r.Header.Get("X-WG-Cache-Key-Prefix"))
24+
time.Sleep(time.Duration(ms) * time.Millisecond)
25+
}
26+
}
27+
next.ServeHTTP(w, r)
28+
})
29+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package cachegraph
2+
3+
import (
4+
"github.com/99designs/gqlgen/graphql"
5+
6+
"github.com/wundergraph/cosmo/demo/pkg/subgraphs/cachegraph/subgraph"
7+
"github.com/wundergraph/cosmo/demo/pkg/subgraphs/cachegraph/subgraph/generated"
8+
)
9+
10+
func NewSchema() graphql.ExecutableSchema {
11+
return generated.NewExecutableSchema(generated.Config{Resolvers: subgraph.NewResolver()})
12+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
//go:generate go run github.com/99designs/gqlgen generate
2+
package cachegraph

0 commit comments

Comments
 (0)