Skip to content

Commit e78bf2c

Browse files
Thomas StrombergThomas Stromberg
authored andcommitted
cleanup the null cache impl
1 parent 7ad66e6 commit e78bf2c

File tree

7 files changed

+121
-185
lines changed

7 files changed

+121
-185
lines changed

cmd/prx/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"time"
1818

1919
"github.com/codeGROOVE-dev/prx/pkg/prx"
20+
"github.com/codeGROOVE-dev/sfcache/pkg/store/null"
2021
)
2122

2223
const (
@@ -78,7 +79,7 @@ func main() {
7879

7980
// Configure client options
8081
if *noCache {
81-
opts = append(opts, prx.WithNoCache())
82+
opts = append(opts, prx.WithCacheStore(null.New[string, prx.PullRequestData]()))
8283
}
8384

8485
client := prx.NewClient(token, opts...)

go.mod

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.25.4
44

55
require (
66
github.com/codeGROOVE-dev/retry v1.3.0
7-
github.com/codeGROOVE-dev/sfcache v1.3.0
8-
github.com/codeGROOVE-dev/sfcache/pkg/persist/localfs v1.3.0
7+
github.com/codeGROOVE-dev/sfcache v1.4.0
98
)
9+
10+
require github.com/codeGROOVE-dev/sfcache/pkg/store/localfs v1.4.0

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
github.com/codeGROOVE-dev/retry v1.3.0 h1:/+ipAWRJLL6y1R1vprYo0FSjSBvH6fE5j9LKXjpD54g=
22
github.com/codeGROOVE-dev/retry v1.3.0/go.mod h1:8OgefgV1XP7lzX2PdKlCXILsYKuz6b4ZpHa/20iLi8E=
3-
github.com/codeGROOVE-dev/sfcache v1.3.0 h1:Ew900GWXkZhMEU560kz0Nk1HvhGshiqaIASbTH+ihHg=
4-
github.com/codeGROOVE-dev/sfcache v1.3.0/go.mod h1:ksV5Y1RwKmOPZZiV0zXpsBOENGUCgO0fVgr/P8f/DJM=
5-
github.com/codeGROOVE-dev/sfcache/pkg/persist/localfs v1.3.0 h1:7zKbd7aHVzmbK2eEbdsf6Dknrte/o8+7I6GkNob8bGA=
6-
github.com/codeGROOVE-dev/sfcache/pkg/persist/localfs v1.3.0/go.mod h1:vHDjjehmi+yjXD+DXVG0rnc4iOBsiIknLThqpkYwA/c=
3+
github.com/codeGROOVE-dev/sfcache v1.4.0 h1:F00PqIYuenn/t2uK72MJ2zUCrrhW8WC5xaV+C16VNE4=
4+
github.com/codeGROOVE-dev/sfcache v1.4.0/go.mod h1:ksV5Y1RwKmOPZZiV0zXpsBOENGUCgO0fVgr/P8f/DJM=
5+
github.com/codeGROOVE-dev/sfcache/pkg/store/localfs v1.4.0 h1:oyHwsawHd9kUFdAuXSCKYiEQTXuHAVd4y7cdBatjsLY=
6+
github.com/codeGROOVE-dev/sfcache/pkg/store/localfs v1.4.0/go.mod h1:D/Y1sYT1m3VXHZRkQjHjFwtKQOsb587QZP/GtfJEDSE=

pkg/prx/cache.go

Lines changed: 24 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
package prx
22

33
import (
4-
"context"
54
"crypto/sha256"
65
"encoding/hex"
76
"errors"
87
"fmt"
9-
"log/slog"
108
"os"
119
"path/filepath"
1210
"strconv"
1311
"strings"
1412
"time"
1513

16-
"github.com/codeGROOVE-dev/sfcache"
17-
"github.com/codeGROOVE-dev/sfcache/pkg/persist/localfs"
14+
"github.com/codeGROOVE-dev/sfcache/pkg/store/localfs"
1815
)
1916

2017
const (
@@ -24,51 +21,6 @@ const (
2421
collaboratorsCacheTTL = 4 * time.Hour
2522
)
2623

27-
// prxCache provides tiered caching with disk persistence using sfcache.
28-
type prxCache struct {
29-
pr *sfcache.TieredCache[string, PullRequestData]
30-
logger *slog.Logger
31-
}
32-
33-
// newCache creates a new cache with disk persistence at the given directory.
34-
func newCache(cacheDir string, logger *slog.Logger) (*prxCache, error) {
35-
if logger == nil {
36-
logger = slog.Default()
37-
}
38-
39-
cleanPath := filepath.Clean(cacheDir)
40-
if !filepath.IsAbs(cleanPath) {
41-
return nil, errors.New("cache directory must be absolute path")
42-
}
43-
44-
if err := os.MkdirAll(cleanPath, 0o700); err != nil {
45-
return nil, fmt.Errorf("creating cache directory: %w", err)
46-
}
47-
48-
prStore, err := localfs.New[string, PullRequestData]("prx-pr", cleanPath)
49-
if err != nil {
50-
return nil, fmt.Errorf("creating PR cache store: %w", err)
51-
}
52-
53-
prCache, err := sfcache.NewTiered(prStore, sfcache.TTL(prCacheTTL))
54-
if err != nil {
55-
return nil, fmt.Errorf("creating PR cache: %w", err)
56-
}
57-
58-
return &prxCache{
59-
pr: prCache,
60-
logger: logger,
61-
}, nil
62-
}
63-
64-
// close releases cache resources.
65-
func (c *prxCache) close() error {
66-
if c.pr != nil {
67-
return c.pr.Close()
68-
}
69-
return nil
70-
}
71-
7224
// prCacheKey generates a cache key for PR data.
7325
func prCacheKey(owner, repo string, prNumber int) string {
7426
key := strings.Join([]string{"graphql", "pr_graphql", owner, repo, strconv.Itoa(prNumber)}, "/")
@@ -81,108 +33,34 @@ func collaboratorsCacheKey(owner, repo string) string {
8133
return fmt.Sprintf("%s/%s", owner, repo)
8234
}
8335

84-
// CacheClient wraps the regular Client and adds disk-based caching.
85-
type CacheClient struct {
86-
*Client
87-
88-
cache *prxCache
89-
}
90-
91-
// NewCacheClient creates a new caching client with the given cache directory.
92-
func NewCacheClient(token string, cacheDir string, opts ...Option) (*CacheClient, error) {
93-
// Create a temporary logger to use during cache creation
94-
logger := slog.Default()
95-
96-
cache, err := newCache(cacheDir, logger)
36+
// CacheClient is an alias for Client, kept for backward compatibility.
37+
//
38+
// Deprecated: Use NewClient with WithCacheStore instead.
39+
type CacheClient = Client
40+
41+
// NewCacheClient creates a client with a specific cache directory.
42+
//
43+
// Deprecated: Use NewClient with WithCacheStore instead.
44+
func NewCacheClient(token, dir string, opts ...Option) (*Client, error) {
45+
dir = filepath.Clean(dir)
46+
if !filepath.IsAbs(dir) {
47+
return nil, errors.New("cache directory must be absolute path")
48+
}
49+
if err := os.MkdirAll(dir, 0o700); err != nil {
50+
return nil, fmt.Errorf("creating cache directory: %w", err)
51+
}
52+
store, err := localfs.New[string, PullRequestData]("prx-pr", dir)
9753
if err != nil {
98-
return nil, err
54+
return nil, fmt.Errorf("creating PR cache store: %w", err)
9955
}
100-
101-
// Create client with no cache since CacheClient handles caching
102-
opts = append(opts, WithNoCache())
103-
client := NewClient(token, opts...)
104-
105-
// Update logger to the one from client options
106-
cache.logger = client.logger
107-
108-
return &CacheClient{
109-
Client: client,
110-
cache: cache,
111-
}, nil
56+
opts = append(opts, WithCacheStore(store))
57+
return NewClient(token, opts...), nil
11258
}
11359

11460
// Close releases cache resources.
115-
func (c *CacheClient) Close() error {
116-
if c.cache != nil {
117-
return c.cache.close()
61+
func (c *Client) Close() error {
62+
if c.prCache != nil {
63+
return c.prCache.Close()
11864
}
11965
return nil
12066
}
121-
122-
// PullRequest fetches a pull request with all its events and metadata, with caching support.
123-
func (c *CacheClient) PullRequest(ctx context.Context, owner, repo string, prNumber int, referenceTime time.Time) (*PullRequestData, error) {
124-
return c.PullRequestWithReferenceTime(ctx, owner, repo, prNumber, referenceTime)
125-
}
126-
127-
// PullRequestWithReferenceTime fetches PR data using GetSet for thundering herd protection.
128-
func (c *CacheClient) PullRequestWithReferenceTime(
129-
ctx context.Context, owner, repo string, prNumber int, referenceTime time.Time,
130-
) (*PullRequestData, error) {
131-
if c.cache == nil || c.cache.pr == nil {
132-
return c.pullRequestViaGraphQL(ctx, owner, repo, prNumber)
133-
}
134-
135-
cacheKey := prCacheKey(owner, repo, prNumber)
136-
137-
// Try to get from cache first with time validation
138-
cached, found, err := c.cache.pr.Get(ctx, cacheKey)
139-
if err != nil {
140-
c.logger.WarnContext(ctx, "cache get error",
141-
"owner", owner,
142-
"repo", repo,
143-
"pr", prNumber,
144-
"error", err)
145-
}
146-
if found {
147-
// Check if cache entry is fresh enough (cached after reference time)
148-
// Note: sfcache handles TTL expiration; we check freshness against referenceTime
149-
if cached.CachedAt.After(referenceTime) || cached.CachedAt.Equal(referenceTime) {
150-
c.logger.InfoContext(ctx, "cache hit: GraphQL pull request",
151-
"owner", owner,
152-
"repo", repo,
153-
"pr", prNumber,
154-
"cached_at", cached.CachedAt)
155-
return &cached, nil
156-
}
157-
c.logger.InfoContext(ctx, "cache miss: GraphQL pull request expired",
158-
"owner", owner,
159-
"repo", repo,
160-
"pr", prNumber,
161-
"cached_at", cached.CachedAt,
162-
"reference_time", referenceTime)
163-
// Delete stale entry so GetSet will fetch fresh data
164-
if delErr := c.cache.pr.Delete(ctx, cacheKey); delErr != nil {
165-
c.logger.WarnContext(ctx, "failed to delete stale cache entry", "error", delErr)
166-
}
167-
} else {
168-
c.logger.InfoContext(ctx, "cache miss: GraphQL pull request not in cache",
169-
"owner", owner,
170-
"repo", repo,
171-
"pr", prNumber)
172-
}
173-
174-
// Fetch from API using GetSet for thundering herd protection
175-
result, err := c.cache.pr.GetSet(ctx, cacheKey, func(ctx context.Context) (PullRequestData, error) {
176-
prData, err := c.pullRequestViaGraphQL(ctx, owner, repo, prNumber)
177-
if err != nil {
178-
return PullRequestData{}, err
179-
}
180-
prData.CachedAt = time.Now()
181-
return *prData, nil
182-
})
183-
if err != nil {
184-
return nil, err
185-
}
186-
187-
return &result, nil
188-
}

pkg/prx/cache_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ func TestCacheClient(t *testing.T) {
148148

149149
// First request - should hit the API
150150
beforeFirstRequest := requestCount
151-
events1, err := client.PullRequest(ctx, "test", "repo", 1, time.Now().Add(-2*time.Hour))
151+
events1, err := client.PullRequestWithReferenceTime(ctx, "test", "repo", 1, time.Now().Add(-2*time.Hour))
152152
if err != nil {
153153
t.Fatalf("First request failed: %v", err)
154154
}
@@ -164,7 +164,7 @@ func TestCacheClient(t *testing.T) {
164164

165165
// Second request with same reference time - should use cache for most endpoints
166166
beforeSecondRequest := requestCount
167-
events2, err := client.PullRequest(ctx, "test", "repo", 1, time.Now().Add(-2*time.Hour))
167+
events2, err := client.PullRequestWithReferenceTime(ctx, "test", "repo", 1, time.Now().Add(-2*time.Hour))
168168
if err != nil {
169169
t.Fatalf("Second request failed: %v", err)
170170
}
@@ -181,7 +181,7 @@ func TestCacheClient(t *testing.T) {
181181

182182
// Third request with future reference time - should hit API again
183183
beforeThirdRequest := requestCount
184-
_, err = client.PullRequest(ctx, "test", "repo", 1, time.Now().Add(1*time.Hour))
184+
_, err = client.PullRequestWithReferenceTime(ctx, "test", "repo", 1, time.Now().Add(1*time.Hour))
185185
if err != nil {
186186
t.Fatalf("Third request failed: %v", err)
187187
}

0 commit comments

Comments
 (0)