Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move session store to storage.SessionDatabase #2475

Merged
merged 2 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions network/dag/consistency_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ import (
)

func TestXorTreeRepair(t *testing.T) {
t.Cleanup(func() {
goleak.VerifyNone(t)
})
defer goleak.VerifyNone(t, goleak.IgnoreCurrent())

tx, _, _ := CreateTestTransaction(1)
t.Run("xor tree repaired after 2 signals", func(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion network/transport/grpc/connection_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ func Test_grpcConnectionManager_hasActiveConnection(t *testing.T) {

func Test_grpcConnectionManager_dialerLoop(t *testing.T) {
// make sure connectLoop only returns after all of its goroutines are closed
defer goleak.VerifyNone(t)
defer goleak.VerifyNone(t, goleak.IgnoreCurrent())

targetAddress := "bootstrap"
var capturedAddress string
Expand Down
2 changes: 1 addition & 1 deletion network/transport/v2/gossip/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func TestManager_PeerDisconnected(t *testing.T) {

t.Run("stops ticker", func(t *testing.T) {
// Use uber/goleak to assert the goroutine started by PeerConnected is stopped when PeerDisconnected is called
defer goleak.VerifyNone(t)
defer goleak.VerifyNone(t, goleak.IgnoreCurrent())

gMan := giveMeAgMan(t)
gMan.interval = time.Millisecond
Expand Down
2 changes: 1 addition & 1 deletion network/transport/v2/protocol_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func TestProtocol_Start(t *testing.T) {

func TestProtocol_Stop(t *testing.T) {
t.Run("waits until goroutines have finished", func(t *testing.T) {
defer goleak.VerifyNone(t)
defer goleak.VerifyNone(t, goleak.IgnoreCurrent())

// Use waitgroup to make sure the goroutine that blocks has started
wg := &sync.WaitGroup{}
Expand Down
4 changes: 1 addition & 3 deletions network/transport/v2/transactionlist_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,7 @@ import (
)

func TestTransactionListHandler(t *testing.T) {
t.Cleanup(func() {
goleak.VerifyNone(t)
})
defer goleak.VerifyNone(t, goleak.IgnoreCurrent())

t.Run("fn is called", func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
Expand Down
2 changes: 1 addition & 1 deletion pki/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ var crlPathMap = map[string]string{
}

func TestValidator_Start(t *testing.T) {
defer goleak.VerifyNone(t)
defer goleak.VerifyNone(t, goleak.IgnoreCurrent())
store, err := core.LoadTrustStore(truststorePKIo)
require.NoError(t, err)
ctx, cancel := context.WithCancel(context.Background())
Expand Down
25 changes: 18 additions & 7 deletions storage/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,19 @@ const storeShutdownTimeout = 5 * time.Second
// New creates a new instance of the storage engine.
func New() Engine {
return &engine{
storesMux: &sync.Mutex{},
stores: map[string]stoabs.Store{},
storesMux: &sync.Mutex{},
stores: map[string]stoabs.Store{},
sessionDatabase: NewInMemorySessionDatabase(),
}
}

type engine struct {
datadir string
storesMux *sync.Mutex
stores map[string]stoabs.Store
databases []database
config Config
datadir string
storesMux *sync.Mutex
stores map[string]stoabs.Store
databases []database
sessionDatabase SessionDatabase
config Config
}

func (e *engine) Config() interface{} {
Expand Down Expand Up @@ -84,9 +86,13 @@ func (e engine) Shutdown() error {
failures = true
}
}

if failures {
return errors.New("one or more stores failed to close")
}

e.sessionDatabase.close()

return nil
}

Expand All @@ -108,6 +114,7 @@ func (e *engine) Configure(config core.ServerConfig) error {
return fmt.Errorf("unable to configure BBolt database: %w", err)
}
e.databases = append(e.databases, bboltDB)

return nil
}

Expand All @@ -118,6 +125,10 @@ func (e *engine) GetProvider(moduleName string) Provider {
}
}

func (e *engine) GetSessionDatabase() SessionDatabase {
return e.sessionDatabase
}

type provider struct {
moduleName string
engine *engine
Expand Down
32 changes: 32 additions & 0 deletions storage/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package storage

import (
"errors"
"github.com/nuts-foundation/go-stoabs"
"github.com/nuts-foundation/nuts-node/core"
"time"
Expand All @@ -34,6 +35,8 @@ type Engine interface {

// GetProvider returns the Provider for the given module.
GetProvider(moduleName string) Provider
// GetSessionDatabase returns the SessionDatabase
GetSessionDatabase() SessionDatabase
}

// Provider lets callers get access to stores.
Expand All @@ -59,3 +62,32 @@ type database interface {
getClass() Class
close()
}

var ErrNotFound = errors.New("not found")

// SessionDatabase is a non-persistent database that holds session data on a KV basis.
// Keys could be access tokens, nonce's, authorization codes, etc.
// All entries are stored with a TTL, so they will be removed automatically.
type SessionDatabase interface {
// GetStore returns a SessionStore with the given keys as key prefixes.
// The keys are used to logically partition the store, eg: tenants and/or flows that are not allowed to overlap like credential issuance and verification.
// The TTL is the time-to-live for the entries in the store.
GetStore(ttl time.Duration, keys ...string) SessionStore
woutslakhorst marked this conversation as resolved.
Show resolved Hide resolved
// close stops any background processes and closes the database.
close()
}

// SessionStore is a key-value store that holds session data.
// The SessionStore is an abstraction for underlying storage, it automatically adds prefixes for logical partitions.
type SessionStore interface {
Copy link
Member

@gerardsn gerardsn Sep 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should include ctx on all methods if there is going to be a version that is not in memory

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That could be done when an implementation is added that supports it. Until then this would add unused parameters.

// Delete deletes the entry for the given key.
// It does not return an error if the key does not exist.
Delete(key string) error
// Exists returns true if the key exists.
Exists(key string) bool
// Get returns the value for the given key.
// Returns ErrNotFound if the key does not exist.
Get(key string, target interface{}) error
// Put stores the given value for the given key.
Put(key string, value interface{}) error
}
148 changes: 148 additions & 0 deletions storage/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading