Skip to content

Commit

Permalink
Merge pull request #1269 from tmiddlet2666/coherence
Browse files Browse the repository at this point in the history
Update Coherence driver to add near cache option
  • Loading branch information
ReneWerner87 authored Mar 10, 2024
2 parents f4d9f05 + 1761a19 commit f3a26d3
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 17 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/test-coherence.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,17 @@ jobs:
- 1.19.x
- 1.20.x
- 1.21.x
- 1.22.x
steps:
- name: Fetch Repository
uses: actions/checkout@v4
- name: Startup Coherence
run: |
docker run -d -p 1408:1408 -p 30000:30000 ghcr.io/oracle/coherence-ce:22.06.5
docker run -d -p 1408:1408 -p 30000:30000 ghcr.io/oracle/coherence-ce:23.09.2
sleep 30
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '${{ matrix.go-version }}'
- name: Run Test
run: cd ./coherence && go clean -testcache && go test ./... -v
run: cd ./coherence && COHERENCE_SESSION_DEBUG=true go clean -testcache && go test ./... -v -race
40 changes: 36 additions & 4 deletions coherence/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ necessary for the client to operate correctly.
To start a Coherence cluster using Docker, issue the following:

```bash
docker run -d -p 1408:1408 ghcr.io/oracle/coherence-ce:22.06.5
docker run -d -p 1408:1408 ghcr.io/oracle/coherence-ce:22.06.7
```

