diff --git a/cmd/arc/services/cache.go b/cmd/arc/services/cache.go index 96440184f..9bcb09843 100644 --- a/cmd/arc/services/cache.go +++ b/cmd/arc/services/cache.go @@ -6,7 +6,6 @@ import ( "github.com/bitcoin-sv/arc/internal/cache" "github.com/bitcoin-sv/arc/config" - "github.com/coocood/freecache" "github.com/go-redis/redis/v8" ) @@ -15,9 +14,8 @@ var ErrCacheUnknownType = errors.New("unknown cache type") // NewCacheStore creates a new CacheStore based on the provided configuration. func NewCacheStore(cacheConfig *config.CacheConfig) (cache.Store, error) { switch cacheConfig.Engine { - case config.FreeCache: - cacheSize := freecache.NewCache(cacheConfig.Freecache.Size) - return cache.NewFreecacheStore(cacheSize), nil + case config.InMemory: + return cache.NewMemoryStore(), nil case config.Redis: c := redis.NewClient(&redis.Options{ Addr: cacheConfig.Redis.Addr, diff --git a/config/config.go b/config/config.go index 55e13fcfc..28ec24431 100644 --- a/config/config.go +++ b/config/config.go @@ -8,8 +8,8 @@ import ( ) const ( - FreeCache = "freecache" - Redis = "redis" + InMemory = "in-memory" + Redis = "redis" ) type ArcConfig struct { @@ -137,9 +137,8 @@ type PostgresConfig struct { } type CacheConfig struct { - Engine string `mapstructure:"engine"` - Freecache *FreeCacheConfig `mapstructure:"freecache"` - Redis *RedisConfig `mapstructure:"redis"` + Engine string `mapstructure:"engine"` + Redis *RedisConfig `mapstructure:"redis"` } type FreeCacheConfig struct { diff --git a/config/defaults.go b/config/defaults.go index 9eeb98c71..1aa3fd610 100644 --- a/config/defaults.go +++ b/config/defaults.go @@ -197,11 +197,8 @@ func getCallbackerConfig() *CallbackerConfig { func getCacheConfig() *CacheConfig { return &CacheConfig{ - Engine: FreeCache, - Freecache: &FreeCacheConfig{ - Size: 10 * 1024 * 1024, // Default size 10MB. - }, - Redis: &RedisConfig{ + Engine: InMemory, // use in memory cache + Redis: &RedisConfig{ // example of Redis config Addr: "localhost:6379", Password: "", DB: 0, diff --git a/config/example_config.yaml b/config/example_config.yaml index e8515e162..7cdd838b0 100644 --- a/config/example_config.yaml +++ b/config/example_config.yaml @@ -48,10 +48,8 @@ broadcasting: # settings for connection to nodes p2p: 18335 cache: - engine: freecache # cache engine - freecache/redis - freecache: # freecache configuration - size: 10000000 # size of cache - redis: + engine: redis # cache engine - in-memory/redis + redis: # redis cache configuration in case that engine: redis addr: "localhost:6379" password: "" db: 1 diff --git a/internal/cache/cache.go b/internal/cache/cache.go index 23e71ca7a..ef6e501d2 100644 --- a/internal/cache/cache.go +++ b/internal/cache/cache.go @@ -6,14 +6,18 @@ import ( ) var ( - ErrCacheNotFound = errors.New("key not found in cache") - ErrCacheFailedToSet = errors.New("failed to set value in cache") - ErrCacheFailedToDel = errors.New("failed to delete value from cache") - ErrCacheFailedToGet = errors.New("failed to get value from cache") + ErrCacheNotFound = errors.New("key not found in cache") + ErrCacheFailedToSet = errors.New("failed to set value in cache") + ErrCacheFailedToDel = errors.New("failed to delete value from cache") + ErrCacheFailedToGet = errors.New("failed to get value from cache") + ErrCacheFailedToScan = errors.New("failed to scan cache") + ErrCacheFailedToGetCount = errors.New("failed to get count from cache") ) type Store interface { - Get(key string) ([]byte, error) - Set(key string, value []byte, ttl time.Duration) error - Del(key string) error + Get(hash *string, key string) ([]byte, error) + GetAllForHash(hash string) (map[string][]byte, error) + Set(hash *string, key string, value []byte, ttl time.Duration) error + Del(hash *string, keys ...string) error + CountElementsForHash(hash string) (int64, error) } diff --git a/internal/cache/freecache.go b/internal/cache/freecache.go deleted file mode 100644 index a84460a54..000000000 --- a/internal/cache/freecache.go +++ /dev/null @@ -1,50 +0,0 @@ -package cache - -import ( - "errors" - "time" - - "github.com/coocood/freecache" -) - -// FreecacheStore is an implementation of CacheStore using freecache. -type FreecacheStore struct { - cache *freecache.Cache -} - -// NewFreecacheStore initializes a FreecacheStore. -func NewFreecacheStore(c *freecache.Cache) *FreecacheStore { - return &FreecacheStore{ - cache: c, - } -} - -// Get retrieves a value by key. -func (f *FreecacheStore) Get(key string) ([]byte, error) { - value, err := f.cache.Get([]byte(key)) - if err != nil { - if errors.Is(err, freecache.ErrNotFound) { - return nil, ErrCacheNotFound - } - return nil, errors.Join(ErrCacheFailedToGet, err) - } - return value, nil -} - -// Set stores a value with a TTL. -func (f *FreecacheStore) Set(key string, value []byte, ttl time.Duration) error { - err := f.cache.Set([]byte(key), value, int(ttl.Seconds())) - if err != nil { - return errors.Join(ErrCacheFailedToSet, err) - } - return nil -} - -// Del removes a value by key. -func (f *FreecacheStore) Del(key string) error { - success := f.cache.Del([]byte(key)) - if !success { - return ErrCacheNotFound - } - return nil -} diff --git a/internal/cache/in_memory.go b/internal/cache/in_memory.go new file mode 100644 index 000000000..bf4c05a83 --- /dev/null +++ b/internal/cache/in_memory.go @@ -0,0 +1,121 @@ +package cache + +import ( + "errors" + "sync" + "time" +) + +type MemoryStore struct { + data sync.Map +} + +func NewMemoryStore() *MemoryStore { + return &MemoryStore{} +} + +// Get retrieves a value by key and hash (if given) +func (s *MemoryStore) Get(hash *string, key string) ([]byte, error) { + if hash != nil { + hashValue, found := s.data.Load(hash) + if !found { + return nil, ErrCacheNotFound + } + + hashMap, ok := hashValue.(map[string][]byte) + if !ok { + return nil, ErrCacheFailedToGet + } + + fieldValue, exists := hashMap[key] + if !exists { + return nil, ErrCacheNotFound + } + + return fieldValue, nil + } + + value, found := s.data.Load(key) + if !found { + return nil, ErrCacheNotFound + } + + bytes, ok := value.([]byte) + if !ok { + return nil, ErrCacheFailedToGet + } + + return bytes, nil +} + +// Set stores a key-value pair, ignoring the ttl parameter. +func (s *MemoryStore) Set(hash *string, key string, value []byte, _ time.Duration) error { + if hash != nil { + raw, _ := s.data.LoadOrStore(*hash, make(map[string][]byte)) + + hashMap, ok := raw.(map[string][]byte) + if !ok { + return ErrCacheFailedToSet + } + + hashMap[key] = value + + s.data.Store(*hash, hashMap) + return nil + } + + s.data.Store(key, value) + return nil +} + +// Del removes a key from the store. +func (s *MemoryStore) Del(hash *string, keys ...string) error { + if hash != nil { + hashValue, found := s.data.Load(*hash) + if !found { + return ErrCacheNotFound + } + + hashMap, ok := hashValue.(map[string][]byte) + if !ok { + return errors.Join(ErrCacheFailedToDel, ErrCacheFailedToGet) + } + + for _, k := range keys { + delete(hashMap, k) + } + + s.data.Store(*hash, hashMap) + return nil + } + + for _, k := range keys { + s.data.Delete(k) + } + return nil +} + +// GetAllForHash retrieves all key-value pairs for a specific hash. +func (s *MemoryStore) GetAllForHash(hash string) (map[string][]byte, error) { + hashValue, found := s.data.Load(hash) + if !found { + return nil, ErrCacheNotFound + } + + hashMap, ok := hashValue.(map[string][]byte) + if !ok { + return nil, ErrCacheFailedToGet + } + + return hashMap, nil +} + +// CountElementsForHash returns the number of elements in a hash in memory. +func (s *MemoryStore) CountElementsForHash(hash string) (int64, error) { + hashMap, err := s.GetAllForHash(hash) + if err != nil { + return 0, err + } + + return int64(len(hashMap)), nil +} diff --git a/internal/cache/redis.go b/internal/cache/redis.go index 932f4ace0..fc12b6226 100644 --- a/internal/cache/redis.go +++ b/internal/cache/redis.go @@ -22,29 +22,54 @@ func NewRedisStore(ctx context.Context, c redis.UniversalClient) *RedisStore { } } -// Get retrieves a value by key. -func (r *RedisStore) Get(key string) ([]byte, error) { - result, err := r.client.Get(r.ctx, key).Result() +// Get retrieves a value by key and hash (if given). +func (r *RedisStore) Get(hash *string, key string) ([]byte, error) { + var result string + var err error + + if hash == nil { + result, err = r.client.Get(r.ctx, key).Result() + } else { + result, err = r.client.HGet(r.ctx, *hash, key).Result() + } + if errors.Is(err, redis.Nil) { return nil, ErrCacheNotFound } else if err != nil { return nil, errors.Join(ErrCacheFailedToGet, err) } + return []byte(result), nil } -// Set stores a value with a TTL. -func (r *RedisStore) Set(key string, value []byte, ttl time.Duration) error { - err := r.client.Set(r.ctx, key, value, ttl).Err() +// Set stores a value with a TTL for a specific hash (if given). +func (r *RedisStore) Set(hash *string, key string, value []byte, ttl time.Duration) error { + var err error + + if hash == nil { + err = r.client.Set(r.ctx, key, value, ttl).Err() + } else { + err = r.client.HSet(r.ctx, *hash, key, value).Err() + } + if err != nil { return errors.Join(ErrCacheFailedToSet, err) } + return nil } // Del removes a value by key. -func (r *RedisStore) Del(key string) error { - result, err := r.client.Del(r.ctx, key).Result() +func (r *RedisStore) Del(hash *string, keys ...string) error { + var result int64 + var err error + + if hash == nil { + result, err = r.client.Del(r.ctx, keys...).Result() + } else { + result, err = r.client.HDel(r.ctx, *hash, keys...).Result() + } + if err != nil { return errors.Join(ErrCacheFailedToDel, err) } @@ -53,3 +78,26 @@ func (r *RedisStore) Del(key string) error { } return nil } + +// GetAllForHash retrieves all key-value pairs for a specific hash. +func (r *RedisStore) GetAllForHash(hash string) (map[string][]byte, error) { + values, err := r.client.HGetAll(r.ctx, hash).Result() + if err != nil { + return nil, errors.Join(ErrCacheFailedToGet, err) + } + + result := make(map[string][]byte) + for field, value := range values { + result[field] = []byte(value) + } + return result, nil +} + +// CountElementsForHash returns the number of elements in a hash. +func (r *RedisStore) CountElementsForHash(hash string) (int64, error) { + count, err := r.client.HLen(r.ctx, hash).Result() + if err != nil { + return 0, errors.Join(ErrCacheFailedToGetCount, err) + } + return count, nil +} diff --git a/internal/metamorph/health_check_test.go b/internal/metamorph/health_check_test.go index 4f6b6b84b..2dca75711 100644 --- a/internal/metamorph/health_check_test.go +++ b/internal/metamorph/health_check_test.go @@ -14,8 +14,6 @@ import ( storeMocks "github.com/bitcoin-sv/arc/internal/metamorph/store/mocks" ) -const baseCacheSize = 100 * 1024 * 1024 - func TestCheck(t *testing.T) { tt := []struct { name string diff --git a/internal/metamorph/integration_test/double_spend_integration_test.go b/internal/metamorph/integration_test/double_spend_integration_test.go index 7a8e04f13..dd6ce5ef6 100644 --- a/internal/metamorph/integration_test/double_spend_integration_test.go +++ b/internal/metamorph/integration_test/double_spend_integration_test.go @@ -24,7 +24,6 @@ import ( "testing" "time" - "github.com/coocood/freecache" _ "github.com/golang-migrate/migrate/v4/source/file" _ "github.com/lib/pq" "github.com/libsv/go-p2p/chaincfg/chainhash" @@ -124,9 +123,8 @@ func TestDoubleSpendDetection(t *testing.T) { require.NoError(t, err) defer metamorphStore.Close(context.Background()) - cStore := cache.NewFreecacheStore(freecache.NewCache(baseCacheSize)) - pm := &mocks.PeerManagerMock{ShutdownFunc: func() {}} + cStore := cache.NewMemoryStore() processor, err := metamorph.NewProcessor(metamorphStore, cStore, pm, statusMessageChannel, metamorph.WithMinedTxsChan(minedTxChannel), diff --git a/internal/metamorph/processor.go b/internal/metamorph/processor.go index dbce47395..9ad85b5f5 100644 --- a/internal/metamorph/processor.go +++ b/internal/metamorph/processor.go @@ -408,28 +408,46 @@ func (p *Processor) StartProcessStatusUpdatesInStorage() { go func() { defer p.waitGroup.Done() - statusUpdatesMap := map[chainhash.Hash]store.UpdateStatus{} - for { select { case <-p.ctx.Done(): return case statusUpdate := <-p.storageStatusUpdateCh: // Ensure no duplicate statuses - updateStatusMap(statusUpdatesMap, statusUpdate) + err := p.updateStatusMap(statusUpdate) + if err != nil { + p.logger.Error("failed to update status", slog.String("err", err.Error())) + return + } + + statusUpdateCount, err := p.getStatusUpdateCount() + if err != nil { + p.logger.Error("failed to get status update count", slog.String("err", err.Error())) + return + } + + if statusUpdateCount >= p.processStatusUpdatesBatchSize { + statusUpdatesMap, err := p.getAllTransactionStatuses() + if err != nil { + p.logger.Error("failed to get all transaction statuses", slog.String("err", err.Error())) + return + } - if len(statusUpdatesMap) >= p.processStatusUpdatesBatchSize { p.checkAndUpdate(ctx, statusUpdatesMap) - statusUpdatesMap = map[chainhash.Hash]store.UpdateStatus{} // Reset ticker to delay the next tick, ensuring the interval starts after the batch is processed. // This prevents unnecessary immediate updates and maintains the intended time interval between batches. ticker.Reset(p.processStatusUpdatesInterval) } case <-ticker.C: + statusUpdatesMap, err := p.getAllTransactionStatuses() + if err != nil { + p.logger.Error("failed to get all transaction statuses", slog.String("err", err.Error())) + return + } + if len(statusUpdatesMap) > 0 { p.checkAndUpdate(ctx, statusUpdatesMap) - statusUpdatesMap = map[chainhash.Hash]store.UpdateStatus{} // Reset ticker to delay the next tick, ensuring the interval starts after the batch is processed. // This prevents unnecessary immediate updates and maintains the intended time interval between batches. @@ -440,7 +458,7 @@ func (p *Processor) StartProcessStatusUpdatesInStorage() { }() } -func (p *Processor) checkAndUpdate(ctx context.Context, statusUpdatesMap map[chainhash.Hash]store.UpdateStatus) { +func (p *Processor) checkAndUpdate(ctx context.Context, statusUpdatesMap StatusUpdateMap) { ctx, span := tracing.StartTracing(ctx, "checkAndUpdate", p.tracingEnabled, p.tracingAttributes...) defer tracing.EndTracing(span) @@ -463,6 +481,11 @@ func (p *Processor) checkAndUpdate(ctx context.Context, statusUpdatesMap map[cha if err != nil { p.logger.Error("failed to bulk update statuses", slog.String("err", err.Error())) } + + err = p.clearCache(statusUpdatesMap) + if err != nil { + p.logger.Error("failed to clear status update cache", slog.String("err", err.Error())) + } } func (p *Processor) statusUpdateWithCallback(ctx context.Context, statusUpdates, doubleSpendUpdates []store.UpdateStatus) error { diff --git a/internal/metamorph/processor_helpers.go b/internal/metamorph/processor_helpers.go index d50f1ba80..0c09c11f6 100644 --- a/internal/metamorph/processor_helpers.go +++ b/internal/metamorph/processor_helpers.go @@ -6,12 +6,13 @@ import ( "github.com/libsv/go-p2p/chaincfg/chainhash" + "github.com/bitcoin-sv/arc/internal/cache" "github.com/bitcoin-sv/arc/internal/metamorph/store" ) -//lint:file-ignore U1000 Ignore all unused code, functions are temporarily not used +type StatusUpdateMap map[chainhash.Hash]store.UpdateStatus -const CacheStatusUpdateKey = "status-updates" +var CacheStatusUpdateHash = "status-update" var ( ErrFailedToSerialize = errors.New("failed to serialize value") @@ -22,64 +23,95 @@ func (p *Processor) GetProcessorMapSize() int { return p.responseProcessor.getMapLen() } -func updateStatusMap(statusUpdatesMap map[chainhash.Hash]store.UpdateStatus, statusUpdate store.UpdateStatus) { - foundStatusUpdate, found := statusUpdatesMap[statusUpdate.Hash] +func (p *Processor) updateStatusMap(statusUpdate store.UpdateStatus) error { + currentStatusUpdate, err := p.getTransactionStatus(statusUpdate.Hash) + if err != nil { + if errors.Is(err, cache.ErrCacheNotFound) { + // if record doesn't exist, save new one + return p.setTransactionStatus(statusUpdate) + } + return err + } - if !found || shouldUpdateStatus(statusUpdate, foundStatusUpdate) { + if shouldUpdateStatus(statusUpdate, *currentStatusUpdate) { if len(statusUpdate.CompetingTxs) > 0 { - statusUpdate.CompetingTxs = mergeUnique(statusUpdate.CompetingTxs, foundStatusUpdate.CompetingTxs) + statusUpdate.CompetingTxs = mergeUnique(statusUpdate.CompetingTxs, currentStatusUpdate.CompetingTxs) } - - statusUpdatesMap[statusUpdate.Hash] = statusUpdate + // TODO: combine status history } -} -func (p *Processor) updateStatusMap(statusUpdate store.UpdateStatus) (map[chainhash.Hash]store.UpdateStatus, error) { //nolint:unused - statusUpdatesMap := p.getStatusUpdateMap() + return p.setTransactionStatus(statusUpdate) +} - foundStatusUpdate, found := statusUpdatesMap[statusUpdate.Hash] +func (p *Processor) setTransactionStatus(status store.UpdateStatus) error { + bytes, err := json.Marshal(status) + if err != nil { + return errors.Join(ErrFailedToSerialize, err) + } - if !found || shouldUpdateStatus(statusUpdate, foundStatusUpdate) { - if len(statusUpdate.CompetingTxs) > 0 { - statusUpdate.CompetingTxs = mergeUnique(statusUpdate.CompetingTxs, foundStatusUpdate.CompetingTxs) - } + err = p.cacheStore.Set(&CacheStatusUpdateHash, status.Hash.String(), bytes, processStatusUpdatesIntervalDefault) + if err != nil { + return err + } + return nil +} - statusUpdatesMap[statusUpdate.Hash] = statusUpdate +func (p *Processor) getTransactionStatus(hash chainhash.Hash) (*store.UpdateStatus, error) { + bytes, err := p.cacheStore.Get(&CacheStatusUpdateHash, hash.String()) + if err != nil { + return nil, err } - err := p.setStatusUpdateMap(statusUpdatesMap) + var status store.UpdateStatus + err = json.Unmarshal(bytes, &status) if err != nil { return nil, err } - return statusUpdatesMap, nil + return &status, nil } -func (p *Processor) setStatusUpdateMap(statusUpdatesMap map[chainhash.Hash]store.UpdateStatus) error { //nolint:unused - bytes, err := serializeStatusMap(statusUpdatesMap) +func (p *Processor) getAllTransactionStatuses() (StatusUpdateMap, error) { + statuses := make(StatusUpdateMap) + keys, err := p.cacheStore.GetAllForHash(CacheStatusUpdateHash) if err != nil { - return err + return nil, err } - err = p.cacheStore.Set(CacheStatusUpdateKey, bytes, processStatusUpdatesIntervalDefault) - if err != nil { - return err + for key, value := range keys { + hash, err := chainhash.NewHashFromStr(key) + if err != nil { + return nil, err + } + + var status store.UpdateStatus + err = json.Unmarshal(value, &status) + if err != nil { + return nil, err + } + + statuses[*hash] = status } - return nil + + return statuses, nil } -func (p *Processor) getStatusUpdateMap() map[chainhash.Hash]store.UpdateStatus { //nolint:unused - existingMap, err := p.cacheStore.Get(CacheStatusUpdateKey) +func (p *Processor) clearCache(updateStatusMap StatusUpdateMap) error { + keys := make([]string, len(updateStatusMap)) + for k := range updateStatusMap { + keys = append(keys, k.String()) + } - if err == nil { - statusUpdatesMap, err := deserializeStatusMap(existingMap) - if err == nil { - return statusUpdatesMap - } + return p.cacheStore.Del(&CacheStatusUpdateHash, keys...) +} + +func (p *Processor) getStatusUpdateCount() (int, error) { + count, err := p.cacheStore.CountElementsForHash(CacheStatusUpdateHash) + if err != nil { + return 0, err } - // If the key doesn't exist or there was an error unmarshalling the value return new map - return make(map[chainhash.Hash]store.UpdateStatus) + return int(count), nil } func shouldUpdateStatus(new, found store.UpdateStatus) bool { @@ -135,36 +167,3 @@ func mergeUnique(arr1, arr2 []string) []string { return uniqueSlice } - -func serializeStatusMap(updateStatusMap map[chainhash.Hash]store.UpdateStatus) ([]byte, error) { //nolint:unused - serializeMap := make(map[string]store.UpdateStatus) - for k, v := range updateStatusMap { - serializeMap[k.String()] = v - } - - bytes, err := json.Marshal(serializeMap) - if err != nil { - return nil, errors.Join(ErrFailedToSerialize, err) - } - return bytes, nil -} - -func deserializeStatusMap(data []byte) (map[chainhash.Hash]store.UpdateStatus, error) { //nolint:unused - serializeMap := make(map[string]store.UpdateStatus) - updateStatusMap := make(map[chainhash.Hash]store.UpdateStatus) - - err := json.Unmarshal(data, &serializeMap) - if err != nil { - return nil, errors.Join(ErrFailedToDeserialize, err) - } - - for k, v := range serializeMap { - hash, err := chainhash.NewHashFromStr(k) - if err != nil { - return nil, errors.Join(ErrFailedToDeserialize, err) - } - updateStatusMap[*hash] = v - } - - return updateStatusMap, nil -} diff --git a/internal/metamorph/processor_test.go b/internal/metamorph/processor_test.go index ea4d65e7d..7e5378ff7 100644 --- a/internal/metamorph/processor_test.go +++ b/internal/metamorph/processor_test.go @@ -11,7 +11,6 @@ import ( "testing" "time" - "github.com/coocood/freecache" "github.com/libsv/go-p2p" "github.com/libsv/go-p2p/chaincfg/chainhash" "github.com/stretchr/testify/assert" @@ -37,8 +36,7 @@ func TestNewProcessor(t *testing.T) { } pm := &mocks.PeerManagerMock{ShutdownFunc: func() {}} - - cStore := cache.NewFreecacheStore(freecache.NewCache(baseCacheSize)) + cStore := cache.NewMemoryStore() tt := []struct { name string @@ -125,10 +123,10 @@ func TestStartLockTransactions(t *testing.T) { SetUnlockedByNameFunc: func(_ context.Context, _ string) (int64, error) { return 0, nil }, } - cStore := cache.NewFreecacheStore(freecache.NewCache(baseCacheSize)) - pm := &mocks.PeerManagerMock{ShutdownFunc: func() {}} + cStore := cache.NewMemoryStore() + // when sut, err := metamorph.NewProcessor(metamorphStore, cStore, pm, nil, metamorph.WithLockTxsInterval(20*time.Millisecond)) require.NoError(t, err) @@ -228,8 +226,6 @@ func TestProcessTransaction(t *testing.T) { }, } - cStore := cache.NewFreecacheStore(freecache.NewCache(baseCacheSize)) - pm := &mocks.PeerManagerMock{ AnnounceTransactionFunc: func(txHash *chainhash.Hash, _ []p2p.PeerI) []p2p.PeerI { require.True(t, testdata.TX1Hash.IsEqual(txHash)) @@ -238,6 +234,8 @@ func TestProcessTransaction(t *testing.T) { RequestTransactionFunc: func(_ *chainhash.Hash) p2p.PeerI { return nil }, } + cStore := cache.NewMemoryStore() + publisher := &mocks.MessageQueueClientMock{ PublishFunc: func(_ string, _ []byte) error { return nil @@ -490,10 +488,10 @@ func TestStartSendStatusForTransaction(t *testing.T) { }, } - cStore := cache.NewFreecacheStore(freecache.NewCache(baseCacheSize)) - pm := &mocks.PeerManagerMock{ShutdownFunc: func() {}} + cStore := cache.NewMemoryStore() + callbackSender := &mocks.CallbackSenderMock{ SendCallbackFunc: func(_ context.Context, _ *store.Data) { callbackSent <- struct{}{} @@ -641,7 +639,6 @@ func TestStartProcessSubmittedTxs(t *testing.T) { }, SetUnlockedByNameFunc: func(_ context.Context, _ string) (int64, error) { return 0, nil }, } - cStore := cache.NewFreecacheStore(freecache.NewCache(baseCacheSize)) counter := 0 pm := &mocks.PeerManagerMock{ AnnounceTransactionFunc: func(txHash *chainhash.Hash, _ []p2p.PeerI) []p2p.PeerI { @@ -657,6 +654,8 @@ func TestStartProcessSubmittedTxs(t *testing.T) { ShutdownFunc: func() {}, } + cStore := cache.NewMemoryStore() + publisher := &mocks.MessageQueueClientMock{ PublishFunc: func(_ string, _ []byte) error { return nil @@ -774,8 +773,6 @@ func TestProcessExpiredTransactions(t *testing.T) { }, } - cStore := cache.NewFreecacheStore(freecache.NewCache(baseCacheSize)) - pm := &mocks.PeerManagerMock{ RequestTransactionFunc: func(_ *chainhash.Hash) p2p.PeerI { return nil @@ -786,6 +783,8 @@ func TestProcessExpiredTransactions(t *testing.T) { ShutdownFunc: func() {}, } + cStore := cache.NewMemoryStore() + publisher := &mocks.MessageQueueClientMock{ PublishFunc: func(_ string, _ []byte) error { return nil @@ -873,7 +872,7 @@ func TestStartProcessMinedCallbacks(t *testing.T) { callbackSender := &mocks.CallbackSenderMock{ SendCallbackFunc: func(_ context.Context, _ *store.Data) {}, } - cStore := cache.NewFreecacheStore(freecache.NewCache(baseCacheSize)) + cStore := cache.NewMemoryStore() sut, err := metamorph.NewProcessor( metamorphStore, cStore, @@ -950,8 +949,6 @@ func TestProcessorHealth(t *testing.T) { }, } - cStore := cache.NewFreecacheStore(freecache.NewCache(baseCacheSize)) - pm := &mocks.PeerManagerMock{ AddPeerFunc: func(_ p2p.PeerI) error { return nil @@ -966,6 +963,7 @@ func TestProcessorHealth(t *testing.T) { }, ShutdownFunc: func() {}, } + cStore := cache.NewMemoryStore() sut, err := metamorph.NewProcessor(metamorphStore, cStore, pm, nil, metamorph.WithProcessExpiredTxsInterval(time.Millisecond*20), @@ -1019,10 +1017,10 @@ func TestStart(t *testing.T) { return 0, nil }} - cStore := cache.NewFreecacheStore(freecache.NewCache(baseCacheSize)) - pm := &mocks.PeerManagerMock{ShutdownFunc: func() {}} + cStore := cache.NewMemoryStore() + var subscribeMinedTxsFunction func([]byte) error var subscribeSubmitTxsFunction func([]byte) error mqClient := &mocks.MessageQueueClientMock{ diff --git a/internal/metamorph/stats_collector_test.go b/internal/metamorph/stats_collector_test.go index 7bd40efab..2dd35de12 100644 --- a/internal/metamorph/stats_collector_test.go +++ b/internal/metamorph/stats_collector_test.go @@ -3,8 +3,6 @@ package metamorph_test import ( "context" "errors" - "github.com/bitcoin-sv/arc/internal/cache" - "github.com/coocood/freecache" "log/slog" "os" "testing" @@ -51,11 +49,9 @@ func TestStartCollectStats(t *testing.T) { SetUnlockedByNameFunc: func(_ context.Context, _ string) (int64, error) { return 0, nil }, } - cStore := cache.NewFreecacheStore(freecache.NewCache(baseCacheSize)) - pm := &mocks.PeerManagerMock{ShutdownFunc: func() {}} - processor, err := metamorph.NewProcessor(mtmStore, cStore, pm, nil, + processor, err := metamorph.NewProcessor(mtmStore, nil, pm, nil, metamorph.WithProcessorLogger(slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: metamorph.LogLevelDefault}))), metamorph.WithStatCollectionInterval(10*time.Millisecond), )