chore: add method to return cached config value (#1944)

* chore: add method to return cached config value

* fix: add check for relay urls when starting NWC wallet service

* fix: mocks

* chore: always use cache for config entries
This commit is contained in:
Roland 2025-11-29 11:24:27 +07:00 committed by GitHub
parent db1167030c
commit d12ed10c67
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 121 additions and 93 deletions

View file

@ -8,6 +8,7 @@ import (
"os"
"path"
"strings"
"sync"
"github.com/getAlby/hub/constants"
"github.com/getAlby/hub/db"
@ -18,8 +19,10 @@ import (
)
type config struct {
Env *AppConfig
db *gorm.DB
Env *AppConfig
db *gorm.DB
cache map[string]string
cacheMutex sync.Mutex
}
const (
@ -28,7 +31,8 @@ const (
func NewConfig(env *AppConfig, db *gorm.DB) (*config, error) {
cfg := &config{
db: db,
db: db,
cache: map[string]string{},
}
err := cfg.init(env)
if err != nil {
@ -177,7 +181,22 @@ func (cfg *config) GetMempoolUrl() string {
}
func (cfg *config) Get(key string, encryptionKey string) (string, error) {
return cfg.get(key, encryptionKey, cfg.db)
cfg.cacheMutex.Lock()
defer cfg.cacheMutex.Unlock()
cachedValue, ok := cfg.cache[key]
if ok {
logger.Logger.WithField("key", key).Debug("hit config cache")
return cachedValue, nil
}
logger.Logger.WithField("key", key).Debug("missed config cache")
value, err := cfg.get(key, encryptionKey, cfg.db)
if err != nil {
return "", err
}
cfg.cache[key] = value
logger.Logger.WithField("key", key).Debug("set config cache")
return value, nil
}
func (cfg *config) get(key string, encryptionKey string, gormDB *gorm.DB) (string, error) {
@ -212,6 +231,12 @@ func (cfg *config) set(key string, value string, clauses clause.OnConflict, encr
if result.Error != nil {
return fmt.Errorf("failed to save key to config: %v", result.Error)
}
logger.Logger.WithField("key", key).Debug("clearing config cache")
cfg.cacheMutex.Lock()
defer cfg.cacheMutex.Unlock()
delete(cfg.cache, key)
return nil
}

View file

@ -30,6 +30,9 @@ import (
func (svc *service) startNostr(ctx context.Context) error {
relayUrls := svc.cfg.GetRelayUrls()
if len(relayUrls) == 0 {
return errors.New("No relay URLs found")
}
npub, err := nip19.EncodePublicKey(svc.keys.GetNostrPublicKey())
if err != nil {

View file

@ -182,6 +182,50 @@ func (_c *MockConfig_Get_Call) RunAndReturn(run func(key string, encryptionKey s
return _c
}
// GetBitcoinDisplayFormat provides a mock function for the type MockConfig
func (_mock *MockConfig) GetBitcoinDisplayFormat() string {
ret := _mock.Called()
if len(ret) == 0 {
panic("no return value specified for GetBitcoinDisplayFormat")
}
var r0 string
if returnFunc, ok := ret.Get(0).(func() string); ok {
r0 = returnFunc()
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// MockConfig_GetBitcoinDisplayFormat_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBitcoinDisplayFormat'
type MockConfig_GetBitcoinDisplayFormat_Call struct {
*mock.Call
}
// GetBitcoinDisplayFormat is a helper method to define mock.On call
func (_e *MockConfig_Expecter) GetBitcoinDisplayFormat() *MockConfig_GetBitcoinDisplayFormat_Call {
return &MockConfig_GetBitcoinDisplayFormat_Call{Call: _e.mock.On("GetBitcoinDisplayFormat")}
}
func (_c *MockConfig_GetBitcoinDisplayFormat_Call) Run(run func()) *MockConfig_GetBitcoinDisplayFormat_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockConfig_GetBitcoinDisplayFormat_Call) Return(s string) *MockConfig_GetBitcoinDisplayFormat_Call {
_c.Call.Return(s)
return _c
}
func (_c *MockConfig_GetBitcoinDisplayFormat_Call) RunAndReturn(run func() string) *MockConfig_GetBitcoinDisplayFormat_Call {
_c.Call.Return(run)
return _c
}
// GetCurrency provides a mock function for the type MockConfig
func (_mock *MockConfig) GetCurrency() string {
ret := _mock.Called()
@ -540,6 +584,51 @@ func (_c *MockConfig_SetAutoUnlockPassword_Call) RunAndReturn(run func(unlockPas
return _c
}
// SetBitcoinDisplayFormat provides a mock function for the type MockConfig
func (_mock *MockConfig) SetBitcoinDisplayFormat(value string) error {
ret := _mock.Called(value)
if len(ret) == 0 {
panic("no return value specified for SetBitcoinDisplayFormat")
}
var r0 error
if returnFunc, ok := ret.Get(0).(func(string) error); ok {
r0 = returnFunc(value)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockConfig_SetBitcoinDisplayFormat_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetBitcoinDisplayFormat'
type MockConfig_SetBitcoinDisplayFormat_Call struct {
*mock.Call
}
// SetBitcoinDisplayFormat is a helper method to define mock.On call
// - value
func (_e *MockConfig_Expecter) SetBitcoinDisplayFormat(value interface{}) *MockConfig_SetBitcoinDisplayFormat_Call {
return &MockConfig_SetBitcoinDisplayFormat_Call{Call: _e.mock.On("SetBitcoinDisplayFormat", value)}
}
func (_c *MockConfig_SetBitcoinDisplayFormat_Call) Run(run func(value string)) *MockConfig_SetBitcoinDisplayFormat_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(string))
})
return _c
}
func (_c *MockConfig_SetBitcoinDisplayFormat_Call) Return(err error) *MockConfig_SetBitcoinDisplayFormat_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockConfig_SetBitcoinDisplayFormat_Call) RunAndReturn(run func(value string) error) *MockConfig_SetBitcoinDisplayFormat_Call {
_c.Call.Return(run)
return _c
}
// SetCurrency provides a mock function for the type MockConfig
func (_mock *MockConfig) SetCurrency(value string) error {
ret := _mock.Called(value)
@ -722,92 +811,3 @@ func (_c *MockConfig_SetupCompleted_Call) RunAndReturn(run func() bool) *MockCon
_c.Call.Return(run)
return _c
}
// GetBitcoinDisplayFormat provides a mock function for the type MockConfig
func (_mock *MockConfig) GetBitcoinDisplayFormat() string {
ret := _mock.Called()
if len(ret) == 0 {
panic("no return value specified for GetBitcoinDisplayFormat")
}
var r0 string
if returnFunc, ok := ret.Get(0).(func() string); ok {
r0 = returnFunc()
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// MockConfig_GetBitcoinDisplayFormat_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBitcoinDisplayFormat'
type MockConfig_GetBitcoinDisplayFormat_Call struct {
*mock.Call
}
// GetBitcoinDisplayFormat is a helper method to define mock.On call
func (_e *MockConfig_Expecter) GetBitcoinDisplayFormat() *MockConfig_GetBitcoinDisplayFormat_Call {
return &MockConfig_GetBitcoinDisplayFormat_Call{Call: _e.mock.On("GetBitcoinDisplayFormat")}
}
func (_c *MockConfig_GetBitcoinDisplayFormat_Call) Run(run func()) *MockConfig_GetBitcoinDisplayFormat_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockConfig_GetBitcoinDisplayFormat_Call) Return(s string) *MockConfig_GetBitcoinDisplayFormat_Call {
_c.Call.Return(s)
return _c
}
func (_c *MockConfig_GetBitcoinDisplayFormat_Call) RunAndReturn(run func() string) *MockConfig_GetBitcoinDisplayFormat_Call {
_c.Call.Return(run)
return _c
}
// SetBitcoinDisplayFormat provides a mock function for the type MockConfig
func (_mock *MockConfig) SetBitcoinDisplayFormat(value string) error {
ret := _mock.Called(value)
if len(ret) == 0 {
panic("no return value specified for SetBitcoinDisplayFormat")
}
var r0 error
if returnFunc, ok := ret.Get(0).(func(string) error); ok {
r0 = returnFunc(value)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockConfig_SetBitcoinDisplayFormat_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetBitcoinDisplayFormat'
type MockConfig_SetBitcoinDisplayFormat_Call struct {
*mock.Call
}
// SetBitcoinDisplayFormat is a helper method to define mock.On call
// - value
func (_e *MockConfig_Expecter) SetBitcoinDisplayFormat(value interface{}) *MockConfig_SetBitcoinDisplayFormat_Call {
return &MockConfig_SetBitcoinDisplayFormat_Call{Call: _e.mock.On("SetBitcoinDisplayFormat", value)}
}
func (_c *MockConfig_SetBitcoinDisplayFormat_Call) Run(run func(value string)) *MockConfig_SetBitcoinDisplayFormat_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(string))
})
return _c
}
func (_c *MockConfig_SetBitcoinDisplayFormat_Call) Return(err error) *MockConfig_SetBitcoinDisplayFormat_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockConfig_SetBitcoinDisplayFormat_Call) RunAndReturn(run func(value string) error) *MockConfig_SetBitcoinDisplayFormat_Call {
_c.Call.Return(run)
return _c
}