Skip to content

Commit

Permalink
Cache doc and code improvement (#588)
Browse files Browse the repository at this point in the history
<!--
Thanks for taking precious time for making a PR.

Before creating a pull request, please make sure:
- Your PR solves one problem for which an issue exist and a solution has
been discussed
- You have read the guide for contributing
- See
https://github.com/beatlabs/patron/blob/master/README.md#how-to-contribute
- You signed all your commits (otherwise we won't be able to merge the
PR)
  - See https://github.com/beatlabs/patron/blob/master/SIGNYOURWORK.md
- You added unit tests for the new functionality
- You mention in the PR description which issue it is addressing, e.g.
"Resolves #123"
-->

## Which problem is this PR solving?

Closes #555 and improves the API of the cache abstractions. This is a
BREAKING CHANGE.

## Short description of the changes

- Introduced context to the cache methods
- Improved Go documentation

Co-authored-by: Dionysis Xenos <[email protected]>
  • Loading branch information
Sotirios Mantziaris and xenosdio authored Dec 1, 2022
1 parent a43c395 commit 2318350
Show file tree
Hide file tree
Showing 13 changed files with 135 additions and 138 deletions.
62 changes: 37 additions & 25 deletions BREAKING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Breaking Changes Migration Guide

## v.0.74.0
## v0.75.0

The `cache` package has introduced the `context.Context` as the first argument in each method and removed it from the constructors.

## v0.74.0

### Instantiation of patron service

Expand All @@ -13,6 +17,7 @@ Types, github.com/beatlabs/patron.Builder and github.com/beatlabs/patron.Option
#### Creating a patron instance with components

##### v0.73.0 and before

```go
svc, err := patron.New(name, version)
if err != nil {
Expand All @@ -27,6 +32,7 @@ if err != nil {
```

##### v0.74.0

```go
svc, err := patron.New(name, version, patron.WithComponents(amqp,grpc))
if err != nil {
Expand All @@ -40,9 +46,11 @@ if err != nil {
}

```

#### Creating a patron instance with SIGHUP handler option

##### v0.73.0 and before

```go
svc, err := patron.New(name, version)
if err != nil {
Expand All @@ -57,6 +65,7 @@ if err != nil {
```

##### v0.74.0

```go
svc, err := patron.New(name, version, patron.WithSIGHUP(sighup))
if err != nil {
Expand All @@ -74,6 +83,7 @@ if err != nil {
#### Creating a patron instance with a custom HTTP Router

##### v0.73.0 and before

```go
svc, err := patron.New(name, version)
if err != nil {
Expand All @@ -88,6 +98,7 @@ if err != nil {
```

##### v0.74.0

```go
svc, err := patron.New(name, version, patron.WithRouter(router))
if err != nil {
Expand All @@ -108,47 +119,49 @@ The instantiation and initialisation of the GRPC component has been moved from `
The configuration parameters used for the builder in previous versions can now be passed as Options to the component constructor.

##### v0.73.0 and before

```go
package main

import (
patrongrpc "github.com/beatlabs/patron/component/grpc"
"google.golang.org/grpc"
"log"
"time"
patrongrpc "github.com/beatlabs/patron/component/grpc"
"google.golang.org/grpc"
"log"
"time"
)

func main(){
port := 5000
builder,err := grpc.WithOptions(grpc.ConnectionTimeout(1*time.Second)).WithReflection().New(port)
if err != nil{
log.Fatalf("failed to create new grpc builder due: %s",err)
}
port := 5000
builder,err := grpc.WithOptions(grpc.ConnectionTimeout(1*time.Second)).WithReflection().New(port)
if err != nil{
log.Fatalf("failed to create new grpc builder due: %s",err)
}

comp,err := builder.Create()
if err != nil{
log.Fatalf("failed to create grpc component due: %s",err)
}
comp,err := builder.Create()
if err != nil{
log.Fatalf("failed to create grpc component due: %s",err)
}
}
```

##### v0.74.0

```go
package main

import (
patrongrpc "github.com/beatlabs/patron/component/grpc"
"log"
"google.golang.org/grpc"
"time"
patrongrpc "github.com/beatlabs/patron/component/grpc"
"log"
"google.golang.org/grpc"
"time"
)

func main(){
port := 5000
comp,err := patrongrpc.New(port, patrongrpc.WithServerOptions(grpc.ConnectionTimeout(1*time.Second)),patrongrpc.WithReflection())
if err != nil{
log.Fatalf("failed to create new grpc component due: %s",err)
}
port := 5000
comp,err := patrongrpc.New(port, patrongrpc.WithServerOptions(grpc.ConnectionTimeout(1*time.Second)),patrongrpc.WithReflection())
if err != nil{
log.Fatalf("failed to create new grpc component due: %s",err)
}
}
```

Expand All @@ -168,7 +181,6 @@ considering package `github.com/beatlabs/patron/client/ampq/v2`

option function `func Config(cfg amqp.Config) OptionFunc` is renamed to `func Config(cfg amqp.Config) OptionFunc`


## v0.73.0

### Migrating from `aws-sdk-go` v1 to v2
Expand Down Expand Up @@ -241,4 +253,4 @@ func createSQSAPI(endpoint string) (*sqs.Client, error) {
}
```
> A more detailed documentation on migrating can be found [here](https://aws.github.io/aws-sdk-go-v2/docs/migrating).
> A more detailed documentation on migrating can be found [here](https://aws.github.io/aws-sdk-go-v2/docs/migrating).
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ The entry point of the framework is the `Service`. The `Service` uses `Component
- [Observability](docs/observability/Observability.md)
- [Logging](docs/observability/Logging.md)
- [Distributed Tracing](docs/observability/DistributedTracing.md)
- [Caching](docs/other/Caching.md)
- [Encoding](docs/other/Encoding.md)
- [Errors](docs/other/Errors.md)
- [Examples](docs/Examples.md)
Expand Down
22 changes: 14 additions & 8 deletions cache/cache.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
// Package cache provide abstractions for concrete cache implementations.
// Package cache provides abstractions to allow the creation of concrete implementations.
package cache

import (
"context"
"time"
)

// Cache interface.
// Cache interface that defines the methods required.
type Cache interface {
Get(key string) (interface{}, bool, error)
Purge() error
Remove(key string) error
Set(key string, value interface{}) error
// Get a value based on a specific key. The call returns whether the key exists or not.
Get(ctx context.Context, key string) (interface{}, bool, error)
// Purge the cache.
Purge(ctx context.Context) error
// Remove the key from the cache.
Remove(ctx context.Context, key string) error
// Set the value for the specified key.
Set(ctx context.Context, key string, value interface{}) error
}

// TTLCache interface adds support for expiring key-value pairs.
// TTLCache interface adds support for expiring key value pairs.
type TTLCache interface {
Cache
SetTTL(key string, value interface{}, ttl time.Duration) error
// SetTTL sets the value of a specified key with a time to live.
SetTTL(ctx context.Context, key string, value interface{}, ttl time.Duration) error
}
18 changes: 11 additions & 7 deletions cache/lru/lru.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
// Package lru is the concrete implementation of the cache abstraction.
// Package lru implements a LRU based cache.
package lru

import (
"context"

"github.com/beatlabs/patron/cache"
lru "github.com/hashicorp/golang-lru"
)

// Cache encapsulates a thread-safe fixed size LRU cache
// as defined in hashicorp/golang-lru.
var _ cache.Cache = &Cache{}

// Cache encapsulates a thread-safe fixed size LRU cache.
type Cache struct {
cache *lru.Cache
}
Expand All @@ -21,25 +25,25 @@ func New(size int) (*Cache, error) {
}

// Get executes a lookup and returns whether a key exists in the cache along with its value.
func (c *Cache) Get(key string) (interface{}, bool, error) {
func (c *Cache) Get(_ context.Context, key string) (interface{}, bool, error) {
value, ok := c.cache.Get(key)
return value, ok, nil
}

// Purge evicts all keys present in the cache.
func (c *Cache) Purge() error {
func (c *Cache) Purge(_ context.Context) error {
c.cache.Purge()
return nil
}

// Remove evicts a specific key from the cache.
func (c *Cache) Remove(key string) error {
func (c *Cache) Remove(_ context.Context, key string) error {
c.cache.Remove(key)
return nil
}

// Set registers a key-value pair to the cache.
func (c *Cache) Set(key string, value interface{}) error {
func (c *Cache) Set(_ context.Context, key string, value interface{}) error {
c.cache.Add(key, value)
return nil
}
20 changes: 11 additions & 9 deletions cache/lru/lru_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package lru

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -38,42 +39,43 @@ func TestCacheOperations(t *testing.T) {
assert.NoError(t, err)

k, v := "foo", "bar"
ctx := context.Background()

t.Run("testGetEmpty", func(t *testing.T) {
res, ok, err := c.Get(k)
res, ok, err := c.Get(ctx, k)
assert.Nil(t, res)
assert.False(t, ok)
assert.NoError(t, err)
})

t.Run("testSetGet", func(t *testing.T) {
err = c.Set(k, v)
err = c.Set(ctx, k, v)
assert.NoError(t, err)
res, ok, err := c.Get(k)
res, ok, err := c.Get(ctx, k)
assert.Equal(t, v, res)
assert.True(t, ok)
assert.NoError(t, err)
})

t.Run("testRemove", func(t *testing.T) {
err = c.Remove(k)
err = c.Remove(ctx, k)
assert.NoError(t, err)
res, ok, err := c.Get(k)
res, ok, err := c.Get(ctx, k)
assert.Nil(t, res)
assert.False(t, ok)
assert.NoError(t, err)
})

t.Run("testPurge", func(t *testing.T) {
err = c.Set("key1", "val1")
err = c.Set(ctx, "key1", "val1")
assert.NoError(t, err)
err = c.Set("key2", "val2")
err = c.Set(ctx, "key2", "val2")
assert.NoError(t, err)
err = c.Set("key3", "val3")
err = c.Set(ctx, "key3", "val3")
assert.NoError(t, err)

assert.Equal(t, c.cache.Len(), 3)
err = c.Purge()
err = c.Purge(ctx)
assert.NoError(t, err)
assert.Equal(t, c.cache.Len(), 0)
})
Expand Down
32 changes: 17 additions & 15 deletions cache/redis/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const (
)

func TestCache(t *testing.T) {
cache, err := New(context.Background(), Options{
cache, err := New(Options{
Addr: dsn,
Password: "", // no password set
DB: 0, // use default DB
Expand All @@ -31,49 +31,51 @@ func TestCache(t *testing.T) {
key3 := "key3"
val3 := "value3"

ctx := context.Background()

t.Run("set", func(t *testing.T) {
assert.NoError(t, cache.Set(key1, val1))
assert.NoError(t, cache.Set(ctx, key1, val1))
})

t.Run("get", func(t *testing.T) {
got, exists, err := cache.Get(key1)
got, exists, err := cache.Get(ctx, key1)
assert.NoError(t, err)
assert.True(t, exists)
assert.Equal(t, val1, got)
})

t.Run("delete", func(t *testing.T) {
assert.NoError(t, cache.Remove(key1))
_, exists, err := cache.Get(key1)
assert.NoError(t, cache.Remove(ctx, key1))
_, exists, err := cache.Get(ctx, key1)
assert.NoError(t, err)
assert.False(t, exists)
})

t.Run("ttl", func(t *testing.T) {
assert.NoError(t, cache.SetTTL(key1, val1, 2*time.Millisecond))
got, exists, err := cache.Get(key1)
assert.NoError(t, cache.SetTTL(ctx, key1, val1, 2*time.Millisecond))
got, exists, err := cache.Get(ctx, key1)
assert.NoError(t, err)
assert.True(t, exists)
assert.Equal(t, val1, got)
time.Sleep(10 * time.Millisecond)
_, exists, err = cache.Get(key1)
_, exists, err = cache.Get(ctx, key1)
assert.NoError(t, err)
assert.False(t, exists)
})

t.Run("purge", func(t *testing.T) {
assert.NoError(t, cache.Set(key1, val1))
assert.NoError(t, cache.Set(key2, val2))
assert.NoError(t, cache.Set(key3, val3))
assert.NoError(t, cache.Set(ctx, key1, val1))
assert.NoError(t, cache.Set(ctx, key2, val2))
assert.NoError(t, cache.Set(ctx, key3, val3))

assert.NoError(t, cache.Purge())
_, exists, err := cache.Get(key1)
assert.NoError(t, cache.Purge(ctx))
_, exists, err := cache.Get(ctx, key1)
assert.NoError(t, err)
assert.False(t, exists)
_, exists, err = cache.Get(key2)
_, exists, err = cache.Get(ctx, key2)
assert.NoError(t, err)
assert.False(t, exists)
_, exists, err = cache.Get(key3)
_, exists, err = cache.Get(ctx, key3)
assert.NoError(t, err)
assert.False(t, exists)
})
Expand Down
Loading

0 comments on commit 2318350

Please sign in to comment.