Refresh Rate anpassbar, Containerübersicht wird nicht mehr überschrieben

This commit is contained in:
2025-11-16 23:53:58 +01:00
parent 6429489f80
commit 8a753ca9ba
15 changed files with 84 additions and 26 deletions

View File

@@ -21,12 +21,16 @@ namespace Watcher.Controllers
// Daten der Backgroundchecks abrufen
private IDashboardStore _DashboardStore;
// System Store für Konfigurationen
private ISystemStore _SystemStore;
// HomeController Constructor
public HomeController(AppDbContext context, ILogger<HomeController> logger, IDashboardStore dashboardStore)
public HomeController(AppDbContext context, ILogger<HomeController> logger, IDashboardStore dashboardStore, ISystemStore systemStore)
{
_context = context;
_logger = logger;
_DashboardStore = dashboardStore;
_SystemStore = systemStore;
}
@@ -59,7 +63,8 @@ namespace Watcher.Controllers
.OrderBy(s => s.Name)
.ToListAsync(),
NetworkStatus = _DashboardStore.NetworkStatus,
DatabaseStatus = _DashboardStore.DatabaseStatus
DatabaseStatus = _DashboardStore.DatabaseStatus,
RefreshIntervalMilliseconds = _SystemStore.FrontendRefreshIntervalMilliseconds
};
//ViewBag.NetworkConnection = _NetworkCheckStore.NetworkStatus;
return View(viewModel);

View File

@@ -280,9 +280,18 @@ public class MonitoringController : Controller
foreach (Container c in newContainers)
{
// Überprüfen, ob ein übergebener Container bereits für den Host registriert ist
if (existingContainers.Contains(c))
// Wichtig: Vergleich über ContainerId, nicht über Objektreferenz!
var existingContainer = existingContainers
.FirstOrDefault(ec => ec.ContainerId == c.ContainerId);
if (existingContainer != null)
{
_logger.LogInformation("Container with id " + c.ContainerId + " already exists.");
// Container existiert bereits, nur Daten aktualisieren falls sich etwas geändert hat
existingContainer.Name = c.Name;
existingContainer.Image = c.Image;
existingContainer.IsRunning = true;
_logger.LogInformation("Container '{containerName}' (ID: {containerId}) already exists for Server {serverId}, updated.", c.Name, c.ContainerId, dto.Server_id);
}
// Container auf einen Host/Server registrieren
else
@@ -292,11 +301,11 @@ public class MonitoringController : Controller
{
_context.Containers.Add(c);
await _context.SaveChangesAsync();
_logger.LogInformation(c.Name + " added for Host " + c.ServerId);
_logger.LogInformation("Container '{containerName}' (ID: {containerId}) added for Server {serverId}", c.Name, c.ContainerId, c.ServerId);
}
catch (SqliteException e)
{
_logger.LogError("Error writing new Containers to Database: " + e.Message);
_logger.LogError("Error writing new Container '{containerName}' to Database: {error}", c.Name, e.Message);
}
}
}
@@ -305,19 +314,26 @@ public class MonitoringController : Controller
foreach (Container c in existingContainers)
{
// Abfrage, ob bereits vorhandener Container im Payload vorhanden war
if (!newContainers.Contains(c))
// Wichtig: Vergleich über ContainerId, nicht über Objektreferenz!
var stillRunning = newContainers
.Any(nc => nc.ContainerId == c.ContainerId);
if (!stillRunning)
{
// Container entfernen
_context.Containers.Remove(c);
await _context.SaveChangesAsync();
// Metrics für den Container entfernen
//Todo
//Todo
_logger.LogInformation("Container " + c.Name + " (" + c.Id + ") on Host-Id " + c.ServerId + " was successfully removed from the database.");
_logger.LogInformation("Container '{containerName}' (DB-ID: {id}, ContainerID: {containerId}) on Server {serverId} was removed from the database.", c.Name, c.Id, c.ContainerId, c.ServerId);
}
}
// Alle Änderungen in einem Batch speichern
await _context.SaveChangesAsync();
return Ok();
}

View File

@@ -4,6 +4,7 @@ using Microsoft.EntityFrameworkCore;
using Watcher.Data;
using Watcher.Models;
using Watcher.ViewModels;
using Watcher.Services;
[Authorize]
[Route("[controller]")]
@@ -13,11 +14,14 @@ public class ServerController : Controller
private readonly ILogger<ServerController> _logger;
private readonly ISystemStore _systemStore;
public ServerController(AppDbContext context, ILogger<ServerController> logger)
public ServerController(AppDbContext context, ILogger<ServerController> logger, ISystemStore systemStore)
{
_context = context;
_logger = logger;
_systemStore = systemStore;
}
@@ -26,7 +30,8 @@ public class ServerController : Controller
{
var vm = new ServerOverviewViewModel
{
Servers = await _context.Servers.OrderBy(s => s.Id).ToListAsync()
Servers = await _context.Servers.OrderBy(s => s.Id).ToListAsync(),
RefreshIntervalMilliseconds = _systemStore.FrontendRefreshIntervalMilliseconds
};
return View(vm);
@@ -159,7 +164,8 @@ public class ServerController : Controller
CreatedAt = s.CreatedAt,
IsOnline = s.IsOnline,
LastSeen = s.LastSeen,
IsVerified = s.IsVerified
IsVerified = s.IsVerified,
RefreshIntervalMilliseconds = _systemStore.FrontendRefreshIntervalMilliseconds
};
return View(vm);
@@ -177,6 +183,7 @@ public class ServerController : Controller
await _context.SaveChangesAsync();
}
ViewBag.RefreshIntervalMilliseconds = _systemStore.FrontendRefreshIntervalMilliseconds;
return PartialView("_ServerCard", servers);
}

