refactor: Refactoring of text creation
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.0" />
|
||||
<PackageReference Include="UnitsNet" Version="5.60.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
@page "/test"
|
||||
@rendermode InteractiveWebAssembly
|
||||
@inject PersistentComponentState ApplicationState
|
||||
@inject ILogger<TestClientForm> Logger
|
||||
|
||||
<p>@Data - @RendererInfo.Name</p>
|
||||
|
||||
<EditForm Enhance FormName="TestForm" OnSubmit="Callback" Model="Item">
|
||||
<InputText @bind-Value="@Item.Text"/>
|
||||
<button class="btn " type="submit" disabled="@(doingStuff || !RendererInfo.IsInteractive)">
|
||||
@if (doingStuff || !RendererInfo.IsInteractive)
|
||||
{
|
||||
<span class="loading loading-spinner"></span>
|
||||
<a>Loading...</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a>Test</a>
|
||||
}
|
||||
</button>
|
||||
</EditForm>
|
||||
|
||||
@code {
|
||||
|
||||
private bool doingStuff = false;
|
||||
|
||||
private PersistingComponentStateSubscription persistingSubscription;
|
||||
|
||||
public sealed class FormInput
|
||||
{
|
||||
public required string Text { get; set; }
|
||||
public required string[] Existing { get; set; }
|
||||
}
|
||||
|
||||
[SupplyParameterFromForm] public FormInput Item { get; set; } = new()
|
||||
{
|
||||
Text = string.Empty,
|
||||
Existing = []
|
||||
};
|
||||
|
||||
public Guid Data = Guid.NewGuid();
|
||||
|
||||
protected override Task OnInitializedAsync()
|
||||
{
|
||||
persistingSubscription =
|
||||
ApplicationState.RegisterOnPersisting(PersistData);
|
||||
|
||||
if (!ApplicationState.TryTakeFromJson<Guid>("TOKEN", out Data))
|
||||
{
|
||||
Data = Guid.NewGuid();
|
||||
Logger.LogInformation("Data needs to be persisted! {Data}", Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogInformation("Using persisted DATA");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task PersistData()
|
||||
{
|
||||
Logger.LogInformation("Persisting! {Data}", Data);
|
||||
ApplicationState.PersistAsJson("TOKEN", Data);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task Callback()
|
||||
{
|
||||
Item = new FormInput
|
||||
{
|
||||
Text = string.Empty,
|
||||
Existing = [..Item.Existing, Item.Text, RendererInfo.Name]
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -27,8 +27,8 @@
|
||||
@{
|
||||
string key = CreatedItems.GetPrimaryKeyString();
|
||||
}
|
||||
<a href="@Nav.ToAbsoluteUri($"/t/{key}")">@Nav.ToAbsoluteUri($"/t/{key}")</a>
|
||||
</div>
|
||||
<a class="link" href="@Nav.ToAbsoluteUri($"/t/{key}")">@Nav.ToAbsoluteUri($"/t/{key}")</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -38,19 +38,21 @@
|
||||
|
||||
[Inject] public ILogger<Home> Logger { get; set; } = null!;
|
||||
|
||||
[Inject] public LinkGenerator ItemGenerator { get; set; } = null!;
|
||||
[Inject] public ILinkGenerator ItemGenerator { get; set; } = null!;
|
||||
|
||||
[Inject] public IClusterClient ClusterClient { get; set; } = null!;
|
||||
[Inject] public IGrainFactory ClusterClient { get; set; } = null!;
|
||||
|
||||
public ITextItem? CreatedItems;
|
||||
|
||||
private async Task SubmitInput()
|
||||
{
|
||||
ITextItem item = await ItemGenerator.GenerateTextShare(Form.InputText);
|
||||
|
||||
CreatedItems = item;
|
||||
|
||||
Form = new UploadForm();
|
||||
LinkResult result = await ItemGenerator.GenerateTextShare(Form.InputText);
|
||||
|
||||
if (result.Item is not null)
|
||||
{
|
||||
CreatedItems = result.Item;
|
||||
Form = new UploadForm();
|
||||
}
|
||||
Logger.LogInformation("A new item was created!");
|
||||
}
|
||||
|
||||
|
||||
49
Pushy/Pushy/Grains/LinkGenerator.cs
Normal file
49
Pushy/Pushy/Grains/LinkGenerator.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Pushy.Grains;
|
||||
|
||||
[Immutable]
|
||||
[GenerateSerializer]
|
||||
[Alias("Pushy.Grains.LinkResult")]
|
||||
public record LinkResult(ITextItem? Item);
|
||||
|
||||
public interface ILinkGenerator : IGrainWithGuidKey
|
||||
{
|
||||
[Alias("GenerateLink")]
|
||||
public ValueTask<LinkResult> GenerateTextShare([Immutable] string text);
|
||||
}
|
||||
|
||||
public sealed class LinkGenerator : IGrainBase, ILinkGenerator
|
||||
{
|
||||
private readonly ILogger<LinkGenerator> _logger;
|
||||
private readonly IClusterClient _clusterClient;
|
||||
|
||||
public IGrainContext GrainContext { get; }
|
||||
|
||||
public LinkGenerator(
|
||||
IGrainContext grainContext,
|
||||
IClusterClient clusterClient,
|
||||
ILogger<LinkGenerator> logger)
|
||||
{
|
||||
_clusterClient = clusterClient;
|
||||
_logger = logger;
|
||||
GrainContext = grainContext;
|
||||
}
|
||||
|
||||
public async ValueTask<LinkResult> GenerateTextShare(string text)
|
||||
{
|
||||
string item = $"{Guid.CreateVersion7():N}"[9..];
|
||||
var textGrain = _clusterClient.GetGrain<ITextItem>(item);
|
||||
try
|
||||
{
|
||||
await textGrain.SetText(text);
|
||||
return new LinkResult(textGrain);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//TODO: Write log message of why it fails?
|
||||
//Swallow small change of error
|
||||
return await GenerateTextShare(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,13 @@ using Orleans.Concurrency;
|
||||
|
||||
namespace Pushy.Grains;
|
||||
|
||||
[GenerateSerializer]
|
||||
public enum TextSetResult
|
||||
{
|
||||
Failure,
|
||||
Success
|
||||
}
|
||||
|
||||
public sealed class TextItem
|
||||
{
|
||||
public string? Text { get; set; }
|
||||
@@ -9,11 +16,8 @@ public sealed class TextItem
|
||||
|
||||
public interface ITextItem : IGrainWithStringKey
|
||||
{
|
||||
[Alias("IsAvailable")]
|
||||
public ValueTask<bool> IsAvailable();
|
||||
|
||||
[Alias("SetText")]
|
||||
public ValueTask SetText(string text);
|
||||
public ValueTask<TextSetResult> SetText(string text);
|
||||
|
||||
[ReadOnly]
|
||||
[return: Immutable]
|
||||
@@ -21,44 +25,51 @@ public interface ITextItem : IGrainWithStringKey
|
||||
ValueTask<string> GetText();
|
||||
}
|
||||
|
||||
public sealed class TextItemGrain : Grain, ITextItem, IRemindable
|
||||
public sealed class TextItemGrain : IGrainBase, ITextItem, IRemindable
|
||||
{
|
||||
private readonly IPersistentState<TextItem> _state;
|
||||
|
||||
private IGrainReminder? _reminder;
|
||||
|
||||
public TextItemGrain(
|
||||
IGrainContext grainContext,
|
||||
[PersistentState("text")] IPersistentState<TextItem> state)
|
||||
{
|
||||
_state = state;
|
||||
GrainContext = grainContext;
|
||||
}
|
||||
|
||||
public IGrainContext GrainContext { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task OnActivateAsync(CancellationToken cancellationToken)
|
||||
public async Task OnActivateAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_reminder = await this.RegisterOrUpdateReminder("clear", TimeSpan.FromDays(10), TimeSpan.FromDays(10));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ValueTask<bool> IsAvailable()
|
||||
public async ValueTask<TextSetResult> SetText(string text)
|
||||
{
|
||||
return ValueTask.FromResult(_state.State.Text is null);
|
||||
}
|
||||
try
|
||||
{
|
||||
if (_state.State.Text is not null)
|
||||
return TextSetResult.Failure;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask SetText(string text)
|
||||
{
|
||||
if(_state.State.Text is not null)
|
||||
throw new InvalidOperationException("Text is already set");
|
||||
|
||||
_state.State.Text = text;
|
||||
await _state.WriteStateAsync();
|
||||
_state.State.Text = text;
|
||||
await _state.WriteStateAsync();
|
||||
|
||||
return TextSetResult.Success;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return TextSetResult.Failure;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ValueTask<string> GetText()
|
||||
{
|
||||
return ValueTask.FromResult(_state.State.Text!);
|
||||
return ValueTask.FromResult(_state.State.Text ?? throw new InvalidOperationException("No text was available"));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -68,6 +79,7 @@ public sealed class TextItemGrain : Grain, ITextItem, IRemindable
|
||||
{
|
||||
_state.State.Text = null;
|
||||
await _state.WriteStateAsync();
|
||||
this.DeactivateOnIdle();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Pushy.Grains;
|
||||
|
||||
namespace Pushy;
|
||||
|
||||
public sealed class LinkGenerator
|
||||
{
|
||||
private readonly ILogger<LinkGenerator> _logger;
|
||||
private readonly IClusterClient _clusterClient;
|
||||
|
||||
public LinkGenerator(
|
||||
IClusterClient clusterClient,
|
||||
ILogger<LinkGenerator> logger)
|
||||
{
|
||||
_clusterClient = clusterClient;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<ITextItem> GenerateTextShare(string text)
|
||||
{
|
||||
string item = $"{Guid.CreateVersion7():N}"[6..];
|
||||
var sharedGrain = _clusterClient.GetGrain<ITextItem>(item);
|
||||
if (await sharedGrain.IsAvailable())
|
||||
{
|
||||
await sharedGrain.SetText(text);
|
||||
return sharedGrain;
|
||||
}
|
||||
|
||||
return await GenerateTextShare(text);
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@ using Elastic.Extensions.Logging.Options;
|
||||
using Elastic.Transport;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Pushy.Components;
|
||||
using Pushy.Grains;
|
||||
using StackExchange.Redis;
|
||||
using LinkGenerator = Pushy.LinkGenerator;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@@ -51,7 +51,8 @@ if (builder.Environment.IsProduction())
|
||||
});
|
||||
}
|
||||
|
||||
builder.Services.AddScoped<LinkGenerator>();
|
||||
builder.Services.AddScoped(service =>
|
||||
service.GetRequiredService<IGrainFactory>().GetGrain<ILinkGenerator>(Guid.Empty));
|
||||
builder.Services.AddAllElasticApm();
|
||||
|
||||
builder.Services.AddHealthChecks();
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
<UserSecretsId>d8fe2296-80f7-4812-b26a-ccaa6167a6e1</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<ServerGarbageCollection>true</ServerGarbageCollection>
|
||||
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Elastic.Apm.NetCoreAll" Version="1.30.0" />
|
||||
<PackageReference Include="Elastic.Extensions.Logging" Version="8.12.2" />
|
||||
@@ -23,6 +28,7 @@
|
||||
<PackageReference Include="Microsoft.Orleans.Sdk" Version="8.2.0" />
|
||||
<PackageReference Include="Microsoft.Orleans.Server" Version="8.2.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="9.0.0" />
|
||||
<PackageReference Include="UnitsNet" Version="5.60.0" />
|
||||
<ProjectReference Include="..\Pushy.Client\Pushy.Client.csproj"/>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user