Crude base implementation

This commit is contained in:
2025-04-01 13:49:46 +03:30
parent 1c3bda092a
commit 9cb5e882c7
3 changed files with 62 additions and 17 deletions

View File

@@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpResponseStream_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fmahdium_003F_002Econfig_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F912bd5c687f4cf55e0daddfb3f8eecd859debac3856d3a98f1a2ad5208413bd_003FHttpResponseStream_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>

View File

@@ -1,3 +1,5 @@
using System.Collections.Concurrent;
using System.Text;
using System.Text.Json.Serialization;
var builder = WebApplication.CreateSlimBuilder(args);
@@ -9,27 +11,69 @@ builder.Services.ConfigureHttpJsonOptions(options =>
var app = builder.Build();
var sampleTodos = new Todo[]
var subscribers = new ConcurrentDictionary<string, List<StreamWriter>>();
// HAPI!
// https://github.com/jheising/HAPI
var createApi = app.MapGroup("/create/with");
createApi.MapGet("/{feedId}", async (HttpContext context,string feedId) =>
{
new(1, "Walk the dog"),
new(2, "Do the dishes", DateOnly.FromDateTime(DateTime.Now)),
new(3, "Do the laundry", DateOnly.FromDateTime(DateTime.Now.AddDays(1))),
new(4, "Clean the bathroom"),
new(5, "Clean the car", DateOnly.FromDateTime(DateTime.Now.AddDays(2)))
};
var rawQueryData = context.Request.QueryString.ToString();
var queryDataDic = context.Request.Query.ToDictionary(k => k.Key, v => v.Value);
foreach (var a in queryDataDic)
{
Console.WriteLine($"""{a.Key}: {a.Value}""");
}
var todosApi = app.MapGroup("/todos");
todosApi.MapGet("/", () => sampleTodos);
todosApi.MapGet("/{id}", (int id) =>
sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
? Results.Ok(todo)
: Results.NotFound());
if (subscribers.TryGetValue(feedId, out var subscribersList))
{
foreach (var writer in subscribersList)
{
await writer.WriteLineAsync(rawQueryData);
await writer.FlushAsync();
}
}
});
var getLiveDataApi = app.MapGroup("/listen/for/data");
getLiveDataApi.MapGet("/{feedId}", async (CancellationToken cancellationToken,HttpContext context, string feedId) =>
{
context.Response.Headers.ContentType = "text/event-stream";
var writer = new StreamWriter(context.Response.Body, Encoding.UTF8);
subscribers.GetOrAdd(feedId, _ => new List<StreamWriter>()).Add(writer);
try
{
while (!cancellationToken.IsCancellationRequested)
{
await Task.Delay(Timeout.Infinite, cancellationToken);
}
}
catch (OperationCanceledException)
{
}
finally
{
if (subscribers.TryGetValue(feedId, out var subscribersList))
{
subscribersList.Remove(writer);
if (subscribersList.Count == 0)
{
subscribers.TryRemove(feedId, out _);
}
await writer.DisposeAsync();
Console.WriteLine("Removed subscriber from feed " + feedId);
}
}
});
app.Run();
public record Todo(int Id, string? Title, DateOnly? DueBy = null, bool IsComplete = false);
[JsonSerializable(typeof(Todo[]))]
[JsonSerializable(typeof(string))]
[JsonSerializable(typeof(Int32))]
internal partial class AppJsonSerializerContext : JsonSerializerContext
{
}

View File

@@ -4,8 +4,7 @@
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "todos",
"launchBrowser": false,
"applicationUrl": "http://localhost:5246",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"