feat: send settings event when a setting is set through the API
This commit is contained in:
parent
c2ff377585
commit
6d19e165d9
|
@ -16,6 +16,8 @@ import (
|
||||||
"github.com/status-im/status-go/sqlite"
|
"github.com/status-im/status-go/sqlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Notifier func(SettingField, interface{})
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// dbInstances holds a map of singleton instances of Database
|
// dbInstances holds a map of singleton instances of Database
|
||||||
dbInstances map[string]*Database
|
dbInstances map[string]*Database
|
||||||
|
@ -28,6 +30,7 @@ var (
|
||||||
type Database struct {
|
type Database struct {
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
SyncQueue chan SyncSettingField
|
SyncQueue chan SyncSettingField
|
||||||
|
notifier Notifier
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeNewDB ensures that a singleton instance of Database is returned per sqlite db file
|
// MakeNewDB ensures that a singleton instance of Database is returned per sqlite db file
|
||||||
|
@ -70,6 +73,11 @@ func MakeNewDB(db *sql.DB) (*Database, error) {
|
||||||
return dbInstances[filename], nil
|
return dbInstances[filename], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set a notifier for setting changes
|
||||||
|
func (db *Database) SetSettingsNotifier(n Notifier) {
|
||||||
|
db.notifier = n
|
||||||
|
}
|
||||||
|
|
||||||
// TODO remove photoPath from settings
|
// TODO remove photoPath from settings
|
||||||
func (db *Database) CreateSettings(s Settings, n params.NodeConfig) error {
|
func (db *Database) CreateSettings(s Settings, n params.NodeConfig) error {
|
||||||
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
|
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
|
||||||
|
@ -196,7 +204,16 @@ func (db *Database) saveSetting(setting SettingField, value interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = update.Exec(value)
|
_, err = update.Exec(value)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if db.notifier != nil {
|
||||||
|
db.notifier(setting, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *Database) parseSaveAndSyncSetting(sf SettingField, value interface{}) (err error) {
|
func (db *Database) parseSaveAndSyncSetting(sf SettingField, value interface{}) (err error) {
|
||||||
|
|
|
@ -109,6 +109,10 @@ func (s SettingField) CanSync(source SyncSource) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s SettingField) Equals(other SettingField) bool {
|
||||||
|
return s.reactFieldName == other.reactFieldName
|
||||||
|
}
|
||||||
|
|
||||||
// Settings represents the entire setting row stored in the application db
|
// Settings represents the entire setting row stored in the application db
|
||||||
type Settings struct {
|
type Settings struct {
|
||||||
// required
|
// required
|
||||||
|
|
|
@ -22,9 +22,11 @@ import (
|
||||||
"github.com/status-im/status-go/logutils"
|
"github.com/status-im/status-go/logutils"
|
||||||
"github.com/status-im/status-go/mailserver"
|
"github.com/status-im/status-go/mailserver"
|
||||||
"github.com/status-im/status-go/multiaccounts/accounts"
|
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||||
|
"github.com/status-im/status-go/multiaccounts/settings"
|
||||||
"github.com/status-im/status-go/params"
|
"github.com/status-im/status-go/params"
|
||||||
"github.com/status-im/status-go/rpc"
|
"github.com/status-im/status-go/rpc"
|
||||||
accountssvc "github.com/status-im/status-go/services/accounts"
|
accountssvc "github.com/status-im/status-go/services/accounts"
|
||||||
|
"github.com/status-im/status-go/services/accounts/settingsevent"
|
||||||
appmetricsservice "github.com/status-im/status-go/services/appmetrics"
|
appmetricsservice "github.com/status-im/status-go/services/appmetrics"
|
||||||
"github.com/status-im/status-go/services/browsers"
|
"github.com/status-im/status-go/services/browsers"
|
||||||
"github.com/status-im/status-go/services/chat"
|
"github.com/status-im/status-go/services/chat"
|
||||||
|
@ -65,10 +67,12 @@ var (
|
||||||
|
|
||||||
func (b *StatusNode) initServices(config *params.NodeConfig, mediaServer *server.MediaServer) error {
|
func (b *StatusNode) initServices(config *params.NodeConfig, mediaServer *server.MediaServer) error {
|
||||||
accountsFeed := &event.Feed{}
|
accountsFeed := &event.Feed{}
|
||||||
|
settingsFeed := &event.Feed{}
|
||||||
accDB, err := accounts.NewDB(b.appDB)
|
accDB, err := accounts.NewDB(b.appDB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
setSettingsNotifier(accDB, settingsFeed)
|
||||||
|
|
||||||
services := []common.StatusService{}
|
services := []common.StatusService{}
|
||||||
services = appendIf(config.UpstreamConfig.Enabled, services, b.rpcFiltersService())
|
services = appendIf(config.UpstreamConfig.Enabled, services, b.rpcFiltersService())
|
||||||
|
@ -342,6 +346,16 @@ func (b *StatusNode) wakuV2Service(nodeConfig *params.NodeConfig, telemetryServe
|
||||||
return b.wakuV2Srvc, nil
|
return b.wakuV2Srvc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setSettingsNotifier(db *accounts.Database, feed *event.Feed) {
|
||||||
|
db.SetSettingsNotifier(func(setting settings.SettingField, val interface{}) {
|
||||||
|
feed.Send(settingsevent.Event{
|
||||||
|
Type: settingsevent.EventTypeChanged,
|
||||||
|
Setting: setting,
|
||||||
|
Value: val,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func wakuRateLimiter(wakuCfg *params.WakuConfig, clusterCfg *params.ClusterConfig) *wakucommon.PeerRateLimiter {
|
func wakuRateLimiter(wakuCfg *params.WakuConfig, clusterCfg *params.ClusterConfig) *wakucommon.PeerRateLimiter {
|
||||||
enodes := append(
|
enodes := append(
|
||||||
parseNodes(clusterCfg.StaticNodes),
|
parseNodes(clusterCfg.StaticNodes),
|
||||||
|
|
|
@ -29,7 +29,12 @@ func (api *SettingsAPI) SaveSetting(ctx context.Context, typ string, val interfa
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return api.db.SaveSetting(typ, val)
|
err := api.db.SaveSetting(typ, val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *SettingsAPI) GetSettings(ctx context.Context) (settings.Settings, error) {
|
func (api *SettingsAPI) GetSettings(ctx context.Context) (settings.Settings, error) {
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package settingsevent
|
||||||
|
|
||||||
|
import "github.com/status-im/status-go/multiaccounts/settings"
|
||||||
|
|
||||||
|
// EventType type for event types.
|
||||||
|
type EventType string
|
||||||
|
|
||||||
|
// Event is a type for accounts events.
|
||||||
|
type Event struct {
|
||||||
|
Type EventType `json:"type"`
|
||||||
|
Setting settings.SettingField `json:"setting"`
|
||||||
|
Value interface{} `json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
EventTypeChanged EventType = "changed"
|
||||||
|
)
|
|
@ -0,0 +1,72 @@
|
||||||
|
package settingsevent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/status-im/status-go/multiaccounts/settings"
|
||||||
|
"github.com/status-im/status-go/services/wallet/async"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SettingChangeCb func(setting settings.SettingField, value interface{})
|
||||||
|
|
||||||
|
// Watcher executes a given callback whenever an account gets added/removed
|
||||||
|
type Watcher struct {
|
||||||
|
feed *event.Feed
|
||||||
|
group *async.Group
|
||||||
|
callback SettingChangeCb
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWatcher(feed *event.Feed, callback SettingChangeCb) *Watcher {
|
||||||
|
return &Watcher{
|
||||||
|
feed: feed,
|
||||||
|
callback: callback,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Watcher) Start() {
|
||||||
|
if w.group != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.group = async.NewGroup(context.Background())
|
||||||
|
w.group.Add(func(ctx context.Context) error {
|
||||||
|
return watch(ctx, w.feed, w.callback)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Watcher) Stop() {
|
||||||
|
if w.group != nil {
|
||||||
|
w.group.Stop()
|
||||||
|
w.group.Wait()
|
||||||
|
w.group = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func onSettingChanged(callback SettingChangeCb, setting settings.SettingField, value interface{}) {
|
||||||
|
if callback != nil {
|
||||||
|
callback(setting, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func watch(ctx context.Context, feed *event.Feed, callback SettingChangeCb) error {
|
||||||
|
ch := make(chan Event, 1)
|
||||||
|
sub := feed.Subscribe(ch)
|
||||||
|
defer sub.Unsubscribe()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return nil
|
||||||
|
case err := <-sub.Err():
|
||||||
|
if err != nil {
|
||||||
|
log.Error("settings watcher subscription failed", "error", err)
|
||||||
|
}
|
||||||
|
case ev := <-ch:
|
||||||
|
if ev.Type == EventTypeChanged {
|
||||||
|
onSettingChanged(callback, ev.Setting, ev.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue