Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,16 @@ public Task<Result<Unit, ScrapeError>> RunAsync(CancellationToken cancellationTo

private async Task<Result<Unit, ScrapeError>> ProcessSearchCategoriesAsync(IReadOnlyList<Category> searchCategories, CancellationToken cancellationToken)
{
Result<Unit, ScrapeError> outcome = Unit.Value;

foreach (var searchCategory in searchCategories)
{
cancellationToken.ThrowIfCancellationRequested();

var categoryResult = await ProcessSearchCategoryAsync(searchCategory, cancellationToken).ConfigureAwait(false);
bool categoryFailed = categoryResult.Match(_ => false, _ => true);

if (categoryFailed) return categoryResult;
outcome = await outcome.BindAsync(_ => ProcessSearchCategoryAsync(searchCategory, cancellationToken)).ConfigureAwait(false);
}

return Unit.Value;
return outcome;
}

private Task<Result<Unit, ScrapeError>> ProcessSearchCategoryAsync(Category searchCategory, CancellationToken cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,9 @@ private async Task<Result<Unit, ScrapeError>> RunSubscriptionsAsync(Cancellation
}

private async Task LoadStartingPageAsync()
{
var loadResult = await subscriptionsImagesListPage.LoadSubscriptionResultsPageAsync(FirstPageNumber).ConfigureAwait(false);
bool loadedSuccessfully = loadResult.Match(_ => true, _ => false);

if (!loadedSuccessfully) _ = await subscriptionsImagesListPage.LoadSubscriptionResultsPageAsync(FirstPageNumber).ConfigureAwait(false);
}
=> _ = await subscriptionsImagesListPage.LoadSubscriptionResultsPageAsync(FirstPageNumber)
.OrElseAsync(_ => subscriptionsImagesListPage.LoadSubscriptionResultsPageAsync(FirstPageNumber))
.ConfigureAwait(false);

private async Task<Result<Unit, ScrapeError>> ProcessSubscriptionsAsync(PageInfo pageInfo, CancellationToken cancellationToken)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,9 @@ private async Task<Result<Unit, ScrapeError>> RunTopWallpapersAsync(Cancellation
}

private async Task LoadStartingPageAsync(int startingPageNumber)
{
var loadResult = await topWallpapersPage.LoadTopWallpapersPageAsync(startingPageNumber).ConfigureAwait(false);
bool loadedSuccessfully = loadResult.Match(_ => true, _ => false);

if (!loadedSuccessfully) _ = await topWallpapersPage.LoadTopWallpapersPageAsync(FirstPageNumber).ConfigureAwait(false);
}
=> _ = await topWallpapersPage.LoadTopWallpapersPageAsync(startingPageNumber)
.OrElseAsync(_ => topWallpapersPage.LoadTopWallpapersPageAsync(FirstPageNumber))
.ConfigureAwait(false);

private async Task<Result<Unit, ScrapeError>> ProcessTopWallpapersAsync(SearchConfiguration searchConfiguration, CancellationToken cancellationToken)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using Shouldly;
using Xunit;

namespace AStar.Dev.FunctionalParadigm.Tests.Unit;

public class GivenOrElseAsync
{
[Fact]
public async Task when_result_is_success_then_returns_original_without_invoking_fallback()
{
var resultTask = Task.FromResult(Result.Success<int, string>(42));
bool invoked = false;

var actual = await resultTask.OrElseAsync(_ =>
{
invoked = true;

return Task.FromResult(Result.Success<int, string>(0));
});

actual.ShouldBe(new Ok<int, string>(42));
invoked.ShouldBeFalse();
}

[Fact]
public async Task when_result_is_failure_then_returns_fallback_result()
{
var resultTask = Task.FromResult(Result.Failure<int, string>("first failed"));

var actual = await resultTask.OrElseAsync(_ => Task.FromResult(Result.Success<int, string>(7)));

actual.ShouldBe(new Ok<int, string>(7));
}

[Fact]
public async Task when_result_is_failure_then_fallback_receives_original_error()
{
var resultTask = Task.FromResult(Result.Failure<int, string>("original error"));
string? receivedError = null;

_ = await resultTask.OrElseAsync(error =>
{
receivedError = error;

return Task.FromResult(Result.Success<int, string>(1));
});

receivedError.ShouldBe("original error");
}

[Fact]
public async Task when_result_and_fallback_both_fail_then_returns_fallback_failure()
{
var resultTask = Task.FromResult(Result.Failure<int, string>("first failed"));

var actual = await resultTask.OrElseAsync(_ => Task.FromResult(Result.Failure<int, string>("fallback failed")));

actual.ShouldBe(new Fail<int, string>("fallback failed"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@ public static Result<TMapped, TError> Bind<TResult, TMapped, TError>(this Result
_ => throw new InvalidOperationException("Unexpected result type.")
};

public static async Task<Result<TResult, TError>> OrElseAsync<TResult, TError>(this Task<Result<TResult, TError>> resultTask, Func<TError, Task<Result<TResult, TError>>> fallback)
=> await resultTask.ConfigureAwait(false) switch
{
Ok<TResult, TError> ok => ok,
Fail<TResult, TError> fail => await fallback(fail.Error).ConfigureAwait(false),
_ => throw new InvalidOperationException("Unexpected result type.")
};

public static Result<TResult, TError> Ensure<TResult, TError>(this Result<TResult, TError> result, Action finallyAction)
{
finallyAction();
Expand Down
Loading