File: README.md

package info (click to toggle)
golang-github-lestrrat-go-httprc 1.0.6-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 168 kB
  • sloc: perl: 56; sh: 6; makefile: 2
file content (130 lines) | stat: -rw-r--r-- 3,678 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# github.com/lestrrat-go/httprc ![](https://github.com/lestrrat-go/httprc/workflows/CI/badge.svg) [![Go Reference](https://pkg.go.dev/badge/github.com/lestrrat-go/httprc.svg)](https://pkg.go.dev/github.com/lestrrat-go/httprc) [![codecov.io](https://codecov.io/github/lestrrat-go/httprc/coverage.svg)](https://codecov.io/github/lestrrat-go/httprc)

`httprc` is a HTTP "Refresh" Cache. Its aim is to cache a remote resource that
can be fetched via HTTP, but keep the cached content up-to-date based on periodic
refreshing.

# SYNOPSIS

<!-- INCLUDE(httprc_example_test.go) -->
```go
package httprc_test

import (
  "context"
  "fmt"
  "net/http"
  "net/http/httptest"
  "sync"
  "time"

  "github.com/lestrrat-go/httprc"
)

const (
  helloWorld   = `Hello World!`
  goodbyeWorld = `Goodbye World!`
)

func ExampleCache() {
  var mu sync.RWMutex

  msg := helloWorld

  srv := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    w.Header().Set(`Cache-Control`, fmt.Sprintf(`max-age=%d`, 2))
    w.WriteHeader(http.StatusOK)
    mu.RLock()
    fmt.Fprint(w, msg)
    mu.RUnlock()
  }))
  defer srv.Close()

  ctx, cancel := context.WithCancel(context.Background())
  defer cancel()

  errSink := httprc.ErrSinkFunc(func(err error) {
    fmt.Printf("%s\n", err)
  })

  c := httprc.NewCache(ctx,
    httprc.WithErrSink(errSink),
    httprc.WithRefreshWindow(time.Second), // force checks every second
  )

  c.Register(srv.URL,
    httprc.WithHTTPClient(srv.Client()),        // we need client with TLS settings
    httprc.WithMinRefreshInterval(time.Second), // allow max-age=1 (smallest)
  )

  payload, err := c.Get(ctx, srv.URL)
  if err != nil {
    fmt.Printf("%s\n", err)
    return
  }

  if string(payload.([]byte)) != helloWorld {
    fmt.Printf("payload mismatch: %s\n", payload)
    return
  }

  mu.Lock()
  msg = goodbyeWorld
  mu.Unlock()

  time.Sleep(4 * time.Second)

  payload, err = c.Get(ctx, srv.URL)
  if err != nil {
    fmt.Printf("%s\n", err)
    return
  }

  if string(payload.([]byte)) != goodbyeWorld {
    fmt.Printf("payload mismatch: %s\n", payload)
    return
  }

  cancel()

  // OUTPUT:
}
```
source: [httprc_example_test.go](https://github.com/lestrrat-go/jwx/blob/refs/heads/main/httprc_example_test.go)
<!-- END INCLUDE -->

# Sequence Diagram

```mermaid
sequenceDiagram
  autonumber
  actor User
  participant httprc.Cache
  participant httprc.Storage
  User->>httprc.Cache: Fetch URL `u`
  activate httprc.Storage
  httprc.Cache->>httprc.Storage: Fetch local cache for `u`
  alt Cache exists
    httprc.Storage-->httprc.Cache: Return local cache
    httprc.Cache-->>User: Return data
    Note over httprc.Storage: If the cache exists, there's nothing more to do.<br />The cached content will be updated periodically in httprc.Refresher
    deactivate httprc.Storage
  else Cache does not exist
    activate httprc.Fetcher
    httprc.Cache->>httprc.Fetcher: Fetch remote resource `u`
    httprc.Fetcher-->>httprc.Cache: Return fetched data
    deactivate httprc.Fetcher
    httprc.Cache-->>User: Return data
    httprc.Cache-)httprc.Refresher: Enqueue into auto-refresh queue
    activate httprc.Refresher
    loop Refresh Loop
      Note over httprc.Storage,httprc.Fetcher: Cached contents are updated synchronously
      httprc.Refresher->>httprc.Refresher: Wait until next refresh
      httprc.Refresher-->>httprc.Fetcher: Request fetch
      httprc.Fetcher->>httprc.Refresher: Return fetched data
      httprc.Refresher-->>httprc.Storage: Store new version in cache
      httprc.Refresher->>httprc.Refresher: Enqueue into auto-refresh queue (again)
    end
    deactivate httprc.Refresher
  end
```