feat: send settings event when a setting is set through the API

This commit is contained in:
Dario Gabriel Lipicar 2023-10-09 16:31:47 -03:00 committed by dlipicar
parent c2ff377585
commit 6d19e165d9
6 changed files with 131 additions and 2 deletions

View File

@ -16,6 +16,8 @@ import (
"github.com/status-im/status-go/sqlite"
)
type Notifier func(SettingField, interface{})
var (
// dbInstances holds a map of singleton instances of Database
dbInstances map[string]*Database
@ -28,6 +30,7 @@ var (
type Database struct {
db *sql.DB
SyncQueue chan SyncSettingField
notifier Notifier
}
// 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
}
// Set a notifier for setting changes
func (db *Database) SetSettingsNotifier(n Notifier) {
db.notifier = n
}
// TODO remove photoPath from settings
func (db *Database) CreateSettings(s Settings, n params.NodeConfig) error {
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)
return err
if err != nil {
return err
}
if db.notifier != nil {
db.notifier(setting, value)
}
return nil
}
func (db *Database) parseSaveAndSyncSetting(sf SettingField, value interface{}) (err error) {

View File

@ -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
type Settings struct {
// required

View File

@ -22,9 +22,11 @@ import (
"github.com/status-im/status-go/logutils"
"github.com/status-im/status-go/mailserver"
"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/rpc"
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"
"github.com/status-im/status-go/services/browsers"
"github.com/status-im/status-go/services/chat"
@ -65,10 +67,12 @@ var (
func (b *StatusNode) initServices(config *params.NodeConfig, mediaServer *server.MediaServer) error {
accountsFeed := &event.Feed{}
settingsFeed := &event.Feed{}
accDB, err := accounts.NewDB(b.appDB)
if err != nil {
return err
}
setSettingsNotifier(accDB, settingsFeed)
services := []common.StatusService{}
services = appendIf(config.UpstreamConfig.Enabled, services, b.rpcFiltersService())
@ -342,6 +346,16 @@ func (b *StatusNode) wakuV2Service(nodeConfig *params.NodeConfig, telemetryServe
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 {
enodes := append(
parseNodes(clusterCfg.StaticNodes),

View File

@ -29,7 +29,12 @@ func (api *SettingsAPI) SaveSetting(ctx context.Context, typ string, val interfa
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) {

View File

@ -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"
)

View File

@ -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)
}
}
}
}