diff --git a/go.mod b/go.mod index 32c9d8f17..5ed018ab7 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/IBM/mathlib v0.0.3-0.20231011094432-44ee0eb539da github.com/dgraph-io/badger/v3 v3.2103.2 github.com/hashicorp/go-uuid v1.0.2 - github.com/hyperledger-labs/fabric-smart-client v0.3.1-0.20240808130420-c90da8a1647a + github.com/hyperledger-labs/fabric-smart-client v0.3.1-0.20240812073223-219f2a84da8f github.com/hyperledger-labs/fabric-token-sdk/txgen v0.0.0-00010101000000-000000000000 github.com/hyperledger-labs/orion-sdk-go v0.2.10 github.com/hyperledger-labs/orion-server v0.2.10 diff --git a/go.sum b/go.sum index 3a82cfbf2..93a160102 100644 --- a/go.sum +++ b/go.sum @@ -467,8 +467,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY= github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/hyperledger-labs/fabric-smart-client v0.3.1-0.20240808130420-c90da8a1647a h1:eBVE/gOE4sSHmB+AjFSNAjn7jgi7p979NCfpNRtO1x0= -github.com/hyperledger-labs/fabric-smart-client v0.3.1-0.20240808130420-c90da8a1647a/go.mod h1:962enO5D++R5KW+rPA2FD85h619hap+4voLAU+Pk9WY= +github.com/hyperledger-labs/fabric-smart-client v0.3.1-0.20240812073223-219f2a84da8f h1:VcSMlP8EWx6mzSIeCTaIVpVtI/08lKoUa079aJ3dM2o= +github.com/hyperledger-labs/fabric-smart-client v0.3.1-0.20240812073223-219f2a84da8f/go.mod h1:962enO5D++R5KW+rPA2FD85h619hap+4voLAU+Pk9WY= github.com/hyperledger-labs/orion-sdk-go v0.2.10 h1:lFgWgxyvngIhWnIqymYGBmtmq9D6uC5d0uLG9cbyh5s= github.com/hyperledger-labs/orion-sdk-go v0.2.10/go.mod h1:iN2xZB964AqwVJwL+EnwPOs8z1EkMEbbIg/qYeC7gDY= github.com/hyperledger-labs/orion-server v0.2.10 h1:G4zbQEL5Egk0Oj+TwHCZWdTOLDBHOjaAEvYOT4G7ozw= diff --git a/token/services/config/config.go b/token/services/config/config.go index 8fae3efcf..93bd1c4b1 100644 --- a/token/services/config/config.go +++ b/token/services/config/config.go @@ -9,8 +9,8 @@ package config import ( "reflect" + "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/lazy" "github.com/hyperledger-labs/fabric-token-sdk/token/driver" - "github.com/hyperledger-labs/fabric-token-sdk/token/services/utils" "github.com/pkg/errors" ) @@ -82,7 +82,7 @@ type Service struct { version string enabled bool - tmsCache utils.LazyGetter[map[string]Configuration] + tmsCache lazy.Getter[map[string]Configuration] } // NewService creates a new Service configuration. @@ -97,7 +97,7 @@ func NewService(cp configProvider) *Service { cp: cp, version: version, enabled: enabled, - tmsCache: utils.NewLazyGetter(loader.load), + tmsCache: lazy.NewGetter(loader.load), } } diff --git a/token/services/db/sql/common/driver.go b/token/services/db/sql/common/driver.go index 7be655476..d71ed7ab8 100644 --- a/token/services/db/sql/common/driver.go +++ b/token/services/db/sql/common/driver.go @@ -10,6 +10,7 @@ import ( "database/sql" utils2 "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils" + "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/lazy" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/db" sql2 "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/db/driver/sql" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/db/driver/sql/common" @@ -18,7 +19,6 @@ import ( "github.com/hyperledger-labs/fabric-token-sdk/token" "github.com/hyperledger-labs/fabric-token-sdk/token/services/config" "github.com/hyperledger-labs/fabric-token-sdk/token/services/db/driver" - "github.com/hyperledger-labs/fabric-token-sdk/token/services/utils" _ "github.com/jackc/pgx/v5/stdlib" "github.com/pkg/errors" _ "modernc.org/sqlite" @@ -37,7 +37,7 @@ type NewDBOpts struct { } type Opener[V any] struct { - dbCache utils.LazyProvider[Opts, V] + dbCache lazy.Provider[Opts, V] optsKey string envVarKey string } @@ -63,7 +63,7 @@ func NewOpenerFromMap[V any](optsKey, envVarKey string, constructors map[common. func NewOpener[V any](optsKey, envVarKey string, constructors OpenDBFunc[V]) *Opener[V] { return &Opener[V]{ - dbCache: utils.NewLazyProviderWithKeyMapper(key, constructors), + dbCache: lazy.NewProviderWithKeyMapper(key, constructors), optsKey: optsKey, envVarKey: envVarKey, } diff --git a/token/services/network/fabric/endorsement/provider.go b/token/services/network/fabric/endorsement/provider.go index e8a4819f4..2d0aa2401 100644 --- a/token/services/network/fabric/endorsement/provider.go +++ b/token/services/network/fabric/endorsement/provider.go @@ -9,6 +9,7 @@ package endorsement import ( "context" + "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/lazy" "github.com/hyperledger-labs/fabric-smart-client/platform/fabric" view2 "github.com/hyperledger-labs/fabric-smart-client/platform/view" driver2 "github.com/hyperledger-labs/fabric-smart-client/platform/view/driver" @@ -17,7 +18,6 @@ import ( token2 "github.com/hyperledger-labs/fabric-token-sdk/token" "github.com/hyperledger-labs/fabric-token-sdk/token/services/network/common" "github.com/hyperledger-labs/fabric-token-sdk/token/services/network/driver" - "github.com/hyperledger-labs/fabric-token-sdk/token/services/utils" "github.com/pkg/errors" ) @@ -40,7 +40,7 @@ type ViewManager interface { type ViewRegistry = driver2.Registry type ServiceProvider struct { - utils.LazyProvider[token2.TMSID, Service] + lazy.Provider[token2.TMSID, Service] } func NewServiceProvider( @@ -59,7 +59,7 @@ func NewServiceProvider( identityProvider: identityProvider, tmsProvider: tmsProvider, } - return &ServiceProvider{LazyProvider: utils.NewLazyProviderWithKeyMapper(key, l.load)} + return &ServiceProvider{Provider: lazy.NewProviderWithKeyMapper(key, l.load)} } type Service interface { diff --git a/token/services/network/fabric/network.go b/token/services/network/fabric/network.go index 86de0f57e..427ff4301 100644 --- a/token/services/network/fabric/network.go +++ b/token/services/network/fabric/network.go @@ -15,6 +15,7 @@ import ( "time" driver2 "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver" + "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/lazy" "github.com/hyperledger-labs/fabric-smart-client/platform/fabric" "github.com/hyperledger-labs/fabric-smart-client/platform/fabric/services/chaincode" view2 "github.com/hyperledger-labs/fabric-smart-client/platform/view" @@ -29,7 +30,6 @@ import ( "github.com/hyperledger-labs/fabric-token-sdk/token/services/network/fabric/endorsement" tokens2 "github.com/hyperledger-labs/fabric-token-sdk/token/services/tokens" "github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx" - "github.com/hyperledger-labs/fabric-token-sdk/token/services/utils" "github.com/hyperledger-labs/fabric-token-sdk/token/services/vault" "github.com/hyperledger-labs/fabric-token-sdk/token/token" "github.com/hyperledger/fabric-protos-go/peer" @@ -155,8 +155,8 @@ type Network struct { tokensProvider *tokens2.Manager finalityTracer trace.Tracer - vaultLazyCache utils.LazyProvider[string, driver.Vault] - tokenVaultLazyCache utils.LazyProvider[string, driver.TokenVault] + vaultLazyCache lazy.Provider[string, driver.Vault] + tokenVaultLazyCache lazy.Provider[string, driver.TokenVault] subscribers *events.Subscribers endorsementServiceProvider *endorsement.ServiceProvider @@ -189,8 +189,8 @@ func NewNetwork( configuration: configuration, filterProvider: filterProvider, tokensProvider: tokensProvider, - vaultLazyCache: utils.NewLazyProvider(loader.loadVault), - tokenVaultLazyCache: utils.NewLazyProvider(loader.loadTokenVault), + vaultLazyCache: lazy.NewProvider(loader.loadVault), + tokenVaultLazyCache: lazy.NewProvider(loader.loadTokenVault), subscribers: events.NewSubscribers(), endorsementServiceProvider: endorsementServiceProvider, finalityTracer: tracerProvider.Tracer("finality_listener", tracing.WithMetricsOpts(tracing.MetricsOpts{ @@ -250,7 +250,7 @@ func (n *Network) Connect(ns string) ([]token2.ServiceOption, error) { NewTokenRWSetProcessor( n.Name(), ns, - utils.NewLazyGetter[*tokens2.Tokens](func() (*tokens2.Tokens, error) { + lazy.NewGetter[*tokens2.Tokens](func() (*tokens2.Tokens, error) { return n.tokensProvider.Tokens(tmsID) }).Get, func() *token2.ManagementServiceProvider { diff --git a/token/services/network/orion/network.go b/token/services/network/orion/network.go index b96977c4c..562e221db 100644 --- a/token/services/network/orion/network.go +++ b/token/services/network/orion/network.go @@ -10,6 +10,7 @@ import ( "context" "time" + "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/lazy" "github.com/hyperledger-labs/fabric-smart-client/platform/orion" view2 "github.com/hyperledger-labs/fabric-smart-client/platform/view" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/events" @@ -21,7 +22,6 @@ import ( "github.com/hyperledger-labs/fabric-token-sdk/token/services/network/common/rws/keys" "github.com/hyperledger-labs/fabric-token-sdk/token/services/network/driver" "github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx" - "github.com/hyperledger-labs/fabric-token-sdk/token/services/utils" "github.com/hyperledger-labs/fabric-token-sdk/token/services/vault" "github.com/hyperledger-labs/fabric-token-sdk/token/token" "github.com/pkg/errors" @@ -48,8 +48,8 @@ type Network struct { filterProvider common2.TransactionFilterProvider[*common2.AcceptTxInDBsFilter] finalityTracer trace.Tracer - vaultLazyCache utils.LazyProvider[string, driver.Vault] - tokenVaultLazyCache utils.LazyProvider[string, driver.TokenVault] + vaultLazyCache lazy.Provider[string, driver.Vault] + tokenVaultLazyCache lazy.Provider[string, driver.TokenVault] subscribers *events.Subscribers dbManager *DBManager } @@ -78,8 +78,8 @@ func NewNetwork( n: n, viewManager: viewManager, tmsProvider: tmsProvider, - vaultLazyCache: utils.NewLazyProvider(loader.loadVault), - tokenVaultLazyCache: utils.NewLazyProvider(loader.loadTokenVault), + vaultLazyCache: lazy.NewProvider(loader.loadVault), + tokenVaultLazyCache: lazy.NewProvider(loader.loadTokenVault), subscribers: events.NewSubscribers(), ledger: &ledger{network: n.Name(), viewManager: viewManager, dbManager: dbManager}, finalityTracer: tracerProvider.Tracer("finality_listener", tracing.WithMetricsOpts(tracing.MetricsOpts{ Namespace: "tokensdk_orion", diff --git a/token/services/selector/sherdlock/manager.go b/token/services/selector/sherdlock/manager.go index 6c3823727..d706724ce 100644 --- a/token/services/selector/sherdlock/manager.go +++ b/token/services/selector/sherdlock/manager.go @@ -9,8 +9,8 @@ package sherdlock import ( "time" + lazy2 "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/lazy" "github.com/hyperledger-labs/fabric-token-sdk/token" - "github.com/hyperledger-labs/fabric-token-sdk/token/services/utils" "github.com/hyperledger-labs/fabric-token-sdk/token/services/utils/types/transaction" token2 "github.com/hyperledger-labs/fabric-token-sdk/token/token" "github.com/pkg/errors" @@ -33,7 +33,7 @@ type tokenSelectorUnlocker interface { } type manager struct { - selectorCache utils.LazyProvider[transaction.ID, tokenSelectorUnlocker] + selectorCache lazy2.Provider[transaction.ID, tokenSelectorUnlocker] locker Locker evictionDelay time.Duration cleanupPeriod time.Duration @@ -56,7 +56,7 @@ func NewManager( m := &manager{ locker: locker, evictionDelay: evictionDelay, - selectorCache: utils.NewLazyProvider(func(txID transaction.ID) (tokenSelectorUnlocker, error) { + selectorCache: lazy2.NewProvider(func(txID transaction.ID) (tokenSelectorUnlocker, error) { return NewSherdSelector(txID, fetcher, locker, precision, backoff), nil }), cleanupPeriod: cleanupPeriod, diff --git a/token/services/selector/sherdlock/service.go b/token/services/selector/sherdlock/service.go index b567d9c3a..bc23f05cd 100644 --- a/token/services/selector/sherdlock/service.go +++ b/token/services/selector/sherdlock/service.go @@ -9,11 +9,11 @@ package sherdlock import ( "time" + lazy2 "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/lazy" "github.com/hyperledger-labs/fabric-token-sdk/token" "github.com/hyperledger-labs/fabric-token-sdk/token/core/common/metrics" "github.com/hyperledger-labs/fabric-token-sdk/token/services/tokendb" "github.com/hyperledger-labs/fabric-token-sdk/token/services/tokenlockdb" - "github.com/hyperledger-labs/fabric-token-sdk/token/services/utils" "github.com/pkg/errors" ) @@ -24,7 +24,7 @@ const ( ) type SelectorService struct { - managerLazyCache utils.LazyProvider[*token.ManagementService, token.SelectorManager] + managerLazyCache lazy2.Provider[*token.ManagementService, token.SelectorManager] } func NewService(tokenDBManager *tokendb.Manager, tokenLockDBManager *tokenlockdb.Manager, metricsProvider metrics.Provider) *SelectorService { @@ -34,7 +34,7 @@ func NewService(tokenDBManager *tokendb.Manager, tokenLockDBManager *tokenlockdb m: newMetrics(metricsProvider), } return &SelectorService{ - managerLazyCache: utils.NewLazyProviderWithKeyMapper(key, loader.load), + managerLazyCache: lazy2.NewProviderWithKeyMapper(key, loader.load), } } diff --git a/token/services/selector/simple/service.go b/token/services/selector/simple/service.go index 97cc96236..60b463f9d 100644 --- a/token/services/selector/simple/service.go +++ b/token/services/selector/simple/service.go @@ -10,10 +10,10 @@ import ( "context" "time" + "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/lazy" "github.com/hyperledger-labs/fabric-token-sdk/token" "github.com/hyperledger-labs/fabric-token-sdk/token/driver" "github.com/hyperledger-labs/fabric-token-sdk/token/services/logging" - "github.com/hyperledger-labs/fabric-token-sdk/token/services/utils" token2 "github.com/hyperledger-labs/fabric-token-sdk/token/token" "github.com/pkg/errors" ) @@ -30,7 +30,7 @@ type LockerProvider interface { } type SelectorService struct { - managerLazyCache utils.LazyProvider[*token.ManagementService, token.SelectorManager] + managerLazyCache lazy.Provider[*token.ManagementService, token.SelectorManager] } func NewService(lockerProvider LockerProvider) *SelectorService { @@ -41,7 +41,7 @@ func NewService(lockerProvider LockerProvider) *SelectorService { requestCertification: true, } return &SelectorService{ - managerLazyCache: utils.NewLazyProviderWithKeyMapper(key, loader.load), + managerLazyCache: lazy.NewProviderWithKeyMapper(key, loader.load), } } diff --git a/token/services/utils/lazygetter.go b/token/services/utils/lazygetter.go deleted file mode 100644 index 6957f3fea..000000000 --- a/token/services/utils/lazygetter.go +++ /dev/null @@ -1,31 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package utils - -import "sync" - -type LazyGetter[V any] interface { - Get() (V, error) -} - -type lazyGetter[V any] struct { - v V - err error - provider func() (V, error) - once sync.Once -} - -func NewLazyGetter[V any](provider func() (V, error)) *lazyGetter[V] { - return &lazyGetter[V]{provider: provider} -} - -func (g *lazyGetter[V]) Get() (V, error) { - g.once.Do(func() { - g.v, g.err = g.provider() - }) - return g.v, g.err -} diff --git a/token/services/utils/lazyprovider.go b/token/services/utils/lazyprovider.go deleted file mode 100644 index 410e16225..000000000 --- a/token/services/utils/lazyprovider.go +++ /dev/null @@ -1,119 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package utils - -import ( - "sync" - - "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils" -) - -type LazyProvider[I any, V any] interface { - Get(I) (V, error) - Peek(input I) (V, bool) - Update(I) (V, V, error) - Delete(I) (V, bool) - Length() int -} - -func NewLazyProvider[K comparable, V any](provider func(K) (V, error)) *lazyProvider[K, K, V] { - return NewLazyProviderWithKeyMapper[K, K, V](func(k K) K { return k }, provider) -} - -func NewLazyProviderWithKeyMapper[I any, K comparable, V any](keyMapper func(I) K, provider func(I) (V, error)) *lazyProvider[I, K, V] { - return &lazyProvider[I, K, V]{ - cache: make(map[K]V), - provider: provider, - keyMapper: keyMapper, - zero: utils.Zero[V](), - } -} - -type lazyProvider[I any, K comparable, V any] struct { - cache map[K]V - cacheLock sync.RWMutex - keyMapper func(I) K - provider func(I) (V, error) - zero V -} - -func (v *lazyProvider[I, K, V]) Update(input I) (V, V, error) { - key := v.keyMapper(input) - - v.cacheLock.Lock() - defer v.cacheLock.Unlock() - oldRes := v.cache[key] - - // create the service for the new public params - res, err := v.provider(input) - if err != nil { - return v.zero, v.zero, err - } - - // register the new service - v.cache[key] = res - - return oldRes, res, nil - -} - -func (v *lazyProvider[I, K, V]) Get(input I) (V, error) { - key := v.keyMapper(input) - if res, ok := v.peek(key); ok { - return res, nil - } - - // lock - v.cacheLock.Lock() - defer v.cacheLock.Unlock() - - // check cache again - if res, ok := v.cache[key]; ok { - return res, nil - } - - // update cache - res, err := v.provider(input) - if err != nil { - return v.zero, err - } - v.cache[key] = res - - return res, nil -} - -func (v *lazyProvider[I, K, V]) Peek(input I) (V, bool) { - return v.peek(v.keyMapper(input)) -} - -func (v *lazyProvider[I, K, V]) peek(key K) (V, bool) { - // Check cache - v.cacheLock.RLock() - defer v.cacheLock.RUnlock() - res, ok := v.cache[key] - return res, ok -} - -func (v *lazyProvider[I, K, V]) Delete(input I) (V, bool) { - key := v.keyMapper(input) - - v.cacheLock.RLock() - res, ok := v.cache[key] - v.cacheLock.RUnlock() - - if ok { - v.cacheLock.Lock() - delete(v.cache, key) - v.cacheLock.Unlock() - } - - return res, ok -} - -func (v *lazyProvider[I, K, V]) Length() int { - return len(v.cache) -} diff --git a/token/services/utils/lazyprovider_test.go b/token/services/utils/lazyprovider_test.go deleted file mode 100644 index 6a2b9443b..000000000 --- a/token/services/utils/lazyprovider_test.go +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package utils - -import ( - "fmt" - "sync" - "testing" - - "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/assert" - "github.com/pkg/errors" -) - -type entry struct{ key, value string } - -func TestNoErrors(t *testing.T) { - cache := newTestCache() - - // Get non existing - val, err := cache.Get(entry{"key", "v1"}) - assert.NoError(err) - assert.Equal("v1", val) - - // Get existing - val, err = cache.Get(entry{"key", "v2"}) - assert.NoError(err) - assert.Equal("v1", val) - - // Update existing - oldVal, newVal, err := cache.Update(entry{"key", "v3"}) - assert.NoError(err) - assert.Equal("v1", oldVal) - assert.Equal("v3", newVal) - - // Get updated - val, err = cache.Get(entry{"key", "v4"}) - assert.NoError(err) - assert.Equal("v3", val) - - // Delete existing - val, ok := cache.Delete(entry{"key", "v5"}) - assert.True(ok) - assert.Equal("v3", val) - - // Get deleted - val, err = cache.Get(entry{"key", "v6"}) - assert.NoError(err) - assert.Equal("v6", val) -} - -func TestDeleteNonExisting(t *testing.T) { - cache := newTestCache() - - val, ok := cache.Delete(entry{"key", "v1"}) - assert.False(ok) - assert.Equal("", val) -} - -func TestUpdateNonExisting(t *testing.T) { - cache := newTestCache() - - oldVal, newVal, err := cache.Update(entry{"key", "v1"}) - assert.NoError(err) - assert.Equal("", oldVal) - assert.Equal("v1", newVal) -} - -func TestError(t *testing.T) { - cache := newTestCache() - - val, err := cache.Get(entry{"error", "e1"}) - assert.Error(err, "e1") - assert.Equal("", val) - - val, err = cache.Get(entry{"key", "v1"}) - assert.NoError(err) - assert.Equal("v1", val) -} - -func TestParallel(t *testing.T) { - const iterations = 100 - cache := newTestCache() - vals := make(chan string, iterations) - done := make(chan struct{}) - - values := make(map[string]struct{}) - go func() { - for v := range vals { - values[v] = struct{}{} - } - done <- struct{}{} - }() - - var wg sync.WaitGroup - wg.Add(iterations) - for i := 0; i < iterations; i++ { - val := fmt.Sprintf("v%d", i) - go func() { - val, err := cache.Get(entry{"key", val}) - assert.NoError(err) - vals <- val - wg.Done() - }() - } - wg.Wait() - close(vals) - - <-done - assert.Equal(1, cache.Length(), "we only updated one key") - assert.Equal(1, len(values), "we always got one value back (the one we first set)") -} - -func newTestCache() LazyProvider[entry, string] { - return NewLazyProviderWithKeyMapper(func(in entry) string { - return in.key - }, func(in entry) (string, error) { - if in.key == "error" { - return "", errors.New(in.value) - } - return in.value, nil - }) -}