using System.Net; using ArcaneLibs.Extensions; namespace SafeNSound.FakeUser; public class MonitorService(ILogger logger, UserStore userStore) : IHostedService { private Task? _getAllAlarmsTask, _assignBudgetTask, _getAlarmForRandomUserTask, _rotateMonitoredUsersTask; private readonly CancellationTokenSource _cts = new(); public async Task StartAsync(CancellationToken cancellationToken) { _getAllAlarmsTask = GetAllAlarms(_cts.Token); _assignBudgetTask = AssignBudget(_cts.Token); _getAlarmForRandomUserTask = GetAlarmForRandomUser(_cts.Token); _rotateMonitoredUsersTask = RotateMonitoredUsers(_cts.Token); } private async Task GetAllAlarms(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { var user = userStore.GetRandomMonitor(); var alarms = await user.Client!.GetAllAlarms(); if (alarms.Count > 0) { logger.LogInformation("Monitor {UserId} has outstanding alarms: {Alarm}", user.Auth.Username, alarms.ToJson(indent: false)); await user.Client!.GetAlarm(alarms.Keys.First()); await user.Client!.DeleteAlarm(alarms.Keys.First()); } await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); } catch (Exception ex) { logger.LogError(ex, "Error querying alarm list"); } } } private async Task GetAlarmForRandomUser(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { var user = userStore.GetRandomMonitor(); var watchedUserIds = await user.Client!.GetAssignedUsers(); if (watchedUserIds.Count == 0) { logger.LogInformation("Monitor {UserId} has no assigned users", user.Auth.Username); continue; } await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); } catch (Exception ex) { logger.LogError(ex, "Error querying alarm for user"); } } } private async Task RotateMonitoredUsers(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { var user = userStore.GetRandomMonitor(); var watchedUserIds = (await user.Client!.GetAssignedUsers()).ToArray(); if (watchedUserIds.Length == 0) { logger.LogInformation("Monitor {UserId} has no assigned users", user.Auth.Username); } else { var idToRemove = Random.Shared.GetItems(watchedUserIds, 1).First(); await user.Client!.RemoveAssignedUser(idToRemove); } string idToAdd; do { idToAdd = userStore.GetRandomUserOfAnyType().WhoAmI!.UserId; } while (watchedUserIds.Contains(idToAdd)); await user.Client!.AddAssignedUser(idToAdd); await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); } catch (Exception ex) { logger.LogError(ex, "Error rotating monitored users"); } } } private async Task AssignBudget(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { var user = userStore.GetRandomMonitor(); var monitoredUsers = (await user.Client!.GetAssignedUsers()).ToArray(); if (monitoredUsers.Length == 0) { logger.LogInformation("Monitor {UserId} has no assigned users", user.Auth.Username); continue; } var userId = Random.Shared.GetItems(monitoredUsers, 1).First(); var budget = Random.Shared.NextDouble(); await user.Client!.GetBudget(userId); await user.Client!.AddBudget(userId, new() { Amount = budget, Reason = "Random budget assignment", Venue = "FakeUser" }); await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); } catch (Exception ex) { logger.LogError(ex, "Error assigning budget"); } } } public async Task StopAsync(CancellationToken cancellationToken) { await _cts.CancelAsync(); await _getAllAlarmsTask!; await _assignBudgetTask!; await _getAlarmForRandomUserTask!; await _rotateMonitoredUsersTask!; } }