Skip to content

Commit

Permalink
RX State improve simplify service transformers
Browse files Browse the repository at this point in the history
Remove dedicated service state transformes
  • Loading branch information
Bernhard Straub committed Feb 25, 2024
1 parent 4da6261 commit 0cb4108
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 29 deletions.
57 changes: 55 additions & 2 deletions RxBlazorLightCore/Core/State.cs
Original file line number Diff line number Diff line change
Expand Up @@ -300,9 +300,37 @@ public void Transform(T value)
protected abstract Task<TType> TransformStateAsync(T value, CancellationToken cancellationToken);
}

public abstract class StateTransformerAsync<S, T>(S service) :
StateProvideTransformBase<S, T, Unit, Unit>(service, null, true, true), IStateTransformer<T>
where S : RxBLService
{
public virtual bool CanTransform(T? _)
{
return true;
}

public void Transform(T value)
{
TransformBaseAsync(value);
}

protected override IObservable<Unit> ProvideObervableValueBase(T? value, Unit state)
{
ArgumentNullException.ThrowIfNull(value);

return Observable.FromAsync(async ct =>
{
await TransformStateAsync(value, ct);
return IState.Default;
});
}

protected abstract Task TransformStateAsync(T value, CancellationToken cancellationToken);
}

public abstract class StateTransformer<S, T, TType>(S service, IState<TType> state) :
StateProvideTransformBase<S, T, TType, TType>(service, state, true, false), IStateTransformer<T>
where S : RxBLService
StateProvideTransformBase<S, T, TType, TType>(service, state, true, false), IStateTransformer<T>
where S : RxBLService
{
public virtual bool CanTransform(T? _)
{
Expand All @@ -324,6 +352,31 @@ public void Transform(T value)
protected abstract TType? TransformState(T value);
}

public abstract class StateTransformer<S, T>(S service) :
StateProvideTransformBase<S, T, Unit, Unit>(service, null, true, false), IStateTransformer<T>
where S : RxBLService
{
public virtual bool CanTransform(T? _)
{
return true;
}

public void Transform(T value)
{
try
{
TransformState(value);
TransformBaseSync(IState.Default);
}
catch (Exception ex)
{
StateChanged(StateChangePhase.EXCEPTION, ex);
}
}

protected abstract void TransformState(T value);
}

public class ObservableStateProvider<S, T>(S service, IState<T>? state) :
StateProvideTransformBase<S, T, T, T>(service, state, true, false), IObservableStateProvider<T>
where S : RxBLService
Expand Down
27 changes: 23 additions & 4 deletions RxBlazorLightCoreTestBase/ServiceFixture.State.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,44 @@ protected override async Task<int> TransformStateAsync(int value, CancellationTo
}
}

public class ChangeTestSP(ServiceFixture service) : StateProviderAsync<ServiceFixture>(service)
public class TransformTestSyncST(ServiceFixture service) : StateTransformer<ServiceFixture, string>(service)
{
public override bool CanCancel => true;

protected override async Task ProvideStateAsync(CancellationToken cancellationToken)
protected override void TransformState(string value)
{
Service.Test = value;
}
}

public class TransformTestAsyncST(ServiceFixture service) : StateTransformerAsync<ServiceFixture, string>(service)
{
public override bool CanCancel => true;

protected override async Task TransformStateAsync(string value, CancellationToken cancellationToken)
{
await Task.Delay(TimeSpan.FromSeconds(2), cancellationToken);
Service.Test = "Async";
Service.Test = value;
}
}

public class ChangeTestSyncSP(ServiceFixture service) : StateProvider<ServiceFixture>(service)
public class ProvideTestSyncSP(ServiceFixture service) : StateProvider<ServiceFixture>(service)
{
protected override void ProvideState()
{
Service.Test = "Sync";
}
}

public class ProvideTestAsyncSP(ServiceFixture service) : StateProviderAsync<ServiceFixture>(service)
{
protected override async Task ProvideStateAsync(CancellationToken cancellationToken)
{
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
Service.Test = "Async";
}
}

