From ca4bc6cb5c20066397a9461d49429e61eaeddf53 Mon Sep 17 00:00:00 2001 From: Stefan Pletka <124689083+Eisei24@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:28:44 +0200 Subject: [PATCH 01/11] Implemented notifications setting get method --- backend/pkg/api/data_access/notifications.go | 177 ++++++++++++++++++- 1 file changed, 176 insertions(+), 1 deletion(-) diff --git a/backend/pkg/api/data_access/notifications.go b/backend/pkg/api/data_access/notifications.go index 5389847db..b85384764 100644 --- a/backend/pkg/api/data_access/notifications.go +++ b/backend/pkg/api/data_access/notifications.go @@ -2,9 +2,16 @@ package dataaccess import ( "context" + "database/sql" + "fmt" + "strings" + "time" "github.com/gobitfly/beaconchain/pkg/api/enums" t "github.com/gobitfly/beaconchain/pkg/api/types" + "github.com/gobitfly/beaconchain/pkg/commons/types" + "github.com/shopspring/decimal" + "golang.org/x/sync/errgroup" ) type NotificationsRepository interface { @@ -58,7 +65,175 @@ func (d *DataAccessService) GetNetworkNotifications(ctx context.Context, userId return d.dummy.GetNetworkNotifications(ctx, userId, cursor, colSort, search, limit) } func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId uint64) (*t.NotificationSettings, error) { - return d.dummy.GetNotificationSettings(ctx, userId) + result := &t.NotificationSettings{} + + wg := errgroup.Group{} + + networks, err := d.GetAllNetworks() + if err != nil { + return nil, err + } + + chainIds := make(map[string]uint64, len(networks)) + for _, network := range networks { + chainIds[network.Name] = network.ChainId + } + + // ------------------------------------- + // Get the "do not disturb" setting + var doNotDisturbTimestamp sql.NullTime + wg.Go(func() error { + err := d.userReader.GetContext(ctx, &doNotDisturbTimestamp, ` + SELECT + notifications_do_not_disturb_ts + FROM users + WHERE id = $1`, userId) + if err != nil { + return fmt.Errorf(`error retrieving data for notifications "do not disturb" setting: %w`, err) + } + + return nil + }) + + // ------------------------------------- + // Get the notification channels + notificationChannels := []struct { + Channel types.NotificationChannel `db:"channel"` + Active bool `db:"active"` + }{} + wg.Go(func() error { + err := d.userReader.SelectContext(ctx, ¬ificationChannels, ` + SELECT + channel, + active + FROM users_notification_channels + WHERE user_id = $1`, userId) + if err != nil { + return fmt.Errorf(`error retrieving data for notifications channels: %w`, err) + } + + return nil + }) + + // ------------------------------------- + // Get the subscribed events + subscribedEvents := []struct { + Name types.EventName `db:"event_name"` + Filter string `db:"event_filter"` + Threshold decimal.Decimal `db:"event_threshold"` + }{} + wg.Go(func() error { + err := d.userReader.SelectContext(ctx, &subscribedEvents, ` + SELECT + event_name, + event_filter, + event_threshold + FROM users_subscriptions + WHERE user_id = $1`, userId) + if err != nil { + return fmt.Errorf(`error retrieving data for notifications subscribed events: %w`, err) + } + + return nil + }) + + // ------------------------------------- + // Get the paired devices + pairedDevices := []struct { + DeviceIdentifier string `db:"device_identifier"` + CreatedTs time.Time `db:"created_ts"` + DeviceName string `db:"device_name"` + NotifyEnabled bool `db:"notify_enabled"` + }{} + wg.Go(func() error { + err := d.userReader.SelectContext(ctx, &pairedDevices, ` + SELECT + device_identifier, + created_ts, + device_name, + notify_enabled + FROM users_devices + WHERE user_id = $1`, userId) + if err != nil { + return fmt.Errorf(`error retrieving data for notifications paired devices: %w`, err) + } + + return nil + }) + + err = wg.Wait() + if err != nil { + return nil, err + } + + // ------------------------------------- + // Fill the result + if doNotDisturbTimestamp.Valid { + result.GeneralSettings.DoNotDisturbTimestamp = doNotDisturbTimestamp.Time.Unix() + } + for _, channel := range notificationChannels { + if channel.Channel == types.EmailNotificationChannel { + result.GeneralSettings.IsEmailNotificationsEnabled = channel.Active + } else if channel.Channel == types.PushNotificationChannel { + result.GeneralSettings.IsPushNotificationsEnabled = channel.Active + } + } + networkEvents := make(map[string]*t.NotificationSettingsNetwork) + for _, event := range subscribedEvents { + switch event.Name { + case types.MonitoringMachineOfflineEventName: + result.GeneralSettings.IsMachineOfflineSubscribed = true + case types.MonitoringMachineDiskAlmostFullEventName: + result.GeneralSettings.MachineStorageUsageThreshold = event.Threshold.InexactFloat64() + case types.MonitoringMachineCpuLoadEventName: + result.GeneralSettings.MachineCpuUsageThreshold = event.Threshold.InexactFloat64() + case types.MonitoringMachineMemoryUsageEventName: + result.GeneralSettings.MachineMemoryUsageThreshold = event.Threshold.InexactFloat64() + case types.EthClientUpdateEventName: + result.GeneralSettings.SubscribedClients = append(result.GeneralSettings.SubscribedClients, event.Filter) + case types.RocketpoolNewClaimRoundStartedEventName: + result.GeneralSettings.IsRocketPoolNewRewardRoundSubscribed = true + case types.RocketpoolCollateralMaxReached: + result.GeneralSettings.RocketPoolMaxCollateralThreshold = event.Threshold.InexactFloat64() + case types.RocketpoolCollateralMinReached: + result.GeneralSettings.RocketPoolMinCollateralThreshold = event.Threshold.InexactFloat64() + } + + eventSplit := strings.Split(string(event.Name), ":") + networkName := eventSplit[0] + networkEvent := eventSplit[1] + + if _, ok := networkEvents[networkName]; !ok { + networkEvents[networkName] = &t.NotificationSettingsNetwork{} + } + switch networkEvent { + case types.NetworkGasAboveThresholdEventName: + networkEvents[networkName].GasAboveThreshold = event.Threshold + case types.NetworkGasBelowThresholdEventName: + networkEvents[networkName].GasBelowThreshold = event.Threshold + case types.NetworkParticipationRateThresholdEventName: + networkEvents[networkName].ParticipationRateThreshold = event.Threshold.InexactFloat64() + } + } + + for network, settings := range networkEvents { + result.Networks = append(result.Networks, t.NotificationNetwork{ + ChainId: chainIds[network], + Settings: *settings, + }) + + } + + for _, device := range pairedDevices { + result.PairedDevices = append(result.PairedDevices, t.NotificationPairedDevice{ + Id: device.DeviceIdentifier, + PairedTimestamp: device.CreatedTs.Unix(), + Name: device.DeviceName, + IsNotificationsEnabled: device.NotifyEnabled, + }) + } + + return result, nil } func (d *DataAccessService) UpdateNotificationSettingsGeneral(ctx context.Context, userId uint64, settings t.NotificationSettingsGeneral) error { return d.dummy.UpdateNotificationSettingsGeneral(ctx, userId, settings) From 7e3cbcdc247531bc6526a7e17d2c5e69602a73ef Mon Sep 17 00:00:00 2001 From: Stefan Pletka <124689083+Eisei24@users.noreply.github.com> Date: Thu, 19 Sep 2024 13:01:49 +0200 Subject: [PATCH 02/11] Adjusted to new struct --- backend/pkg/api/data_access/notifications.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/pkg/api/data_access/notifications.go b/backend/pkg/api/data_access/notifications.go index b85384764..b299d75a9 100644 --- a/backend/pkg/api/data_access/notifications.go +++ b/backend/pkg/api/data_access/notifications.go @@ -184,18 +184,23 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId case types.MonitoringMachineOfflineEventName: result.GeneralSettings.IsMachineOfflineSubscribed = true case types.MonitoringMachineDiskAlmostFullEventName: + result.GeneralSettings.IsMachineStorageUsageSubscribed = true result.GeneralSettings.MachineStorageUsageThreshold = event.Threshold.InexactFloat64() case types.MonitoringMachineCpuLoadEventName: + result.GeneralSettings.IsMachineCpuUsageSubscribed = true result.GeneralSettings.MachineCpuUsageThreshold = event.Threshold.InexactFloat64() case types.MonitoringMachineMemoryUsageEventName: + result.GeneralSettings.IsMachineMemoryUsageSubscribed = true result.GeneralSettings.MachineMemoryUsageThreshold = event.Threshold.InexactFloat64() case types.EthClientUpdateEventName: result.GeneralSettings.SubscribedClients = append(result.GeneralSettings.SubscribedClients, event.Filter) case types.RocketpoolNewClaimRoundStartedEventName: result.GeneralSettings.IsRocketPoolNewRewardRoundSubscribed = true case types.RocketpoolCollateralMaxReached: + result.GeneralSettings.IsRocketPoolMaxCollateralSubscribed = true result.GeneralSettings.RocketPoolMaxCollateralThreshold = event.Threshold.InexactFloat64() case types.RocketpoolCollateralMinReached: + result.GeneralSettings.IsRocketPoolMinCollateralSubscribed = true result.GeneralSettings.RocketPoolMinCollateralThreshold = event.Threshold.InexactFloat64() } From 5267052f7df2a81ea83e5868bcb46d47e899a297 Mon Sep 17 00:00:00 2001 From: Stefan Pletka <124689083+Eisei24@users.noreply.github.com> Date: Thu, 19 Sep 2024 14:17:49 +0200 Subject: [PATCH 03/11] Adjusted to new struct --- backend/pkg/api/data_access/notifications.go | 78 +++++++++++--------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/backend/pkg/api/data_access/notifications.go b/backend/pkg/api/data_access/notifications.go index b299d75a9..88e69cde8 100644 --- a/backend/pkg/api/data_access/notifications.go +++ b/backend/pkg/api/data_access/notifications.go @@ -180,44 +180,50 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId } networkEvents := make(map[string]*t.NotificationSettingsNetwork) for _, event := range subscribedEvents { - switch event.Name { - case types.MonitoringMachineOfflineEventName: - result.GeneralSettings.IsMachineOfflineSubscribed = true - case types.MonitoringMachineDiskAlmostFullEventName: - result.GeneralSettings.IsMachineStorageUsageSubscribed = true - result.GeneralSettings.MachineStorageUsageThreshold = event.Threshold.InexactFloat64() - case types.MonitoringMachineCpuLoadEventName: - result.GeneralSettings.IsMachineCpuUsageSubscribed = true - result.GeneralSettings.MachineCpuUsageThreshold = event.Threshold.InexactFloat64() - case types.MonitoringMachineMemoryUsageEventName: - result.GeneralSettings.IsMachineMemoryUsageSubscribed = true - result.GeneralSettings.MachineMemoryUsageThreshold = event.Threshold.InexactFloat64() - case types.EthClientUpdateEventName: - result.GeneralSettings.SubscribedClients = append(result.GeneralSettings.SubscribedClients, event.Filter) - case types.RocketpoolNewClaimRoundStartedEventName: - result.GeneralSettings.IsRocketPoolNewRewardRoundSubscribed = true - case types.RocketpoolCollateralMaxReached: - result.GeneralSettings.IsRocketPoolMaxCollateralSubscribed = true - result.GeneralSettings.RocketPoolMaxCollateralThreshold = event.Threshold.InexactFloat64() - case types.RocketpoolCollateralMinReached: - result.GeneralSettings.IsRocketPoolMinCollateralSubscribed = true - result.GeneralSettings.RocketPoolMinCollateralThreshold = event.Threshold.InexactFloat64() - } - eventSplit := strings.Split(string(event.Name), ":") - networkName := eventSplit[0] - networkEvent := eventSplit[1] - if _, ok := networkEvents[networkName]; !ok { - networkEvents[networkName] = &t.NotificationSettingsNetwork{} - } - switch networkEvent { - case types.NetworkGasAboveThresholdEventName: - networkEvents[networkName].GasAboveThreshold = event.Threshold - case types.NetworkGasBelowThresholdEventName: - networkEvents[networkName].GasBelowThreshold = event.Threshold - case types.NetworkParticipationRateThresholdEventName: - networkEvents[networkName].ParticipationRateThreshold = event.Threshold.InexactFloat64() + if len(eventSplit) == 2 { + networkName := eventSplit[0] + networkEvent := types.EventName(eventSplit[1]) + + if _, ok := networkEvents[networkName]; !ok { + networkEvents[networkName] = &t.NotificationSettingsNetwork{} + } + switch networkEvent { + case types.RocketpoolNewClaimRoundStartedEventName: + result.GeneralSettings.IsRocketPoolNewRewardRoundSubscribed = true + case types.RocketpoolCollateralMaxReached: + result.GeneralSettings.IsRocketPoolMaxCollateralSubscribed = true + result.GeneralSettings.RocketPoolMaxCollateralThreshold = event.Threshold.InexactFloat64() + case types.RocketpoolCollateralMinReached: + result.GeneralSettings.IsRocketPoolMinCollateralSubscribed = true + result.GeneralSettings.RocketPoolMinCollateralThreshold = event.Threshold.InexactFloat64() + case types.NetworkGasAboveThresholdEventName: + networkEvents[networkName].IsGasAboveSubscribed = true + networkEvents[networkName].GasAboveThreshold = event.Threshold + case types.NetworkGasBelowThresholdEventName: + networkEvents[networkName].IsGasBelowSubscribed = true + networkEvents[networkName].GasBelowThreshold = event.Threshold + case types.NetworkParticipationRateThresholdEventName: + networkEvents[networkName].IsParticipationRateSubscribed = true + networkEvents[networkName].ParticipationRateThreshold = event.Threshold.InexactFloat64() + } + } else { + switch event.Name { + case types.MonitoringMachineOfflineEventName: + result.GeneralSettings.IsMachineOfflineSubscribed = true + case types.MonitoringMachineDiskAlmostFullEventName: + result.GeneralSettings.IsMachineStorageUsageSubscribed = true + result.GeneralSettings.MachineStorageUsageThreshold = event.Threshold.InexactFloat64() + case types.MonitoringMachineCpuLoadEventName: + result.GeneralSettings.IsMachineCpuUsageSubscribed = true + result.GeneralSettings.MachineCpuUsageThreshold = event.Threshold.InexactFloat64() + case types.MonitoringMachineMemoryUsageEventName: + result.GeneralSettings.IsMachineMemoryUsageSubscribed = true + result.GeneralSettings.MachineMemoryUsageThreshold = event.Threshold.InexactFloat64() + case types.EthClientUpdateEventName: + result.GeneralSettings.SubscribedClients = append(result.GeneralSettings.SubscribedClients, event.Filter) + } } } From f107666b4bee699b365710e9ae4ef05640730371 Mon Sep 17 00:00:00 2001 From: Stefan Pletka <124689083+Eisei24@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:53:18 +0200 Subject: [PATCH 04/11] Changed threshold type from decimal to float --- backend/pkg/api/data_access/notifications.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/backend/pkg/api/data_access/notifications.go b/backend/pkg/api/data_access/notifications.go index 88e69cde8..331345194 100644 --- a/backend/pkg/api/data_access/notifications.go +++ b/backend/pkg/api/data_access/notifications.go @@ -120,7 +120,7 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId subscribedEvents := []struct { Name types.EventName `db:"event_name"` Filter string `db:"event_filter"` - Threshold decimal.Decimal `db:"event_threshold"` + Threshold float64 `db:"event_threshold"` }{} wg.Go(func() error { err := d.userReader.SelectContext(ctx, &subscribedEvents, ` @@ -194,19 +194,19 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId result.GeneralSettings.IsRocketPoolNewRewardRoundSubscribed = true case types.RocketpoolCollateralMaxReached: result.GeneralSettings.IsRocketPoolMaxCollateralSubscribed = true - result.GeneralSettings.RocketPoolMaxCollateralThreshold = event.Threshold.InexactFloat64() + result.GeneralSettings.RocketPoolMaxCollateralThreshold = event.Threshold case types.RocketpoolCollateralMinReached: result.GeneralSettings.IsRocketPoolMinCollateralSubscribed = true - result.GeneralSettings.RocketPoolMinCollateralThreshold = event.Threshold.InexactFloat64() + result.GeneralSettings.RocketPoolMinCollateralThreshold = event.Threshold case types.NetworkGasAboveThresholdEventName: networkEvents[networkName].IsGasAboveSubscribed = true - networkEvents[networkName].GasAboveThreshold = event.Threshold + networkEvents[networkName].GasAboveThreshold = decimal.NewFromFloat(event.Threshold).Mul(decimal.NewFromInt(1e9)) case types.NetworkGasBelowThresholdEventName: networkEvents[networkName].IsGasBelowSubscribed = true - networkEvents[networkName].GasBelowThreshold = event.Threshold + networkEvents[networkName].GasBelowThreshold = decimal.NewFromFloat(event.Threshold).Mul(decimal.NewFromInt(1e9)) case types.NetworkParticipationRateThresholdEventName: networkEvents[networkName].IsParticipationRateSubscribed = true - networkEvents[networkName].ParticipationRateThreshold = event.Threshold.InexactFloat64() + networkEvents[networkName].ParticipationRateThreshold = event.Threshold } } else { switch event.Name { @@ -214,13 +214,13 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId result.GeneralSettings.IsMachineOfflineSubscribed = true case types.MonitoringMachineDiskAlmostFullEventName: result.GeneralSettings.IsMachineStorageUsageSubscribed = true - result.GeneralSettings.MachineStorageUsageThreshold = event.Threshold.InexactFloat64() + result.GeneralSettings.MachineStorageUsageThreshold = event.Threshold case types.MonitoringMachineCpuLoadEventName: result.GeneralSettings.IsMachineCpuUsageSubscribed = true - result.GeneralSettings.MachineCpuUsageThreshold = event.Threshold.InexactFloat64() + result.GeneralSettings.MachineCpuUsageThreshold = event.Threshold case types.MonitoringMachineMemoryUsageEventName: result.GeneralSettings.IsMachineMemoryUsageSubscribed = true - result.GeneralSettings.MachineMemoryUsageThreshold = event.Threshold.InexactFloat64() + result.GeneralSettings.MachineMemoryUsageThreshold = event.Threshold case types.EthClientUpdateEventName: result.GeneralSettings.SubscribedClients = append(result.GeneralSettings.SubscribedClients, event.Filter) } From 7725426da50eb453ca00ad150ec4f34aef644b2b Mon Sep 17 00:00:00 2001 From: Stefan Pletka <124689083+Eisei24@users.noreply.github.com> Date: Wed, 25 Sep 2024 11:59:24 +0200 Subject: [PATCH 05/11] Set default values for thresholds --- backend/pkg/api/data_access/notifications.go | 61 ++++++++++++++------ 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/backend/pkg/api/data_access/notifications.go b/backend/pkg/api/data_access/notifications.go index 331345194..6f6a5afc8 100644 --- a/backend/pkg/api/data_access/notifications.go +++ b/backend/pkg/api/data_access/notifications.go @@ -7,6 +7,7 @@ import ( "strings" "time" + "github.com/ethereum/go-ethereum/params" "github.com/gobitfly/beaconchain/pkg/api/enums" t "github.com/gobitfly/beaconchain/pkg/api/types" "github.com/gobitfly/beaconchain/pkg/commons/types" @@ -37,6 +38,18 @@ type NotificationsRepository interface { UpdateNotificationSettingsAccountDashboard(ctx context.Context, dashboardId t.VDBIdPrimary, groupId uint64, settings t.NotificationSettingsAccountDashboard) error } +const ( + MachineStorageUsageThresholdDefault float64 = 0.1 + MachineCpuUsageThresholdDefault float64 = 0.2 + MachineMemoryUsageThresholdDefault float64 = 0.3 + RocketPoolMaxCollateralThresholdDefault float64 = 0.4 + RocketPoolMinCollateralThresholdDefault float64 = 0.5 + + GasAboveThresholdDefault float64 = 1000.0001 + GasBelowThresholdDefault float64 = 1000.0002 + ParticipationRateThresholdDefault float64 = 0.6 +) + func (d *DataAccessService) GetNotificationOverview(ctx context.Context, userId uint64) (*t.NotificationOverviewData, error) { return d.dummy.GetNotificationOverview(ctx, userId) } @@ -65,18 +78,35 @@ func (d *DataAccessService) GetNetworkNotifications(ctx context.Context, userId return d.dummy.GetNetworkNotifications(ctx, userId, cursor, colSort, search, limit) } func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId uint64) (*t.NotificationSettings, error) { - result := &t.NotificationSettings{} - wg := errgroup.Group{} + // ------------------------------------- + // Create the default settings + result := &t.NotificationSettings{ + GeneralSettings: t.NotificationSettingsGeneral{ + MachineStorageUsageThreshold: MachineStorageUsageThresholdDefault, + MachineCpuUsageThreshold: MachineCpuUsageThresholdDefault, + MachineMemoryUsageThreshold: MachineMemoryUsageThresholdDefault, + RocketPoolMaxCollateralThreshold: RocketPoolMaxCollateralThresholdDefault, + RocketPoolMinCollateralThreshold: RocketPoolMinCollateralThresholdDefault, + }, + } + networks, err := d.GetAllNetworks() if err != nil { return nil, err } - chainIds := make(map[string]uint64, len(networks)) + networksSettings := make(map[string]*t.NotificationNetwork, len(networks)) for _, network := range networks { - chainIds[network.Name] = network.ChainId + networksSettings[network.Name] = &t.NotificationNetwork{ + ChainId: network.ChainId, + Settings: t.NotificationSettingsNetwork{ + GasAboveThreshold: decimal.NewFromFloat(GasAboveThresholdDefault).Mul(decimal.NewFromInt(params.GWei)), + GasBelowThreshold: decimal.NewFromFloat(GasBelowThresholdDefault).Mul(decimal.NewFromInt(params.GWei)), + ParticipationRateThreshold: ParticipationRateThresholdDefault, + }, + } } // ------------------------------------- @@ -178,7 +208,6 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId result.GeneralSettings.IsPushNotificationsEnabled = channel.Active } } - networkEvents := make(map[string]*t.NotificationSettingsNetwork) for _, event := range subscribedEvents { eventSplit := strings.Split(string(event.Name), ":") @@ -186,9 +215,6 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId networkName := eventSplit[0] networkEvent := types.EventName(eventSplit[1]) - if _, ok := networkEvents[networkName]; !ok { - networkEvents[networkName] = &t.NotificationSettingsNetwork{} - } switch networkEvent { case types.RocketpoolNewClaimRoundStartedEventName: result.GeneralSettings.IsRocketPoolNewRewardRoundSubscribed = true @@ -199,14 +225,14 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId result.GeneralSettings.IsRocketPoolMinCollateralSubscribed = true result.GeneralSettings.RocketPoolMinCollateralThreshold = event.Threshold case types.NetworkGasAboveThresholdEventName: - networkEvents[networkName].IsGasAboveSubscribed = true - networkEvents[networkName].GasAboveThreshold = decimal.NewFromFloat(event.Threshold).Mul(decimal.NewFromInt(1e9)) + networksSettings[networkName].Settings.IsGasAboveSubscribed = true + networksSettings[networkName].Settings.GasAboveThreshold = decimal.NewFromFloat(event.Threshold).Mul(decimal.NewFromInt(params.GWei)) case types.NetworkGasBelowThresholdEventName: - networkEvents[networkName].IsGasBelowSubscribed = true - networkEvents[networkName].GasBelowThreshold = decimal.NewFromFloat(event.Threshold).Mul(decimal.NewFromInt(1e9)) + networksSettings[networkName].Settings.IsGasBelowSubscribed = true + networksSettings[networkName].Settings.GasBelowThreshold = decimal.NewFromFloat(event.Threshold).Mul(decimal.NewFromInt(params.GWei)) case types.NetworkParticipationRateThresholdEventName: - networkEvents[networkName].IsParticipationRateSubscribed = true - networkEvents[networkName].ParticipationRateThreshold = event.Threshold + networksSettings[networkName].Settings.IsParticipationRateSubscribed = true + networksSettings[networkName].Settings.ParticipationRateThreshold = event.Threshold } } else { switch event.Name { @@ -227,11 +253,8 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId } } - for network, settings := range networkEvents { - result.Networks = append(result.Networks, t.NotificationNetwork{ - ChainId: chainIds[network], - Settings: *settings, - }) + for _, settings := range networksSettings { + result.Networks = append(result.Networks, *settings) } From 9dcfda7d0c4cb4212a3307f2c4316b9fdb4e4cb7 Mon Sep 17 00:00:00 2001 From: Stefan Pletka <124689083+Eisei24@users.noreply.github.com> Date: Tue, 1 Oct 2024 15:43:34 +0200 Subject: [PATCH 06/11] Adjusted to new settings structure --- backend/pkg/api/data_access/clients.go | 78 ++++++++++++++++++++ backend/pkg/api/data_access/data_access.go | 1 + backend/pkg/api/data_access/notifications.go | 39 ++++++---- backend/pkg/api/types/data_access.go | 6 ++ 4 files changed, 110 insertions(+), 14 deletions(-) create mode 100644 backend/pkg/api/data_access/clients.go diff --git a/backend/pkg/api/data_access/clients.go b/backend/pkg/api/data_access/clients.go new file mode 100644 index 000000000..a92a3e5f0 --- /dev/null +++ b/backend/pkg/api/data_access/clients.go @@ -0,0 +1,78 @@ +package dataaccess + +import "github.com/gobitfly/beaconchain/pkg/api/types" + +type ClientRepository interface { + GetAllClients() ([]types.ClientInfo, error) +} + +func (d *DataAccessService) GetAllClients() ([]types.ClientInfo, error) { + // TODO @recy21 + // probably should load the clients into mem from some config when the service is created + + return []types.ClientInfo{ + // Execution Clients + { + Id: 0, + Name: "Geth", + Category: "Execution Clients", + }, + { + Id: 1, + Name: "Nethermind", + Category: "Execution Clients", + }, + { + Id: 2, + Name: "Besu", + Category: "Execution Clients", + }, + { + Id: 3, + Name: "Erigon", + Category: "Execution Clients", + }, + { + Id: 4, + Name: "Reth", + Category: "Execution Clients", + }, + // Consensus Clients + { + Id: 5, + Name: "Teku", + Category: "Consensus Clients", + }, + { + Id: 6, + Name: "Prysm", + Category: "Consensus Clients", + }, + { + Id: 7, + Name: "Nimbus", + Category: "Consensus Clients", + }, + { + Id: 8, + Name: "Lighthouse", + Category: "Consensus Clients", + }, + { + Id: 9, + Name: "Lodestar", + Category: "Consensus Clients", + }, + // Other + { + Id: 10, + Name: "Rocketpool Smart Node", + Category: "Other", + }, + { + Id: 11, + Name: "MEV-Boost", + Category: "Other", + }, + }, nil +} diff --git a/backend/pkg/api/data_access/data_access.go b/backend/pkg/api/data_access/data_access.go index 047d471a6..6c1ff1a0e 100644 --- a/backend/pkg/api/data_access/data_access.go +++ b/backend/pkg/api/data_access/data_access.go @@ -21,6 +21,7 @@ type DataAccessor interface { ValidatorDashboardRepository SearchRepository NetworkRepository + ClientRepository UserRepository AppRepository NotificationsRepository diff --git a/backend/pkg/api/data_access/notifications.go b/backend/pkg/api/data_access/notifications.go index aee02b2fb..fafb31795 100644 --- a/backend/pkg/api/data_access/notifications.go +++ b/backend/pkg/api/data_access/notifications.go @@ -85,19 +85,17 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId // Create the default settings result := &t.NotificationSettings{ GeneralSettings: t.NotificationSettingsGeneral{ - MachineStorageUsageThreshold: MachineStorageUsageThresholdDefault, - MachineCpuUsageThreshold: MachineCpuUsageThresholdDefault, - MachineMemoryUsageThreshold: MachineMemoryUsageThresholdDefault, - RocketPoolMaxCollateralThreshold: RocketPoolMaxCollateralThresholdDefault, - RocketPoolMinCollateralThreshold: RocketPoolMinCollateralThresholdDefault, + MachineStorageUsageThreshold: MachineStorageUsageThresholdDefault, + MachineCpuUsageThreshold: MachineCpuUsageThresholdDefault, + MachineMemoryUsageThreshold: MachineMemoryUsageThresholdDefault, }, } + // For networks networks, err := d.GetAllNetworks() if err != nil { return nil, err } - networksSettings := make(map[string]*t.NotificationNetwork, len(networks)) for _, network := range networks { networksSettings[network.Name] = &t.NotificationNetwork{ @@ -110,6 +108,20 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId } } + // For clients + clients, err := d.GetAllClients() + if err != nil { + return nil, err + } + clientSettings := make(map[string]*t.NotificationSettingsClient, len(clients)) + for _, client := range clients { + clientSettings[client.Name] = &t.NotificationSettingsClient{ + Id: client.Id, + Name: client.Name, + Category: client.Category, + } + } + // ------------------------------------- // Get the "do not disturb" setting var doNotDisturbTimestamp sql.NullTime @@ -209,6 +221,7 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId result.GeneralSettings.IsPushNotificationsEnabled = channel.Active } } + for _, event := range subscribedEvents { eventSplit := strings.Split(string(event.Name), ":") @@ -218,13 +231,7 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId switch networkEvent { case types.RocketpoolNewClaimRoundStartedEventName: - result.GeneralSettings.IsRocketPoolNewRewardRoundSubscribed = true - case types.RocketpoolCollateralMaxReached: - result.GeneralSettings.IsRocketPoolMaxCollateralSubscribed = true - result.GeneralSettings.RocketPoolMaxCollateralThreshold = event.Threshold - case types.RocketpoolCollateralMinReached: - result.GeneralSettings.IsRocketPoolMinCollateralSubscribed = true - result.GeneralSettings.RocketPoolMinCollateralThreshold = event.Threshold + networksSettings[networkName].Settings.IsNewRewardRoundSubscribed = true case types.NetworkGasAboveThresholdEventName: networksSettings[networkName].Settings.IsGasAboveSubscribed = true networksSettings[networkName].Settings.GasAboveThreshold = decimal.NewFromFloat(event.Threshold).Mul(decimal.NewFromInt(params.GWei)) @@ -249,7 +256,7 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId result.GeneralSettings.IsMachineMemoryUsageSubscribed = true result.GeneralSettings.MachineMemoryUsageThreshold = event.Threshold case types.EthClientUpdateEventName: - result.GeneralSettings.SubscribedClients = append(result.GeneralSettings.SubscribedClients, event.Filter) + clientSettings[event.Filter].IsSubscribed = true } } } @@ -268,6 +275,10 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId }) } + for _, settings := range clientSettings { + result.Clients = append(result.Clients, *settings) + } + return result, nil } func (d *DataAccessService) UpdateNotificationSettingsGeneral(ctx context.Context, userId uint64, settings t.NotificationSettingsGeneral) error { diff --git a/backend/pkg/api/types/data_access.go b/backend/pkg/api/types/data_access.go index b24a6b76c..bbabbc435 100644 --- a/backend/pkg/api/types/data_access.go +++ b/backend/pkg/api/types/data_access.go @@ -130,6 +130,12 @@ type NetworkInfo struct { Name string } +type ClientInfo struct { + Id uint64 + Name string + Category string +} + // ------------------------- // validator indices structs, only used between data access and api layer From fd45411b66e59bbd11e6c83776cdea849b722c2e Mon Sep 17 00:00:00 2001 From: Stefan Pletka <124689083+Eisei24@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:56:04 +0200 Subject: [PATCH 07/11] Added the required network events --- backend/pkg/commons/types/frontend.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/pkg/commons/types/frontend.go b/backend/pkg/commons/types/frontend.go index 5a8485c24..b00881235 100644 --- a/backend/pkg/commons/types/frontend.go +++ b/backend/pkg/commons/types/frontend.go @@ -63,6 +63,9 @@ const ( NetworkValidatorExitQueueFullEventName EventName = "network_validator_exit_queue_full" NetworkValidatorExitQueueNotFullEventName EventName = "network_validator_exit_queue_not_full" NetworkLivenessIncreasedEventName EventName = "network_liveness_increased" + NetworkGasAboveThresholdEventName EventName = "network_gas_above_threshold" + NetworkGasBelowThresholdEventName EventName = "network_gas_below_threshold" + NetworkParticipationRateThresholdEventName EventName = "network_participation_rate_threshold" EthClientUpdateEventName EventName = "eth_client_update" MonitoringMachineOfflineEventName EventName = "monitoring_machine_offline" MonitoringMachineDiskAlmostFullEventName EventName = "monitoring_hdd_almostfull" From b4bd27ff271915595d62e7cf05ab8736178bdb26 Mon Sep 17 00:00:00 2001 From: Stefan Pletka <124689083+Eisei24@users.noreply.github.com> Date: Wed, 2 Oct 2024 11:59:13 +0200 Subject: [PATCH 08/11] Check whether the user has machines --- backend/pkg/api/data_access/notifications.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/backend/pkg/api/data_access/notifications.go b/backend/pkg/api/data_access/notifications.go index fafb31795..8c4497e32 100644 --- a/backend/pkg/api/data_access/notifications.go +++ b/backend/pkg/api/data_access/notifications.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/gobitfly/beaconchain/pkg/api/enums" t "github.com/gobitfly/beaconchain/pkg/api/types" + "github.com/gobitfly/beaconchain/pkg/commons/db" "github.com/gobitfly/beaconchain/pkg/commons/types" "github.com/shopspring/decimal" "golang.org/x/sync/errgroup" @@ -204,6 +205,20 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId return nil }) + // ------------------------------------- + // Get the machines + hasMachines := false + wg.Go(func() error { + machineNames, err := db.BigtableClient.GetMachineMetricsMachineNames(types.UserId(userId)) + if err != nil { + return fmt.Errorf(`error retrieving data for notifications machine names: %w`, err) + } + if len(machineNames) > 0 { + hasMachines = true + } + return nil + }) + err = wg.Wait() if err != nil { return nil, err @@ -211,9 +226,11 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId // ------------------------------------- // Fill the result + result.HasMachines = hasMachines if doNotDisturbTimestamp.Valid { result.GeneralSettings.DoNotDisturbTimestamp = doNotDisturbTimestamp.Time.Unix() } + for _, channel := range notificationChannels { if channel.Channel == types.EmailNotificationChannel { result.GeneralSettings.IsEmailNotificationsEnabled = channel.Active From c15ab66d091068d913232f06b43fadc68852f23e Mon Sep 17 00:00:00 2001 From: Stefan Pletka <124689083+Eisei24@users.noreply.github.com> Date: Wed, 2 Oct 2024 12:18:54 +0200 Subject: [PATCH 09/11] Created GetAllClients dummy method --- backend/pkg/api/data_access/dummy.go | 68 ++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/backend/pkg/api/data_access/dummy.go b/backend/pkg/api/data_access/dummy.go index 2d667417b..e292d35a1 100644 --- a/backend/pkg/api/data_access/dummy.go +++ b/backend/pkg/api/data_access/dummy.go @@ -412,6 +412,74 @@ func (d *DummyService) GetAllNetworks() ([]t.NetworkInfo, error) { }, nil } +func (d *DummyService) GetAllClients() ([]types.ClientInfo, error) { + return []types.ClientInfo{ + // Execution Clients + { + Id: 0, + Name: "Geth", + Category: "Execution Clients", + }, + { + Id: 1, + Name: "Nethermind", + Category: "Execution Clients", + }, + { + Id: 2, + Name: "Besu", + Category: "Execution Clients", + }, + { + Id: 3, + Name: "Erigon", + Category: "Execution Clients", + }, + { + Id: 4, + Name: "Reth", + Category: "Execution Clients", + }, + // Consensus Clients + { + Id: 5, + Name: "Teku", + Category: "Consensus Clients", + }, + { + Id: 6, + Name: "Prysm", + Category: "Consensus Clients", + }, + { + Id: 7, + Name: "Nimbus", + Category: "Consensus Clients", + }, + { + Id: 8, + Name: "Lighthouse", + Category: "Consensus Clients", + }, + { + Id: 9, + Name: "Lodestar", + Category: "Consensus Clients", + }, + // Other + { + Id: 10, + Name: "Rocketpool Smart Node", + Category: "Other", + }, + { + Id: 11, + Name: "MEV-Boost", + Category: "Other", + }, + }, nil +} + func (d *DummyService) GetSearchValidatorByIndex(ctx context.Context, chainId, index uint64) (*t.SearchValidator, error) { return getDummyStruct[t.SearchValidator]() } From 1d75d1bc6a4173f8f47083d8aed5e3a30a6e17c8 Mon Sep 17 00:00:00 2001 From: Stefan Pletka <124689083+Eisei24@users.noreply.github.com> Date: Wed, 2 Oct 2024 14:17:39 +0200 Subject: [PATCH 10/11] Set the correct default values --- backend/pkg/api/data_access/notifications.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/backend/pkg/api/data_access/notifications.go b/backend/pkg/api/data_access/notifications.go index 8c4497e32..e802dc317 100644 --- a/backend/pkg/api/data_access/notifications.go +++ b/backend/pkg/api/data_access/notifications.go @@ -41,15 +41,13 @@ type NotificationsRepository interface { } const ( - MachineStorageUsageThresholdDefault float64 = 0.1 - MachineCpuUsageThresholdDefault float64 = 0.2 - MachineMemoryUsageThresholdDefault float64 = 0.3 - RocketPoolMaxCollateralThresholdDefault float64 = 0.4 - RocketPoolMinCollateralThresholdDefault float64 = 0.5 - - GasAboveThresholdDefault float64 = 1000.0001 - GasBelowThresholdDefault float64 = 1000.0002 - ParticipationRateThresholdDefault float64 = 0.6 + MachineStorageUsageThresholdDefault float64 = 0.9 + MachineCpuUsageThresholdDefault float64 = 0.6 + MachineMemoryUsageThresholdDefault float64 = 0.8 + + GasAboveThresholdDefault float64 = 950 + GasBelowThresholdDefault float64 = 150 + ParticipationRateThresholdDefault float64 = 0.8 ) func (d *DataAccessService) GetNotificationOverview(ctx context.Context, userId uint64) (*t.NotificationOverviewData, error) { From 9b87df18854d1e3b09b879faa8653d1327a6a3a9 Mon Sep 17 00:00:00 2001 From: Stefan Pletka <124689083+Eisei24@users.noreply.github.com> Date: Wed, 2 Oct 2024 14:35:59 +0200 Subject: [PATCH 11/11] Fixed lint issue --- backend/pkg/api/data_access/notifications.go | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/pkg/api/data_access/notifications.go b/backend/pkg/api/data_access/notifications.go index e802dc317..5e4959a17 100644 --- a/backend/pkg/api/data_access/notifications.go +++ b/backend/pkg/api/data_access/notifications.go @@ -278,7 +278,6 @@ func (d *DataAccessService) GetNotificationSettings(ctx context.Context, userId for _, settings := range networksSettings { result.Networks = append(result.Networks, *settings) - } for _, device := range pairedDevices {