View File

@@ -34,10 +34,24 @@ builder.Services.AddHttpContextAccessor();
// Storage Singleton
builder.Services.AddSingleton<IDashboardStore, DashboardStore>();
builder.Services.AddSingleton<ISystemStore, SystemStore>();
builder.Services.AddSingleton<IVersionService, VersionService>();
builder.Services.AddSingleton<IUpdateCheckStore, UpdateCheckStore>();
// SystemStore mit Konfiguration initialisieren
builder.Services.AddSingleton<ISystemStore>(sp =>
{
var configuration = sp.GetRequiredService<IConfiguration>();
var refreshIntervalSeconds = int.TryParse(
configuration["Frontend:RefreshIntervalSeconds"]
?? Environment.GetEnvironmentVariable("FRONTEND_REFRESH_INTERVAL_SECONDS"),
out var seconds) ? seconds : 30;
return new SystemStore
{
FrontendRefreshIntervalMilliseconds = refreshIntervalSeconds * 1000
};
});
// Background Services
builder.Services.AddHostedService<NetworkCheck>();
builder.Services.AddHostedService<DatabaseCheck>();

View File

@@ -6,4 +6,6 @@ public interface ISystemStore
Double DatabaseSize { get; set; }
int FrontendRefreshIntervalMilliseconds { get; set; }
}

View File

@@ -6,4 +6,6 @@ public class SystemStore: ISystemStore
public Double DatabaseSize { get; set; }
public int FrontendRefreshIntervalMilliseconds { get; set; }
}

View File

@@ -17,5 +17,7 @@ namespace Watcher.ViewModels
public String? NetworkStatus { get; set; } = "?";
public String? DatabaseStatus { get; set; } = "?";
public int RefreshIntervalMilliseconds { get; set; } = 30000;
}
}

View File

@@ -36,4 +36,6 @@ public class ServerDetailsViewModel
public DateTime LastSeen { get; set; }
public Boolean IsVerified { get; set; } = false;
public int RefreshIntervalMilliseconds { get; set; } = 30000;
}

View File

@@ -6,5 +6,6 @@ namespace Watcher.ViewModels
public class ServerOverviewViewModel
{
public List<Server> Servers { get; set; } = new();
public int RefreshIntervalMilliseconds { get; set; } = 30000;
}
}

View File

@@ -31,8 +31,8 @@
}
}
// Initial laden und dann alle 30 Sekunden
// Initial laden und dann mit konfiguriertem Intervall
loadDashboardStats();
setInterval(loadDashboardStats, 30000);
setInterval(loadDashboardStats, @Model.RefreshIntervalMilliseconds);
</script>
}

View File

@@ -480,10 +480,10 @@
loadRamData();
loadGpuData();
// Alle 30 Sekunden aktualisieren
setInterval(loadCpuData, 30000);
setInterval(loadRamData, 30000);
setInterval(loadGpuData, 30000);
// Mit konfiguriertem Intervall aktualisieren
setInterval(loadCpuData, @Model.RefreshIntervalMilliseconds);
setInterval(loadRamData, @Model.RefreshIntervalMilliseconds);
setInterval(loadGpuData, @Model.RefreshIntervalMilliseconds);
});
</script>
}

View File

@@ -163,7 +163,8 @@
}
}
// Initial laden und alle 30 Sekunden aktualisieren
// Initial laden und mit konfiguriertem Intervall aktualisieren
loadCurrentMetrics();
setInterval(loadCurrentMetrics, 30000);
const refreshInterval = @(ViewBag.RefreshIntervalMilliseconds ?? 30000);
setInterval(loadCurrentMetrics, refreshInterval);
</script>

View File

@@ -44,8 +44,8 @@
}
}
// Initial laden und dann alle 30 Sekunden
// Initial laden und dann mit konfiguriertem Intervall
loadServerCards();
setInterval(loadServerCards, 30000);
setInterval(loadServerCards, @Model.RefreshIntervalMilliseconds);
</script>
}

View File

@@ -12,5 +12,9 @@
"ConnectionStrings": {
"Sqlite": "Data Source=./persistence/watcher.db"
}
},
"Frontend": {
"RefreshIntervalSeconds": 30
}
}

View File

@@ -18,9 +18,11 @@ services:
- METRIC_RETENTION_DAYS=30
- METRIC_CLEANUP_INTERVAL_HOURS=24
- METRIC_CLEANUP_ENABLED=true
# Aktualisierungsrate Frontend
- FRONTEND_REFRESH_INTERVAL_SECONDS=30
ports:
- "5000:5000"
volumes:
- ./watcher-volumes/data:/app/persistence
- ./watcher-volumes/dumps:/app/wwwroot/downloads/sqlite
- ./watcher-volumes/logs:/app/logs
- ./data/db:/app/persistence
- ./data/dumps:/app/wwwroot/downloads/sqlite
- ./data/logs:/app/logs