See the documentation [here](https://pkg.go.dev/github.com/oracle/coherence-go-client/coherence#hdr-Obtaining_a_Session) on connection options
Expand All @@ -52,9 +52,10 @@ You can use the following possibilities to create a storage:
// Initialize default config, to connect to localhost:1408 using plain text
store, err := coherence.New()

// Initialize custom config to connect to a different host/port and use plaint ext.
// Initialize custom config to connect to a different host/port and use plain text and expiry of 5 minutes.
store, err := coherence.New(coherence.Config{
Address: "my-host:myport",
Expiration: time.Duration(300) * time.Second, // 5 minutes
})

// Initialize to connect with TLS enabled with your own tls.Config
Expand All @@ -66,13 +67,38 @@ store, err := coherence.New(coherence.Config{
})
```

> Note: If you create two stores using `coherence.New()` they will effectivity be idential.
> Note: If you create two stores using `coherence.New()` they will effectivity be identical.
> If you wish to have two separate stores, then you can use:
> ```go
> store1, err := coherence.New(Config{ScopeName: "scope1"})
> store2, err := coherence.New(Config{ScopeName: "scope2"})
> ```
**Near Caches**
The latest version of the Coherence Go client introduces near cache support
to cache frequently accessed data in the Go client to avoid sending requests across the network.
This is particularly useful if you are using sticky sessions via a LBR as this will cache
the session in the Go process and the `Get()` operations will be much quicker.
When the session is expired on the server it will automatically be removed from the near cache.
To enable this for you session, you can set the `NearCacheTimeout` to a duration less than the expiry.
```go
// Initialize default config, to connect to localhost:1408 using plain text
store, err := coherence.New()
// Use plain text with default expiry of 5 minutes, and a near cache expiry of 2 minutes
store, err := coherence.New(coherence.Config{
Address: "my-host:myport",
Expiration: time.Duration(300) * time.Second, // 5 minutes
NearCacheTimeout: time.Duration(120) * time.Second, // 2 minutes
})
```
> Note: You must ensure your near cache timeout is less that the session timeout.
### Config

```go
Expand All @@ -92,15 +118,21 @@ type Config struct {

// TLSConfig specifies tls.Config to use when connecting, if nil then plain text is used
TLSConfig *tls.Config

// NearCacheTimeout defines the timeout for a near cache. Is this is set, then a near cache
// with the timeout is created. Note: this must be less than the session timeout or any timeout you specify
// when using Set().
NearCacheTimeout time.Duration
}
```

### Default Config
```go
var DefaultConfig = Config{
Address: "localhost:1408",
Timeout: time.Duration(30) * time.Millisecond,
Timeout: time.Duration(120) * time.Seconds,
ScopeName: defaultScopeName,
Reset: false,
NearCacheTimeout: time.Duration(60) * time.Seconds,
}
```
39 changes: 31 additions & 8 deletions coherence/coherence.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package coherence

/*
* Copyright © 2023, Oracle and/or its affiliates.
* Copyright © 2023, 2024 Oracle and/or its affiliates.
*/
import (
"context"
"crypto/tls"
"fmt"
coh "github.com/oracle/coherence-go-client/coherence"
"time"
)
Expand Down Expand Up @@ -39,6 +40,11 @@ type Config struct {

// TLSConfig specifies tls.Config to use when connecting, if nil then plain text is used
TLSConfig *tls.Config

// NearCacheTimeout defines the timeout for a near cache. Is this is set, then a near cache
// with the timeout is created. Note: this must be less than the session timeout or any timeout you specify
// when using Set().
NearCacheTimeout time.Duration
}

// DefaultConfig defines default options.
Expand All @@ -51,9 +57,10 @@ var DefaultConfig = Config{

// New returns a new [Storage] given a [Config].
func New(config ...Config) (*Storage, error) {
cfg := setupConfig(config...)

options := make([]func(session *coh.SessionOptions), 0)
var (
cfg = setupConfig(config...)
options = make([]func(session *coh.SessionOptions), 0)
)

// apply any config values as Coherence options
options = append(options, coh.WithAddress(cfg.Address))
Expand All @@ -66,13 +73,21 @@ func New(config ...Config) (*Storage, error) {

options = append(options, coh.WithRequestTimeout(cfg.Timeout))

// validate near cache options
if cfg.NearCacheTimeout != 0 {
if cfg.NearCacheTimeout > cfg.Timeout {
return nil, fmt.Errorf("you cannot set the near cache timeout (%v) to less than session timeout (%v)",
cfg.NearCacheTimeout, cfg.Timeout)
}
}

// create the Coherence session
session, err := coh.NewSession(context.Background(), options...)
if err != nil {
return nil, err
}

store, err := newCoherenceStorage(session, cfg.ScopeName)
store, err := newCoherenceStorage(session, cfg.ScopeName, cfg.NearCacheTimeout)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -109,8 +124,16 @@ func setupConfig(config ...Config) Config {
}

// newCoherenceStorage returns a new Coherence [Storage].
func newCoherenceStorage(session *coh.Session, cacheName string) (*Storage, error) {
nc, err := coh.GetNamedCache[string, []byte](session, "fiber$"+cacheName)
func newCoherenceStorage(session *coh.Session, cacheName string, nearCacheTimeout time.Duration) (*Storage, error) {
cacheOptions := make([]func(cache *coh.CacheOptions), 0)

// configure a near cache if the nearCacheTimeout is set
if nearCacheTimeout != 0 {
nearCacheOptions := coh.NearCacheOptions{TTL: nearCacheTimeout}
cacheOptions = append(cacheOptions, coh.WithNearCache(&nearCacheOptions))
}

nc, err := coh.GetNamedCache[string, []byte](session, "fiber$"+cacheName, cacheOptions...)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -143,7 +166,7 @@ func (s *Storage) Delete(key string) error {
}

func (s *Storage) Reset() error {
return s.namedCache.Clear(s.ctx)
return s.namedCache.Truncate(s.ctx)
}

func (s *Storage) Close() error {
Expand Down
6 changes: 3 additions & 3 deletions coherence/coherence_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package coherence

/*
* Copyright © 2023, Oracle and/or its affiliates.
* Copyright © 2023, 2024 Oracle and/or its affiliates.
*/
import (
"github.com/stretchr/testify/require"
Expand All @@ -22,7 +22,8 @@ var testStore *Storage

func TestMain(m *testing.M) {
testStore, _ = New(Config{
Reset: true,
Reset: true,
NearCacheTimeout: time.Duration(4) * time.Second,
})

code := m.Run()
Expand Down Expand Up @@ -102,7 +103,6 @@ func Test_Coherence_Set_With_Expiry(t *testing.T) {
val, err = testStore.Get(key1)
require.NoError(t, err)
require.True(t, len(val) == 0)

}

func Test_Coherence_Get_Missing(t *testing.T) {
Expand Down

0 comments on commit f3a26d3

Please sign in to comment.