From 77bd3b389c46a9bc62bd8f4037ab3321f947b70e Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 21 Oct 2025 19:18:54 +0200 Subject: [PATCH] Implemented the .NET side of Tauri event stream handling --- app/MindWork AI Studio/Program.cs | 5 ++ app/MindWork AI Studio/Tools/Event.cs | 1 + .../Tools/Rust/TauriEvent.cs | 3 ++ .../Tools/Rust/TauriEventType.cs | 11 ++++ .../Tools/Services/RustService.Events.cs | 53 +++++++++++++++++++ .../Tools/Services/RustService.cs | 13 +++-- 6 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 app/MindWork AI Studio/Tools/Rust/TauriEvent.cs create mode 100644 app/MindWork AI Studio/Tools/Rust/TauriEventType.cs create mode 100644 app/MindWork AI Studio/Tools/Services/RustService.Events.cs diff --git a/app/MindWork AI Studio/Program.cs b/app/MindWork AI Studio/Program.cs index a4d9c2b4..2514a67f 100644 --- a/app/MindWork AI Studio/Program.cs +++ b/app/MindWork AI Studio/Program.cs @@ -133,6 +133,11 @@ internal sealed class Program builder.Services.AddHostedService(); builder.Services.AddHostedService(); builder.Services.AddHostedService(); + + // ReSharper disable AccessToDisposedClosure + builder.Services.AddHostedService(_ => rust); + // ReSharper restore AccessToDisposedClosure + builder.Services.AddRazorComponents() .AddInteractiveServerComponents() .AddHubOptions(options => diff --git a/app/MindWork AI Studio/Tools/Event.cs b/app/MindWork AI Studio/Tools/Event.cs index 8d8ce415..9f612f04 100644 --- a/app/MindWork AI Studio/Tools/Event.cs +++ b/app/MindWork AI Studio/Tools/Event.cs @@ -14,6 +14,7 @@ public enum Event SHOW_ERROR, SHOW_WARNING, SHOW_SUCCESS, + TAURI_EVENT_RECEIVED, // Update events: USER_SEARCH_FOR_UPDATE, diff --git a/app/MindWork AI Studio/Tools/Rust/TauriEvent.cs b/app/MindWork AI Studio/Tools/Rust/TauriEvent.cs new file mode 100644 index 00000000..140522be --- /dev/null +++ b/app/MindWork AI Studio/Tools/Rust/TauriEvent.cs @@ -0,0 +1,3 @@ +namespace AIStudio.Tools.Rust; + +public readonly record struct TauriEvent(TauriEventType Type, List Payload); \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Rust/TauriEventType.cs b/app/MindWork AI Studio/Tools/Rust/TauriEventType.cs new file mode 100644 index 00000000..2710c16b --- /dev/null +++ b/app/MindWork AI Studio/Tools/Rust/TauriEventType.cs @@ -0,0 +1,11 @@ +namespace AIStudio.Tools.Rust; + +public enum TauriEventType +{ + WINDOW_FOCUSED, + WINDOW_NOT_FOCUSED, + + FILE_DROP_HOVERED, + FILE_DROP_DROPPED, + FILE_DROP_CANCELED, +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Services/RustService.Events.cs b/app/MindWork AI Studio/Tools/Services/RustService.Events.cs new file mode 100644 index 00000000..539c3d06 --- /dev/null +++ b/app/MindWork AI Studio/Tools/Services/RustService.Events.cs @@ -0,0 +1,53 @@ +using System.Text.Json; + +using AIStudio.Tools.Rust; + +namespace AIStudio.Tools.Services; + +public partial class RustService +{ + private async Task StartStreamTauriEvents(CancellationToken stopToken) + { + try + { + while (!stopToken.IsCancellationRequested) + { + try + { + await using var stream = await this.http.GetStreamAsync("/events", stopToken); + using var reader = new StreamReader(stream); + while(!reader.EndOfStream) + { + var line = await reader.ReadLineAsync(stopToken); + if (string.IsNullOrWhiteSpace(line)) + continue; + + var tauriEvent = JsonSerializer.Deserialize(line, this.jsonRustSerializerOptions); + if (tauriEvent != default) + await MessageBus.INSTANCE.SendMessage(null, Event.TAURI_EVENT_RECEIVED, tauriEvent); + } + } + + // The cancellation token was triggered, exit the loop: + catch (OperationCanceledException) + { + break; + } + + // Some other error occurred, log it and retry after a delay: + catch (Exception e) + { + this.logger!.LogError("Error while streaming Tauri events: {Message}", e.Message); + await Task.Delay(TimeSpan.FromSeconds(3), stopToken); + } + } + } + + // The cancellation token was triggered, exit the method: + catch (OperationCanceledException) + { + } + + this.logger!.LogWarning("Stopped streaming Tauri events."); + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Services/RustService.cs b/app/MindWork AI Studio/Tools/Services/RustService.cs index 38fab8cc..56032b65 100644 --- a/app/MindWork AI Studio/Tools/Services/RustService.cs +++ b/app/MindWork AI Studio/Tools/Services/RustService.cs @@ -8,7 +8,7 @@ namespace AIStudio.Tools.Services; /// /// Calling Rust functions. /// -public sealed partial class RustService : IDisposable +public sealed partial class RustService : BackgroundService { private readonly HttpClient http; @@ -59,11 +59,18 @@ public sealed partial class RustService : IDisposable this.encryptor = encryptionService; } - #region IDisposable + #region Overrides of BackgroundService - public void Dispose() + protected override async Task ExecuteAsync(CancellationToken stopToken) + { + this.logger?.LogInformation("The Rust service was initialized."); + await this.StartStreamTauriEvents(stopToken); + } + + public override void Dispose() { this.http.Dispose(); + base.Dispose(); } #endregion