public class IntListVP(ServiceFixture service, IState<IEnumerable<CRUDTest>, List<CRUDTest>> state) :
StateRefTransformerAsync<ServiceFixture, (IntListVP.CMD_LIST CMD, CRUDTest? ITEM), IEnumerable<CRUDTest>, List<CRUDTest>>(service, state)
{
Expand Down
15 changes: 11 additions & 4 deletions RxBlazorLightCoreTestBase/ServiceFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ public partial class ServiceFixture : RxBLService

public IStateProvider<int> Increment { get; }
public IStateTransformer<int> Add { get; }
public IStateProvider ChangeTestAsync { get; }
public IStateProvider ChangeTestSync { get; }
public IStateTransformer<string> TransformTestAsync { get; }
public IStateTransformer<string> TransformTestSync { get; }

public IStateProvider ProvideTestSync { get; }
public IStateProvider ProvideTestAsync { get; }

public IStateTransformer<(IntListVP.CMD_LIST CMD, CRUDTest? ITEM)> CRUDListCmds { get; }
public IStateTransformer<(IntDictVP.CMD_DICT CMD, Guid? ID, CRUDTest? ITEM)> CRUDDictCmds { get; }
Expand All @@ -46,8 +49,12 @@ public ServiceFixture()

Increment = new IncremementVP(this, IntState);
Add = new AddVP(this, IntState);
ChangeTestAsync = new ChangeTestSP(this);
ChangeTestSync = new ChangeTestSyncSP(this);

TransformTestSync = new TransformTestSyncST(this);
TransformTestAsync = new TransformTestAsyncST(this);

ProvideTestSync = new ProvideTestSyncSP(this);
ProvideTestAsync = new ProvideTestAsyncSP(this);
}

public void ClearTest()
Expand Down
141 changes: 123 additions & 18 deletions RxBlazorLightCoreTests/StateTests.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using RxBlazorLightCore;
using RxBlazorLightCoreTestBase;
using Xunit.Abstractions;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Reactive;
using System;

