-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Closed
Labels
needs-area-labelUsed by the dotnet-issue-labeler to label those issues which couldn't be triaged automaticallyUsed by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically
Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
Hello,
For some time now, I've been experiencing an issue where on a specific page in a .NET 8/9 application hosted on a raspberry Pi (self-contained publish for linux-arm64), sometimes when a search happens, the WebSocket connection drops.
This page used to work in the past, nothing has changed on it for it to stop working.
I found this issue:
#58932
- tried disabling response compression on WebSockets and removed it since it was enabled for other stuff as well, did not help the issue
Program.cs
public class Program
{
public static object RESTORE_LOCK = new object();
public static void Main(string[] args)
{
bool afterUpdate = false;
if (UpdateHelper.IsUpdateInProgress())
{
UpdateHelper.FinalizeUpdate();
afterUpdate = true;
}
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseUrls("http://0.0.0.0:5000");
builder.Services.AddRazorComponents().AddInteractiveServerComponents();
builder.Services.Configure<RouteOptions>(options => options.LowercaseUrls = true);
builder.Services.AddDbContextFactory<DataContext>(options =>
{
options.UseNpgsql(builder.Configuration.GetConnectionString("MainDB"));
});
builder.Services.AddAutoMapper(typeof(SettingsProfile));
builder.Services.AddScoped<HubService>();
builder.Services.AddScoped<FileService>();
builder.Services.AddScoped<DeletionService>();
builder.Services.AddScoped<BackupService>();
builder.Services.AddScoped<PsalmService>();
builder.Services.AddScoped<BreviarService>();
builder.Services.AddScoped<SystemService>();
builder.Services.AddHostedService<CleanupHostedService>();
builder.Services.AddHostedService<PsalmHostedService>();
builder.Services.AddHostedService<BreviarHostedService>();
builder.Services.AddControllers();
var configuration = builder.Configuration;
builder.Services.AddLogging(loggingBuilder =>
{
var path = configuration
.GetSection("Logging")
.GetSection("File")
.GetValue<string>("Path");
var fileName =
path + "/app_{0:yyyy}-{0:MM}-{0:dd}_" + Process.GetCurrentProcess().Id + ".log";
loggingBuilder.AddFile(
fileName,
fileLoggerOpts =>
{
fileLoggerOpts.FormatLogFileName = fName =>
{
return string.Format(fName, DateTime.Now);
};
fileLoggerOpts.MinLevel = LogLevel.Information;
}
);
});
var app = builder.Build();
using (var scope = app.Services.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<DataContext>();
if (afterUpdate)
{
try
{
dbContext.Database.Migrate();
}
catch
{
var logging = scope.ServiceProvider.GetService<ILogger<Program>>()!;
logging.LogError(
"An error occurred while migrating after an update, resetting database..."
);
dbContext.Database.EnsureDeleted();
dbContext.Database.EnsureCreated();
dbContext.Database.Migrate();
logging.LogInformation("Database reset successful.");
}
}
else
dbContext.Database.Migrate();
}
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
}
var staticFileProvider = new FileExtensionContentTypeProvider();
staticFileProvider.Mappings[".apk"] = "application/vnd.android.package-archive";
app.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = staticFileProvider });
app.UseStaticFiles();
app.UseRouting();
app.UseAntiforgery();
app.MapControllers();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode(o => o.DisableWebSocketCompression = true);
app.MapHub<DisplayHub>(Constants.HubRoutes.DISPLAY_HUB);
var logger = app.Services.GetService<ILogger<Program>>()!;
logger.LogInformation($"Launching with version {VersionService.CurrentVersion.Version}.");
app.Run();
}
}
Page with the issue in question: - removed irrelevant parts:
<div class="p-2 ">
<h2><b>Search</b></h2>
<div class="input-search flex flex-row w-[95%]">
<input type="text" class="input-style" @oninput="SearchTextChanged" value="@_searchText" />
</div>
<div>
@if (_results is null)
{
<Spinner />
}
else
{
if (_results.Any())
{
if (_isLoading)
{
<ElementSpinner />
}
else
{
foreach (var song in _results)
{
<div class="result grid grid-cols-10 gap-2 cursor-pointer" @onclick="() => AddToQueue(song)">
<label class="p-2 col-span-9 cursor-pointer">
@song.Name.Shorten() (@song.Number)
</label>
<div class="p-2 col-span-1">
<h4 class="primary-color pointer material-symbols-rounded">
add_circle
</h4>
</div>
</div>
}
}
}
else
{
<label>No results</label>
}
}
</div>
</div>
@code {
private Queue? _currentQueue;
private bool _automaticallyAddResult;
private IEnumerable<Song>? _results;
private string _searchText = string.Empty;
private bool _isLoading;
private Timer? _timer;
private CancellationToken _cancellationToken = new CancellationToken();
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
_timer = new Timer(Constants.Times.DEBOUNCE_TIME);
_timer.Stop();
_timer.Elapsed += UpdateResults;
_timer.AutoReset = false;
using var db = _dbContextFactory.CreateDbContext();
_currentQueue = await db.Queues
.Include(x => x.Playable)
.AsNoTracking()
.FirstAsync();
_automaticallyAddResult = await db.Settings
.AsNoTracking()
.Select(x => x.AutomaticallyAddResult)
.FirstAsync();
UpdateResults();
}
}
private async void UpdateResults(Object? obj = null, ElapsedEventArgs? e = null)
{
_isLoading = true;
if (!string.IsNullOrWhiteSpace(_searchText))
{
using var db = _dbContextFactory.CreateDbContext();
var queryableResults = db.Songs.AsNoTracking()
.Where(x => (x.Number != null && x.Number!.ToString()!.Contains(_searchText)) ||
x.SearchName.Contains(_searchText.NormalizeForSearch()))
.OrderBy(x => x.Number)
.ThenBy(x => x.Name)
.Take(10);
_results = await queryableResults.ToListAsync(_cancellationToken);
}
else
{
_results = new List<Song>();
}
if (_automaticallyAddResult && _results.Count() == 1)
AddToQueue(_results.First());
_isLoading = false;
await InvokeAsync(StateHasChanged);
}
private async void AddToQueue(Song song)
{
if (_currentQueue is null)
return;
if (!_currentQueue.Playable.Contains(song))
{
using var db = _dbContextFactory.CreateDbContext();
var targetSong = await db.Songs.FirstOrDefaultAsync(x => x.Id.Equals(song.Id));
if (targetSong is null)
return;
targetSong.AddedToQueue = DateTime.Now;
targetSong.PlayableQueueId = _currentQueue.Id;
await db.SaveChangesAsync();
song.AddedToQueue = targetSong.AddedToQueue;
_currentQueue.Playable.Add(song);
StateHasChanged();
}
ClearSearchText();
}
private async void RemoveFromQueue(Song song)
{
if (_currentQueue is null)
return;
using var db = _dbContextFactory.CreateDbContext();
var targetSong = await db.Songs.FirstOrDefaultAsync(x => x.Id.Equals(song.Id));
if (targetSong is null)
return;
targetSong.AddedToQueue = null;
targetSong.PlayableQueueId = null;
await db.SaveChangesAsync();
song.AddedToQueue = null;
_currentQueue.Playable.Remove(song);
StateHasChanged();
}
private void SearchTextChanged(ChangeEventArgs e)
{
if (e?.Value is null || e.Value is not string value)
return;
_searchText = value;
_timer?.Stop();
_timer?.Start();
}
private void AddToSearchText(int value)
{
_searchText += value.ToString();
UpdateResults();
}
private void ClearSearchText()
{
_searchText = string.Empty;
UpdateResults();
}
void IDisposable.Dispose()
=> _timer?.Dispose();
}
Importantly, this does not happen when debugging in Visual Studio, does not happen on any other page. Only happens when searching with my keyboard on the provided page.
Expected Behavior
No response
Steps To Reproduce
No response
Exceptions (if any)
Server-side no exceptions
.NET Version
9
Anything else?
Issue occurs on Raspbian, Raspberry Pi 4, published for linux-arm64 (self-contained)
Metadata
Metadata
Assignees
Labels
needs-area-labelUsed by the dotnet-issue-labeler to label those issues which couldn't be triaged automaticallyUsed by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically