Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions src/NetworkOptimizer.Storage/Repositories/CmRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ public async Task SaveCmConfigurationAsync(CmConfiguration config, CancellationT
existing.Username = config.Username;
existing.Password = config.Password;
existing.StatusPagePath = config.StatusPagePath;
existing.Enabled = config.Enabled;
existing.PollingIntervalSeconds = config.PollingIntervalSeconds;
existing.LastPolled = config.LastPolled;
existing.LastError = config.LastError;
Expand Down Expand Up @@ -154,19 +153,20 @@ public async Task<bool> UpdateCmPollResultAsync(int id, DateTime? lastPolled, st
{
try
{
var config = await _context.CmConfigurations.FirstOrDefaultAsync(c => c.Id == id, cancellationToken);
// Never resurrect or overwrite a config that was disabled while the poll was
// in flight - its frozen state (and cleared LastError) must stand.
if (config == null || !config.Enabled)
return false;

var now = DateTime.UtcNow;
int rows;
if (lastPolled.HasValue)
config.LastPolled = lastPolled.Value;
config.LastError = lastError;
config.UpdatedAt = DateTime.UtcNow;

await _context.SaveChangesAsync(cancellationToken);
return true;
rows = await _context.CmConfigurations.Where(c => c.Id == id && c.Enabled)
.ExecuteUpdateAsync(s => s
.SetProperty(c => c.LastPolled, lastPolled.Value)
.SetProperty(c => c.LastError, lastError)
.SetProperty(c => c.UpdatedAt, now), cancellationToken);
else
rows = await _context.CmConfigurations.Where(c => c.Id == id && c.Enabled)
.ExecuteUpdateAsync(s => s
.SetProperty(c => c.LastError, lastError)
.SetProperty(c => c.UpdatedAt, now), cancellationToken);
return rows > 0;
}
catch (Exception ex)
{
Expand Down
26 changes: 13 additions & 13 deletions src/NetworkOptimizer.Storage/Repositories/ModemRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ public async Task SaveModemConfigurationAsync(ModemConfiguration config, Cancell
existing.ModemType = config.ModemType;
existing.QmiDevice = config.QmiDevice;
existing.Provider = config.Provider;
existing.Enabled = config.Enabled;
existing.PollingIntervalSeconds = config.PollingIntervalSeconds;
existing.LastPolled = config.LastPolled;
existing.LastError = config.LastError;
Expand Down Expand Up @@ -182,19 +181,20 @@ public async Task<bool> UpdateModemPollResultAsync(int id, DateTime? lastPolled,
{
try
{
var config = await _context.ModemConfigurations.FirstOrDefaultAsync(m => m.Id == id, cancellationToken);
// Never resurrect or overwrite a config that was disabled while the poll was
// in flight - its frozen state (and cleared LastError) must stand.
if (config == null || !config.Enabled)
return false;

var now = DateTime.UtcNow;
int rows;
if (lastPolled.HasValue)
config.LastPolled = lastPolled.Value;
config.LastError = lastError;
config.UpdatedAt = DateTime.UtcNow;

await _context.SaveChangesAsync(cancellationToken);
return true;
rows = await _context.ModemConfigurations.Where(m => m.Id == id && m.Enabled)
.ExecuteUpdateAsync(s => s
.SetProperty(m => m.LastPolled, lastPolled.Value)
.SetProperty(m => m.LastError, lastError)
.SetProperty(m => m.UpdatedAt, now), cancellationToken);
else
rows = await _context.ModemConfigurations.Where(m => m.Id == id && m.Enabled)
.ExecuteUpdateAsync(s => s
.SetProperty(m => m.LastError, lastError)
.SetProperty(m => m.UpdatedAt, now), cancellationToken);
return rows > 0;
}
catch (Exception ex)
{
Expand Down
26 changes: 13 additions & 13 deletions src/NetworkOptimizer.Storage/Repositories/OntRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ public async Task SaveOntConfigurationAsync(OntConfiguration config, Cancellatio
existing.Password = config.Password;
existing.PrivateKeyPath = config.PrivateKeyPath;
existing.AttachedSfpId = config.AttachedSfpId;
existing.Enabled = config.Enabled;
existing.PollingIntervalSeconds = config.PollingIntervalSeconds;
existing.LastPolled = config.LastPolled;
existing.LastError = config.LastError;
Expand Down Expand Up @@ -155,19 +154,20 @@ public async Task<bool> UpdateOntPollResultAsync(int id, DateTime? lastPolled, s
{
try
{
var config = await _context.OntConfigurations.FirstOrDefaultAsync(o => o.Id == id, cancellationToken);
// Never resurrect or overwrite a config that was disabled while the poll was
// in flight - its frozen state (and cleared LastError) must stand.
if (config == null || !config.Enabled)
return false;

var now = DateTime.UtcNow;
int rows;
if (lastPolled.HasValue)
config.LastPolled = lastPolled.Value;
config.LastError = lastError;
config.UpdatedAt = DateTime.UtcNow;

await _context.SaveChangesAsync(cancellationToken);
return true;
rows = await _context.OntConfigurations.Where(o => o.Id == id && o.Enabled)
.ExecuteUpdateAsync(s => s
.SetProperty(o => o.LastPolled, lastPolled.Value)
.SetProperty(o => o.LastError, lastError)
.SetProperty(o => o.UpdatedAt, now), cancellationToken);
else
rows = await _context.OntConfigurations.Where(o => o.Id == id && o.Enabled)
.ExecuteUpdateAsync(s => s
.SetProperty(o => o.LastError, lastError)
.SetProperty(o => o.UpdatedAt, now), cancellationToken);
return rows > 0;
}
catch (Exception ex)
{
Expand Down
28 changes: 16 additions & 12 deletions src/NetworkOptimizer.Storage/Repositories/StarlinkRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ public async Task SaveStarlinkConfigurationAsync(StarlinkConfiguration config, C
existing.Provider = config.Provider;
existing.Host = config.Host;
existing.Port = config.Port;
existing.Enabled = config.Enabled;
existing.PollingIntervalSeconds = config.PollingIntervalSeconds;
existing.LastPolled = config.LastPolled;
existing.LastError = config.LastError;
Expand Down Expand Up @@ -132,19 +131,24 @@ public async Task<bool> UpdateStarlinkPollResultAsync(int id, DateTime? lastPoll
{
try
{
var config = await _context.StarlinkConfigurations.FirstOrDefaultAsync(c => c.Id == id, cancellationToken);
// Never resurrect or overwrite a config that was disabled while the poll was
// in flight - its frozen state (and cleared LastError) must stand.
if (config == null || !config.Enabled)
return false;

// in flight - its frozen state (and cleared LastError) must stand. Check and
// write in one conditional statement so a Disable committing in between
// cannot slip through.
var now = DateTime.UtcNow;
int rows;
if (lastPolled.HasValue)
config.LastPolled = lastPolled.Value;
config.LastError = lastError;
config.UpdatedAt = DateTime.UtcNow;

await _context.SaveChangesAsync(cancellationToken);
return true;
rows = await _context.StarlinkConfigurations.Where(c => c.Id == id && c.Enabled)
.ExecuteUpdateAsync(s => s
.SetProperty(c => c.LastPolled, lastPolled.Value)
.SetProperty(c => c.LastError, lastError)
.SetProperty(c => c.UpdatedAt, now), cancellationToken);
else
rows = await _context.StarlinkConfigurations.Where(c => c.Id == id && c.Enabled)
.ExecuteUpdateAsync(s => s
.SetProperty(c => c.LastError, lastError)
.SetProperty(c => c.UpdatedAt, now), cancellationToken);
return rows > 0;
}
catch (Exception ex)
{
Expand Down
27 changes: 0 additions & 27 deletions src/NetworkOptimizer.Web/Components/Pages/Settings.razor
Original file line number Diff line number Diff line change
Expand Up @@ -1236,12 +1236,6 @@
}
}

<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" @bind="editingModem.Enabled" />
<span>Enable polling</span>
</label>
</div>
}

<div class="action-buttons">
Expand Down Expand Up @@ -1438,13 +1432,6 @@
</div>
</div>

<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" @bind="_editingCm.Enabled" />
<span>Enable polling</span>
</label>
</div>

<div class="action-buttons">
<button class="btn btn-primary" @onclick="SaveCm" disabled="@_savingCm">
@if (_savingCm)
Expand Down Expand Up @@ -1663,13 +1650,6 @@
</div>
</div>

<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" @bind="_editingOnt.Enabled" />
<span>Enable polling</span>
</label>
</div>

<div class="action-buttons">
<button class="btn btn-primary" @onclick="SaveOnt" disabled="@_savingOnt">
@if (_savingOnt)
Expand Down Expand Up @@ -1845,13 +1825,6 @@
</div>
</div>

<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" @bind="_editingStarlink.Enabled" />
<span>Enable polling</span>
</label>
</div>

<div class="action-buttons">
<button class="btn btn-primary" @onclick="SaveStarlink" disabled="@_savingStarlink">
@if (_savingStarlink)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@
{
modemStats = cachedStats;
}
else
else if (modem.Enabled)
{
// No cached stats - do initial poll
var (success, _) = await ModemService.PollModemAsync(modem);
Expand Down Expand Up @@ -580,7 +580,7 @@
modemStats = cached;
StateHasChanged();

if (cached == null)
if (cached == null && modem.Enabled)
{
// No cached stats - try polling, but don't block paging
var (success, _) = await ModemService.PollModemAsync(modem);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ public async Task PollCmAsync(int cmId)
_logger.LogWarning("PollCmAsync called for unknown CM config {Id}", cmId);
return;
}
if (!config.Enabled)
{
_logger.LogDebug("PollCmAsync skipped for disabled CM config {Id}", cmId);
return;
}

await PollSingleAsync(config);
}
Expand Down Expand Up @@ -331,7 +336,7 @@ private async Task<bool> UpdateConfigSuccessAsync(int id)
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to update CM config {Id} after successful poll", id);
return false;
throw;
}
}

Expand Down
10 changes: 9 additions & 1 deletion src/NetworkOptimizer.Web/Services/CellularModemService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,14 @@ private async Task<ModemPollContext> ToPollContextAsync(ModemConfiguration modem
{
try
{
using (var scope = CreateSiteScope())
{
var repository = scope.ServiceProvider.GetRequiredService<IModemRepository>();
var current = await repository.GetModemConfigurationAsync(modem.Id);
if (current == null || !current.Enabled)
return (false, "Modem is disabled - enable it to resume polling.");
}

var stats = await ExecutePollAsync(modem);

if (stats != null)
Expand Down Expand Up @@ -420,7 +428,7 @@ private async Task<bool> UpdateModemConfigAsync(int modemId, string? error, bool
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to update modem config after poll");
return false;
throw;
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/NetworkOptimizer.Web/Services/OntMonitorService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ public async Task<List<OntConfiguration>> GetStandaloneConfigsAsync()
_logger.LogWarning("Cannot poll ONT {Id}: configuration not found", ontId);
return null;
}
if (!config.Enabled)
{
_logger.LogDebug("Cannot poll ONT {Id}: configuration is disabled", ontId);
return null;
}

return await PollSingleAsync(config, repository, await ResolveThresholdsAsync(scope));
}
Expand Down
9 changes: 8 additions & 1 deletion src/NetworkOptimizer.Web/Services/StarlinkMonitorService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ public async Task PollStarlinkAsync(int id)
_logger.LogWarning("PollStarlinkAsync called for unknown Starlink config {Id}", id);
return;
}
if (!config.Enabled)
{
_logger.LogDebug("PollStarlinkAsync skipped for disabled Starlink config {Id}", id);
return;
}

await PollSingleAsync(config);
}
Expand Down Expand Up @@ -318,6 +323,8 @@ private async Task<StarlinkPollContext> ToContextAsync(StarlinkConfiguration con
/// <summary>
/// Guarded success write - returns false (and persists nothing) when the config was
/// disabled while the poll was in flight, so callers can skip caching/Influx too.
/// A write failure is rethrown rather than reported as that same false, so it
/// surfaces on the poll error path instead of silently dropping valid stats.
/// </summary>
private async Task<bool> UpdateConfigSuccessAsync(int id)
{
Expand All @@ -330,7 +337,7 @@ private async Task<bool> UpdateConfigSuccessAsync(int id)
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to update Starlink config {Id} after successful poll", id);
return false;
throw;
}
}

Expand Down
Loading