Skip to content

Commit

Permalink
feat: implement routes overwrite core for the /quote endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
p0mvn committed Jan 8, 2024
1 parent 331870e commit fa414f7
Show file tree
Hide file tree
Showing 20 changed files with 772 additions and 922 deletions.
16 changes: 15 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,20 @@
"mode": "auto",
"program": "${workspaceFolder}/app/main.go ${workspaceFolder}/app/sidecar_query_server.go ${workspaceFolder}/app/sqs_config.go",
"cwd": "${workspaceFolder}",
}
},
{
"name": "router/usecase",
"type": "go",
"request": "launch",
"mode": "test",
"program": "${workspaceFolder}/router/usecase",
"args": [
"-test.timeout",
"30m",
"-test.run",
"TestRouterTestSuite/TestGetOptimalQuote_Cache_Overwrites",
"-test.v"
],
},
]
}
7 changes: 6 additions & 1 deletion app/sidecar_query_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,14 @@ func NewSideCarQueryServer(appCodec codec.Codec, routerConfig domain.RouterConfi
poolsUseCase := poolsUseCase.NewPoolsUsecase(timeoutContext, poolsRepository, redisTxManager)
poolsHttpDelivery.NewPoolsHandler(e, poolsUseCase)

// Create an overwrite route cache if enabled.
// We keep it as nil by default.
// The relevant endpoints must check if it is set.
routesOverwrite := cache.CreateRoutesOverwrite(routerConfig.EnableOverwriteRoutesCache)

// Initialize router repository, usecase and HTTP handler
routerRepository := routerredisrepo.New(redisTxManager, routerConfig.RouteCacheExpirySeconds)
routerUsecase := routerUseCase.NewRouterUsecase(timeoutContext, routerRepository, poolsUseCase, routerConfig, logger, cache.New())
routerUsecase := routerUseCase.NewRouterUsecase(timeoutContext, routerRepository, poolsUseCase, routerConfig, logger, cache.New(), routesOverwrite)
routerHttpDelivery.NewRouterHandler(e, routerUsecase, logger)

// Initialize system handler
Expand Down
21 changes: 0 additions & 21 deletions config-mainnet.json

This file was deleted.

3 changes: 2 additions & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"min-osmo-liquidity": 10000,
"route-cache-enabled": true,
"route-cache-expiry-seconds": 600
}
},
"enable-overwrite-routes-cache": true
}

15 changes: 13 additions & 2 deletions domain/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ func (c *Cache) Set(key string, value interface{}, expiration time.Duration) {
c.mutex.Lock()
defer c.mutex.Unlock()

expirationTime := time.Now().Add(expiration)
expirationTime := time.Time{}
if expiration != noExpiration {
expirationTime = time.Now().Add(expiration)
}
c.data[key] = CacheItem{
Value: value,
Expiration: expirationTime,
Expand All @@ -46,7 +49,7 @@ func (c *Cache) Get(key string) (interface{}, bool) {
return nil, false
}

if time.Now().After(item.Expiration) {
if !item.Expiration.IsZero() && time.Now().After(item.Expiration) {
// Unlock before locking again
c.mutex.RUnlock()

Expand All @@ -61,3 +64,11 @@ func (c *Cache) Get(key string) (interface{}, bool) {

return item.Value, true
}

// Delete removes an item from the cache.
func (c *Cache) Delete(key string) {
c.mutex.Lock()
defer c.mutex.Unlock()

delete(c.data, key)
}
52 changes: 52 additions & 0 deletions domain/cache/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,55 @@ func TestConcurrentCache(t *testing.T) {
}
}
}

func TestCache_SetExpiration(t *testing.T) {
c := cache.New()

tests := []struct {
name string
key string
value interface{}
expiration time.Duration
expectExist bool
}{
{
name: "Set with Expiration - Key Exists",
key: "key1",
value: "value1",
expiration: 100 * time.Millisecond,
expectExist: true,
},
{
name: "Set with Expiration - Key Expires",
key: "key2",
value: "value2",
expiration: 50 * time.Millisecond,
expectExist: false,
},
{
name: "Set with No Expiration - Key Exists",
key: "key3",
value: "value3",
expiration: cache.NoExpiration,
expectExist: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c.Set(tt.key, tt.value, tt.expiration)
time.Sleep(75 * time.Millisecond) // Sleep to wait for expiration in the second test case

// Check if the key exists in the cache
value, exists := c.Get(tt.key)
if exists != tt.expectExist {
t.Errorf("Expected key %s to exist: %v, got: %v", tt.key, tt.expectExist, exists)
}

// If the key is expected to exist, also check if the value matches
if tt.expectExist && value != tt.value {
t.Errorf("Expected value for key %s: %v, got: %v", tt.key, tt.value, value)
}
})
}
}
5 changes: 5 additions & 0 deletions domain/cache/export_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package cache

import "time"

const NoExpiration time.Duration = 0
61 changes: 61 additions & 0 deletions domain/cache/routes_overwrite.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package cache

import "time"

type RoutesOverwrite struct {
cache *Cache
}

const noExpiration time.Duration = 0

// NewRoutesOverwrite creates a new routes overwrite container.
func NewRoutesOverwrite() *RoutesOverwrite {
return &RoutesOverwrite{
cache: New(),
}
}

// NewNoOpRoutesOverwrite creates a new routes overwrite container that does nothing.
func NewNoOpRoutesOverwrite() *RoutesOverwrite {
return &RoutesOverwrite{}
}

// CreateRoutesOverwrite creates a new routes overwrite container depending on the value of isRoutesOverwriteEnabled.
// If isRoutesOverwriteEnabled is true, it will return a new routes overwrite container.
// If isRoutesOverwriteEnabled is false, it will return a new no-op routes overwrite container.
func CreateRoutesOverwrite(isRoutesOverwriteEnabled bool) *RoutesOverwrite {
if isRoutesOverwriteEnabled {
return NewRoutesOverwrite()
}
return NewNoOpRoutesOverwrite()
}

// Set adds an item to the cache with a specified key and value.
// If the routes overwrite cache is not enabled, it will silently ignore the call.
func (r *RoutesOverwrite) Set(key string, value interface{}) {
if r.cache == nil {
return
}

r.cache.Set(key, value, noExpiration)
}

// Get retrieves the value associated with a key from the cache. Returns false if the key does not exist.
// If the routes overwrite cache is not enabled, it will silently ignore the call.
func (r *RoutesOverwrite) Get(key string) (interface{}, bool) {
if r.cache == nil {
return nil, false
}

return r.cache.Get(key)
}

// Delete removes an item from the cache.
// If the routes overwrite cache is not enabled, it will silently ignore the call.
func (r *RoutesOverwrite) Delete(key string) {
if r.cache == nil {
return
}

r.cache.Delete(key)
}
157 changes: 157 additions & 0 deletions domain/cache/routes_overwrite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package cache_test

import (
"testing"

"github.com/osmosis-labs/sqs/domain/cache"
)

func TestRoutesOverwrite_Set(t *testing.T) {
tests := []struct {
name string
isRoutesOverwriteEnabled bool
key string
value interface{}
expectedExists bool
expectedValue interface{}
}{
{
name: "Cache Enabled - Set Value",
isRoutesOverwriteEnabled: true,
key: "key1",
value: "value1",
expectedExists: true,
expectedValue: "value1",
},
{
name: "Cache Disabled - Set Value",
isRoutesOverwriteEnabled: false,
key: "key2",
value: "value2",
expectedExists: false,
expectedValue: nil,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := cache.CreateRoutesOverwrite(tt.isRoutesOverwriteEnabled)
r.Set(tt.key, tt.value)

// Additional assertions
value, exists := r.Get(tt.key)
if exists != tt.expectedExists {
t.Errorf("Expected key %s to exist: %v, got: %v", tt.key, tt.expectedExists, exists)
}

if value != tt.expectedValue {
t.Errorf("Expected value for key %s: %v, got: %v", tt.key, tt.expectedValue, value)
}
})
}
}

