go 63 lines · 9 steps

Deduping in-flight requests in Gin

A middleware that collapses identical concurrent requests so only one runs while the rest wait for and share its response.

Explained by highlit
1package handler
2 
3type flightResult struct {
4 status int
5 body []byte
6}
7 
8type inflightEntry struct {
9 done chan struct{}
10 result flightResult
11}
12 
13type flightRegistry struct {
14 mu sync.Mutex
15 pending map[string]*inflightEntry
16}
17 
18var registry = &flightRegistry{pending: make(map[string]*inflightEntry)}
19 
20func Dedupe() gin.HandlerFunc {
21 return func(c *gin.Context) {
22 key := c.Request.Method + " " + c.FullPath() + "?" + c.Request.URL.RawQuery
23 
24 registry.mu.Lock()
25 if entry, ok := registry.pending[key]; ok {
26 registry.mu.Unlock()
27 <-entry.done
28 c.Header("X-Deduped", "1")
29 c.Data(entry.result.status, "application/json", entry.result.body)
30 c.Abort()
31 return
32 }
33 entry := &inflightEntry{done: make(chan struct{})}
34 registry.pending[key] = entry
35 registry.mu.Unlock()
36 
37 rec := &bodyRecorder{ResponseWriter: c.Writer, buf: &bytes.Buffer{}}
38 c.Writer = rec
39 
40 c.Next()
41 
42 entry.result = flightResult{status: rec.Status(), body: rec.buf.Bytes()}
43 close(entry.done)
44 
45 time.AfterFunc(2*time.Second, func() {
46 registry.mu.Lock()
47 if registry.pending[key] == entry {
48 delete(registry.pending, key)
49 }
50 registry.mu.Unlock()
51 })
52 }
53}
54 
55type bodyRecorder struct {
56 gin.ResponseWriter
57 buf *bytes.Buffer
58}
59 
60func (r *bodyRecorder) Write(b []byte) (int, error) {
61 r.buf.Write(b)
62 return r.ResponseWriter.Write(b)
63}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1A shared map guarded by a mutex plus a done channel lets many goroutines wait on one in-flight computation.
  2. 2Wrapping the ResponseWriter captures the response body so it can be replayed to duplicate callers.
  3. 3Cleaning up the registry entry after a short delay bounds how long results are shared without leaking memory.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Deduping in-flight requests in Gin — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code