namespace RxBlazorLightCoreTests
{
Expand Down Expand Up @@ -164,14 +164,14 @@ public void TestState()

fixture.Subscribe(sc =>
{
if (sc.ID == fixture.ChangeTestAsync.ID)
if (sc.ID == fixture.TransformTestAsync.ID)
{
stateChangeCount++;
}

_output.WriteLine($"Done {fixture.ChangeTestAsync.Done()}, CC {stateChangeCount} Reason {sc.Reason}, Phase {fixture.ChangeTestAsync.Phase}, ID {sc.ID}, VPID {fixture.ChangeTestAsync.ID}");
_output.WriteLine($"Done {fixture.TransformTestAsync.Done()}, CC {stateChangeCount} Reason {sc.Reason}, Phase {fixture.TransformTestAsync.Phase}, ID {sc.ID}, VPID {fixture.TransformTestAsync.ID}");

if (fixture.ChangeTestAsync.Done())
if (fixture.TransformTestAsync.Done())
{
done = true;
}
Expand All @@ -181,30 +181,30 @@ public void TestState()

Assert.Equal(string.Empty, fixture.Test);

fixture.ChangeTestAsync.Provide();
fixture.TransformTestAsync.Transform("Async");
while (!done) ;

Assert.Equal("Async", fixture.Test);
Assert.True(stateChangeCount > 0 && stateChangeCount <= 2);
}

[Fact]
public void TestStateSync()
public void TransformStateSync()
{
ServiceFixture fixture = new();
var stateChangeCount = 0;
bool done = false;

fixture.Subscribe(sc =>
{
if (sc.ID == fixture.ChangeTestSync.ID)
if (sc.ID == fixture.TransformTestSync.ID)
{
stateChangeCount++;
}

_output.WriteLine($"Done {fixture.ChangeTestSync.Done()}, CC {stateChangeCount} Reason {sc.Reason}, Phase {fixture.ChangeTestSync.Phase}, ID {sc.ID}, VPID {fixture.ChangeTestSync.ID}");
_output.WriteLine($"Done {fixture.TransformTestSync.Done()}, CC {stateChangeCount} Reason {sc.Reason}, Phase {fixture.TransformTestSync.Phase}, ID {sc.ID}, VPID {fixture.TransformTestSync.ID}");

if (fixture.ChangeTestSync.Done())
if (fixture.TransformTestSync.Done())
{
done = true;
}
Expand All @@ -214,13 +214,112 @@ public void TestStateSync()

Assert.Equal(string.Empty, fixture.Test);

fixture.ChangeTestSync.Provide();
fixture.TransformTestSync.Transform("Sync");
while (!done) ;

Assert.Equal("Sync", fixture.Test);
Assert.True(stateChangeCount > 0 && stateChangeCount <= 1);
}

[Fact]
public void TransformStateAsync()
{
ServiceFixture fixture = new();
var stateChangeCount = 0;
bool done = false;

fixture.Subscribe(sc =>
{
if (sc.ID == fixture.TransformTestAsync.ID)
{
stateChangeCount++;
}

_output.WriteLine($"Done {fixture.TransformTestAsync.Done()}, CC {stateChangeCount} Reason {sc.Reason}, Phase {fixture.TransformTestAsync.Phase}, ID {sc.ID}, VPID {fixture.TransformTestAsync.ID}");

if (fixture.TransformTestAsync.Done())
{
done = true;
}
}, 0);

fixture.ClearTest();

Assert.Equal(string.Empty, fixture.Test);

fixture.TransformTestAsync.Transform("Async");
while (!done) ;

Assert.Equal("Async", fixture.Test);
Assert.True(stateChangeCount > 0 && stateChangeCount <= 2);
}

[Fact]
public void ProvideStateSync()
{
ServiceFixture fixture = new();
var stateChangeCount = 0;
bool done = false;

fixture.Subscribe(sc =>
{
if (sc.ID == fixture.ProvideTestSync.ID)
{
stateChangeCount++;
}

_output.WriteLine($"Done {fixture.ProvideTestSync.Done()}, CC {stateChangeCount} Reason {sc.Reason}, Phase {fixture.ProvideTestSync.Phase}, ID {sc.ID}, VPID {fixture.ProvideTestSync.ID}");

if (fixture.ProvideTestSync.Done())
{
done = true;
}
}, 0);

fixture.ClearTest();

Assert.Equal(string.Empty, fixture.Test);

fixture.ProvideTestSync.Provide();
while (!done) ;

Assert.Equal("Sync", fixture.Test);
Assert.Equal(1, stateChangeCount);
}

[Fact]
public void ProvideStateAsync()
{
ServiceFixture fixture = new();
var stateChangeCount = 0;
bool done = false;

fixture.Subscribe(sc =>
{
if (sc.ID == fixture.ProvideTestAsync.ID)
{
stateChangeCount++;
}

_output.WriteLine($"Done {fixture.ProvideTestAsync.Done()}, CC {stateChangeCount} Reason {sc.Reason}, Phase {fixture.ProvideTestAsync.Phase}, ID {sc.ID}, VPID {fixture.ProvideTestAsync.ID}");

if (fixture.ProvideTestAsync.Done())
{
done = true;
}
}, 0);

fixture.ClearTest();

Assert.Equal(string.Empty, fixture.Test);

fixture.ProvideTestAsync.Provide();
while (!done) ;

Assert.Equal("Async", fixture.Test);
Assert.Equal(2, stateChangeCount);
}

[Fact]
public void TestStateCancel()
{
Expand All @@ -231,18 +330,18 @@ public void TestStateCancel()

fixture.Subscribe(sc =>
{
if (sc.ID == fixture.ChangeTestAsync.ID)
if (sc.ID == fixture.TransformTestAsync.ID)
{
stateChangeCount++;

if (fixture.ChangeTestAsync.Canceled())
if (fixture.TransformTestAsync.Canceled())
{
canceled = true;
}

_output.WriteLine($"Done {fixture.ChangeTestAsync.Done()}, CC {stateChangeCount} Reason {sc.Reason}, Phase {fixture.ChangeTestAsync.Phase}, ID {sc.ID}, VPID {fixture.ChangeTestAsync.ID}");
_output.WriteLine($"Done {fixture.TransformTestAsync.Done()}, CC {stateChangeCount} Reason {sc.Reason}, Phase {fixture.TransformTestAsync.Phase}, ID {sc.ID}, VPID {fixture.TransformTestAsync.ID}");

if (fixture.ChangeTestAsync.Done())
if (fixture.TransformTestAsync.Done())
{
done = true;
}
Expand All @@ -252,8 +351,8 @@ public void TestStateCancel()
fixture.ClearTest();
Assert.Equal(string.Empty, fixture.Test);

fixture.ChangeTestAsync.Provide();
fixture.ChangeTestAsync.Cancel();
fixture.TransformTestAsync.Transform("Async");
fixture.TransformTestAsync.Cancel();

while (!done) ;

Expand Down Expand Up @@ -286,7 +385,10 @@ public void TestStateObservable()

var changer = Observable.Range(0, 2);

var disposable = changer.Select(_ => Unit.Default).Subscribe(fixture.ObservableStateVoidProvider);
var disposable = changer.Select(_ => Unit.Default)
.ObserveOn(ImmediateScheduler.Instance)
.SubscribeOn(ImmediateScheduler.Instance)
.Subscribe(fixture.ObservableStateVoidProvider);

while (!completed) ;

Expand Down Expand Up @@ -319,7 +421,10 @@ public void TestStateObservableException()

var changer = Observable.Throw<Unit>(new InvalidOperationException("Test"));

var disposable = changer.Select(_ => Unit.Default).Subscribe(fixture.ObservableStateVoidProvider);
var disposable = changer
.ObserveOn(ImmediateScheduler.Instance)
.SubscribeOn(ImmediateScheduler.Instance)
.Select(_ => Unit.Default).Subscribe(fixture.ObservableStateVoidProvider);

while (!exception) ;

Expand Down
2 changes: 1 addition & 1 deletion RxMudBlazorLight/RxMudBlazorLight.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<PackageTags>Blazor,MudBlazor,Rx,Reactive</PackageTags>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageOutputPath>..\Nuget</PackageOutputPath>
<PackageVersion>0.9.5</PackageVersion>
<PackageVersion>0.9.6</PackageVersion>
</PropertyGroup>

<ItemGroup>
Expand Down

0 comments on commit 0cb4108

Please sign in to comment.