Skip to content

Commit

Permalink
progress so far
Browse files Browse the repository at this point in the history
  • Loading branch information
lestrrat committed Mar 20, 2022
1 parent bd6d481 commit d23a7ba
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 33 deletions.
6 changes: 4 additions & 2 deletions fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ type fetcher struct {
}

func NewFetcher(ctx context.Context /*options ...FetcherOption*/) Fetcher {
var nworkers int
nworkers := 1

incoming := make(chan *FetchRequest)
for i := 0; i < nworkers; i++ {
go runFetchWorker(ctx, incoming)
}
return &fetcher{}
return &fetcher{
requests: incoming,
}
}

// Fetch requests that a HTTP request be made on behalf of the caller,
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ module github.com/lestrrat-go/httprc
go 1.17

require (
github.com/lestrrat-go/httpcc v1.0.0
github.com/lestrrat-go/option v1.0.0
github.com/stretchr/testify v1.7.1
)

require (
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
)
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/lestrrat-go/httpcc v1.0.0 h1:FszVC6cKfDvBKcJv646+lkh4GydQg2Z29scgUfkOpYc=
github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE=
github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4=
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down
12 changes: 10 additions & 2 deletions httprc.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,17 @@ type Cache struct {
// Cached(string) bool
}

func New(ctx context.Context) *Cache {
func New(ctx context.Context, options ...NewOption) *Cache {
refreshWindow := 15 * time.Minute
for _, option := range options {
//nolint:forcetypeassert
switch option.Ident() {
case identRefreshWindow{}:
refreshWindow = option.Value().(time.Duration)
}
}
fetch := NewFetcher(ctx)
queue := NewQueue(ctx, 5*time.Minute, fetch)
queue := NewQueue(ctx, refreshWindow, fetch)

return &Cache{
queue: queue,
Expand Down
65 changes: 65 additions & 0 deletions httprc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package httprc_test

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

"github.com/lestrrat-go/httprc"
"github.com/stretchr/testify/assert"
)

func TestCache(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

var called int
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
select {
case <-ctx.Done():
return
default:
}

t.Logf("HTTP handler")
called++
w.Header().Set(`Cache-Control`, fmt.Sprintf(`max-age=%d`, 3))
w.WriteHeader(http.StatusOK)
}))
c := httprc.New(ctx, httprc.WithRefreshWindow(time.Second))

c.Register(srv.URL, httprc.WithHTTPClient(srv.Client()), httprc.WithMinRefreshInterval(time.Second))
/*
if !assert.True(t, c.IsRegistered(srv.URL)) {
return
}
*/

for i := 0; i < 3; i++ {
_, err := c.Get(ctx, srv.URL)
if !assert.NoError(t, err, `c.Get should succeed`) {
return
}
}
if !assert.Equal(t, 1, called, `there should only be one fetch request`) {
return
}

time.Sleep(4 * time.Second)
for i := 0; i < 3; i++ {
_, err := c.Get(ctx, srv.URL)
if !assert.NoError(t, err, `c.Get should succeed`) {
return
}
}
if !assert.Equal(t, 2, called, `there should only be one fetch request`) {
return
}

cancel()

time.Sleep(5 * time.Second)
}
7 changes: 5 additions & 2 deletions options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ package_name: httprc
output: options_gen.go
interfaces:
- name: RegisterOption
- name: MemoryCacheOption
- name: NewOption
options:
- ident: HTTPClient
interface: RegisterOption
argument_type: HTTPClient
- ident: MinRefreshInterval
interface: RegisterOption
argument_type: time.Duration
- ident: RefreshInterval
interface: RegisterOption
argument_type: time.Duration
- ident: RefreshWindow
interface: MemoryCacheOption
interface: NewOption
argument_type: time.Duration
21 changes: 15 additions & 6 deletions options_gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ import (

type Option = option.Interface

type MemoryCacheOption interface {
type NewOption interface {
Option
memoryCacheOption()
newOption()
}

type memoryCacheOption struct {
type newOption struct {
Option
}

func (*memoryCacheOption) memoryCacheOption() {}
func (*newOption) newOption() {}

type RegisterOption interface {
Option
Expand All @@ -33,13 +33,18 @@ type registerOption struct {
func (*registerOption) registerOption() {}

type identHTTPClient struct{}
type identMinRefreshInterval struct{}
type identRefreshInterval struct{}
type identRefreshWindow struct{}

func (identHTTPClient) String() string {
return "WithHTTPClient"
}

func (identMinRefreshInterval) String() string {
return "WithMinRefreshInterval"
}

func (identRefreshInterval) String() string {
return "WithRefreshInterval"
}
Expand All @@ -52,10 +57,14 @@ func WithHTTPClient(v HTTPClient) RegisterOption {
return &registerOption{option.New(identHTTPClient{}, v)}
}

func WithMinRefreshInterval(v time.Duration) RegisterOption {
return &registerOption{option.New(identMinRefreshInterval{}, v)}
}

func WithRefreshInterval(v time.Duration) RegisterOption {
return &registerOption{option.New(identRefreshInterval{}, v)}
}

func WithRefreshWindow(v time.Duration) MemoryCacheOption {
return &memoryCacheOption{option.New(identRefreshWindow{}, v)}
func WithRefreshWindow(v time.Duration) NewOption {
return &newOption{option.New(identRefreshWindow{}, v)}
}
1 change: 1 addition & 0 deletions options_gen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

func TestOptionIdent(t *testing.T) {
require.Equal(t, "WithHTTPClient", identHTTPClient{}.String())
require.Equal(t, "WithMinRefreshInterval", identMinRefreshInterval{}.String())
require.Equal(t, "WithRefreshInterval", identRefreshInterval{}.String())
require.Equal(t, "WithRefreshWindow", identRefreshWindow{}.String())
}
Loading

0 comments on commit d23a7ba

Please sign in to comment.