-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2693 from erri120/feat/event-bus
Event Bus and reacting to downloads
- Loading branch information
Showing
17 changed files
with
277 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
src/Abstractions/NexusMods.Abstractions.EventBus/IEventBus.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using DynamicData.Kernel; | ||
using JetBrains.Annotations; | ||
using R3; | ||
|
||
namespace NexusMods.Abstractions.EventBus; | ||
|
||
/// <summary> | ||
/// Represents an event bus for sending messages and requests. | ||
/// </summary> | ||
[PublicAPI] | ||
public interface IEventBus | ||
{ | ||
/// <summary> | ||
/// Sends a message. | ||
/// </summary> | ||
void Send<T>(T message) where T : IEventBusMessage; | ||
|
||
/// <summary> | ||
/// Sends a request as a message and returns task that completes when a handler responds with a result. | ||
/// </summary> | ||
Task<Optional<TResult>> SendAndReceive<TRequest, TResult>(TRequest request, CancellationToken cancellationToken) | ||
where TRequest : IEventBusRequest<TResult> | ||
where TResult : notnull; | ||
|
||
/// <summary> | ||
/// Observes incoming messages of type <typeparamref name="T"/>. | ||
/// </summary> | ||
Observable<T> ObserveMessages<T>() where T : IEventBusMessage; | ||
|
||
/// <summary> | ||
/// Observes all incoming messages. | ||
/// </summary> | ||
Observable<IEventBusMessage> ObserveAllMessages(); | ||
} |
9 changes: 9 additions & 0 deletions
9
src/Abstractions/NexusMods.Abstractions.EventBus/IEventBusMessage.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using JetBrains.Annotations; | ||
|
||
namespace NexusMods.Abstractions.EventBus; | ||
|
||
/// <summary> | ||
/// Represents a message. | ||
/// </summary> | ||
[PublicAPI] | ||
public interface IEventBusMessage; |
10 changes: 10 additions & 0 deletions
10
src/Abstractions/NexusMods.Abstractions.EventBus/IEventBusRequest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using JetBrains.Annotations; | ||
|
||
namespace NexusMods.Abstractions.EventBus; | ||
|
||
/// <summary> | ||
/// Represents a request. | ||
/// </summary> | ||
[PublicAPI] | ||
public interface IEventBusRequest<TResult> : IEventBusMessage | ||
where TResult : notnull; |
17 changes: 17 additions & 0 deletions
17
src/Abstractions/NexusMods.Abstractions.EventBus/IEventBusRequestHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using JetBrains.Annotations; | ||
|
||
namespace NexusMods.Abstractions.EventBus; | ||
|
||
/// <summary> | ||
/// Handles requests by responding with a result. | ||
/// </summary> | ||
[PublicAPI] | ||
public interface IEventBusRequestHandler<in TRequest, TResult> | ||
where TRequest : IEventBusRequest<TResult> | ||
where TResult : notnull | ||
{ | ||
/// <summary> | ||
/// Handles the request. | ||
/// </summary> | ||
Task<TResult> Handle(TRequest request, CancellationToken cancellationToken); | ||
} |
9 changes: 9 additions & 0 deletions
9
src/Abstractions/NexusMods.Abstractions.EventBus/NexusMods.Abstractions.EventBus.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<!-- NuGet Package Shared Details --> | ||
<Import Project="$([MSBuild]::GetPathOfFileAbove('NuGet.Build.props', '$(MSBuildThisFileDirectory)../'))" /> | ||
<ItemGroup> | ||
<PackageReference Include="DynamicData"/> | ||
<PackageReference Include="R3"/> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using NexusMods.Abstractions.EventBus; | ||
using NexusMods.Abstractions.NexusModsLibrary.Models; | ||
|
||
namespace NexusMods.CLI; | ||
|
||
public static class CliMessages | ||
{ | ||
public record AddedCollection(CollectionRevisionMetadata.ReadOnly Revision) : IEventBusMessage; | ||
|
||
public record AddedDownload() : IEventBusMessage; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
using System.Diagnostics.CodeAnalysis; | ||
using DynamicData.Kernel; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Logging; | ||
using NexusMods.Abstractions.EventBus; | ||
using R3; | ||
|
||
namespace NexusMods.App.UI; | ||
|
||
public sealed class EventBus : IEventBus, IDisposable | ||
{ | ||
private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(10); | ||
|
||
private static IEventBus? _instance; | ||
public static IEventBus Instance | ||
{ | ||
get => _instance ?? throw new InvalidOperationException("Event Bus hasn't been registered yet"); | ||
private set | ||
{ | ||
if (_instance is not null) throw new InvalidOperationException("Event Bus has already been registered"); | ||
_instance = value; | ||
} | ||
} | ||
|
||
private readonly IServiceProvider _serviceProvider; | ||
private readonly ILogger _logger; | ||
private readonly Subject<IEventBusMessage> _messages = new(); | ||
|
||
public EventBus(IServiceProvider serviceProvider) | ||
{ | ||
_serviceProvider = serviceProvider; | ||
_logger = serviceProvider.GetRequiredService<ILogger<EventBus>>(); | ||
|
||
Instance = this; | ||
} | ||
|
||
[SuppressMessage("ReSharper", "HeapView.PossibleBoxingAllocation")] | ||
public void Send<T>(T message) where T : IEventBusMessage | ||
{ | ||
_logger.LogDebug("Received message of type `{Type}`: `{Message}`", typeof(T), message.ToString()); | ||
_messages.OnNext(message); | ||
} | ||
|
||
public Task<Optional<TResult>> SendAndReceive<TRequest, TResult>(TRequest request, CancellationToken cancellationToken) | ||
where TRequest : IEventBusRequest<TResult> | ||
where TResult : notnull | ||
{ | ||
Send(request); | ||
|
||
var requestHandler = _serviceProvider.GetService<IEventBusRequestHandler<TRequest, TResult>>(); | ||
if (requestHandler is null) | ||
{ | ||
_logger.LogError("Found no request handler for request of type `{RequestType}` with result type `{ResultType}`: `{StringRepresentation}`", typeof(TRequest), typeof(TResult), request.ToString()); | ||
return Task.FromResult(Optional<TResult>.None); | ||
} | ||
|
||
var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); | ||
cts.CancelAfter(delay: DefaultTimeout); | ||
|
||
return Inner(); | ||
|
||
async Task<Optional<TResult>> Inner() | ||
{ | ||
try | ||
{ | ||
return await requestHandler.Handle(request, cts.Token); | ||
} | ||
catch (Exception e) | ||
{ | ||
_logger.LogError(e, "Exception running request handler for request of type `{RequestType}` with result type `{ResultType}`: `{StringRepresentation}`", typeof(TRequest), typeof(TResult), request.ToString()); | ||
return Optional<TResult>.None; | ||
} | ||
} | ||
} | ||
|
||
public Observable<T> ObserveMessages<T>() where T : IEventBusMessage | ||
{ | ||
return _messages.OfType<IEventBusMessage, T>(); | ||
} | ||
|
||
public Observable<IEventBusMessage> ObserveAllMessages() | ||
{ | ||
return _messages; | ||
} | ||
|
||
private bool _isDisposed; | ||
public void Dispose() | ||
{ | ||
if (_isDisposed) return; | ||
|
||
_messages.Dispose(); | ||
_isDisposed = true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using NexusMods.Abstractions.Settings; | ||
|
||
namespace NexusMods.App.UI.Settings; | ||
|
||
public record BehaviorSettings : ISettings | ||
{ | ||
public bool BringWindowToFront { get; set; } = true; | ||
|
||
public static ISettingsBuilder Configure(ISettingsBuilder settingsBuilder) | ||
{ | ||
return settingsBuilder.AddToUI<BehaviorSettings>(builder => builder | ||
.AddPropertyToUI(x => x.BringWindowToFront, propertyBuilder => propertyBuilder | ||
.AddToSection(Sections.General) | ||
.WithDisplayName("Bring app window to front") | ||
.WithDescription("When enabled, operations like adding a collection will bring the app window to the foreground") | ||
.UseBooleanContainer() | ||
) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.