func TestRoutesOverwrite_Get(t *testing.T) {
// Assuming Set method is working correctly.
// Setting up some initial data for testing Get method.

r := cache.NewRoutesOverwrite()
r.Set("key1", "value1")
r.Set("key2", "value2")

tests := []struct {
name string
isRoutesOverwriteEnabled bool
key string
expectedValue interface{}
expectedExists bool
}{
{
name: "Cache Enabled - Key Exists",
isRoutesOverwriteEnabled: true,
key: "key1",
expectedValue: "value1",
expectedExists: true,
},
{
name: "Cache Enabled - Key Does Not Exist",
isRoutesOverwriteEnabled: true,
key: "key3",
expectedValue: nil,
expectedExists: false,
},
{
name: "Cache Disabled - Key Exists",
isRoutesOverwriteEnabled: false,
key: "key2",
expectedValue: nil,
expectedExists: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
value, exists := r.Get(tt.key)

if value != tt.expectedValue || exists != tt.expectedExists {
t.Errorf("Got (%v, %v), expected (%v, %v)", value, exists, tt.expectedValue, tt.expectedExists)
}
})
}
}

func TestRoutesOverwrite_Delete(t *testing.T) {
// Assuming Set method is working correctly.
// Setting up some initial data for testing Delete method.

r := cache.NewRoutesOverwrite()
r.Set("key1", "value1")
r.Set("key2", "value2")

tests := []struct {
name string
isRoutesOverwriteEnabled bool
key string
expectedExists bool
expectedValue interface{}
}{
{
name: "Cache Enabled - Delete Key",
isRoutesOverwriteEnabled: true,
key: "key1",
expectedExists: false,
expectedValue: nil,
},
{
name: "Cache Enabled - Delete Non-Existing Key",
isRoutesOverwriteEnabled: true,
key: "key3",
expectedExists: false,
expectedValue: nil,
},
{
name: "Cache Disabled - Delete Key",
isRoutesOverwriteEnabled: false,
key: "key2",
expectedExists: false,
expectedValue: nil,
},
// Add more test cases as needed
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r.Delete(tt.key)

// Additional assertions
value, exists := r.Get(tt.key)
if exists != tt.expectedExists {
t.Errorf("Expected key %s to exist: %v, got: %v", tt.key, tt.expectedExists, exists)
}

if value != tt.expectedValue {
t.Errorf("Expected value for key %s: %v, got: %v", tt.key, tt.expectedValue, value)
}
})
}
}
2 changes: 2 additions & 0 deletions domain/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,6 @@ type RouterConfig struct {
RouteCacheEnabled bool `mapstructure:"route-cache-enabled"`
// The number of seconds to cache routes for before expiry.
RouteCacheExpirySeconds uint64 `mapstructure:"route-cache-expiry-seconds"`
// Flag indicating whether we should have a cache for overwrite routes enabled.
EnableOverwriteRoutesCache bool `mapstructure:"enable-overwrite-routes-cache"`
}
Loading

0 comments on commit fa414f7

Please sign in to comment.