Skip to content

Commit

Permalink
Supports .NET 5 (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
tommasobertoni committed Dec 1, 2020
2 parents 8dac46c + c4e9611 commit 28cb61a
Show file tree
Hide file tree
Showing 34 changed files with 427 additions and 379 deletions.
65 changes: 56 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,45 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
- name: Setup .NET
uses: actions/setup-dotnet@v1.7.2
with:
dotnet-version: 3.1.x
dotnet-version: 5.0.x
- name: Install dependencies
run: dotnet restore src/NScatterGather/NScatterGather.csproj
- name: Build
run: dotnet build src/NScatterGather/NScatterGather.csproj -c Release --no-restore

test:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup .NET 5 SDK and runtime
uses: actions/setup-dotnet@v1.7.2
with:
dotnet-version: 5.0.x
- name: Tests net5.0 on .NET 5
run: |
dotnet build src/NScatterGather/NScatterGather.csproj -c Release --framework net5.0
dotnet build tests/NScatterGather.Tests/NScatterGather.Tests.csproj -c Release --framework net5.0
dotnet test --no-build --verbosity normal -c Release --framework net5.0
test-netcore:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup .NET Core 3.1
uses: actions/setup-dotnet@v1
- name: Setup .NET 5 SDK
uses: actions/setup-dotnet@v1.7.2
with:
dotnet-version: 5.0.x
- name: Setup .NET 3.1 runtime
uses: actions/setup-dotnet@v1.7.2
with:
dotnet-version: 3.1.x
- name: Setup .NET Core 2.1
uses: actions/setup-dotnet@v1
- name: Setup .NET 2.1 runtime
uses: actions/setup-dotnet@v1.7.2
with:
dotnet-version: 2.1.x
- name: Tests netstandard2.1 on .NET Core 3.1
Expand All @@ -44,15 +63,43 @@ jobs:
dotnet build tests/NScatterGather.Tests/NScatterGather.Tests.csproj -c Release --framework netcoreapp2.1
dotnet test --no-build --verbosity normal -c Release --framework netcoreapp2.1
test-netframework:
test-netframework-legacy:
needs: build
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Setup .NET Framework
- name: Setup .NET 5 SDK
uses: actions/setup-dotnet@v1.7.2
with:
dotnet-version: 5.0.x
- name: Setup .NET Framework runtime
uses: microsoft/setup-msbuild@v1.0.2
- name: Tests netstandard2.0 on .NET Framework 4.6.1
run: |
dotnet build src/NScatterGather/NScatterGather.csproj -c Release --framework netstandard2.0
dotnet build tests/NScatterGather.Tests/NScatterGather.Tests.csproj -c Release --framework net461
dotnet test --no-build --verbosity normal -c Release --framework net461
coverage:
if: ${{ github.event_name == 'push' }}
needs: [test, test-netcore, test-netframework-legacy]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1.7.2
with:
dotnet-version: 5.0.x
- run: dotnet build -c Debug src/NScatterGather/NScatterGather.csproj
- run: dotnet build -c Debug tests/NScatterGather.Tests/NScatterGather.Tests.csproj --framework net5.0
- name: Collect coverage
run: dotnet test -c Debug --framework net5.0 /p:CollectCoverage=true /p:CoverletOutput=coverage/ /p:CoverletOutputFormat=lcov
- name: Upload coverage artifacts
uses: actions/upload-artifact@v2
with:
name: coverage.info
path: tests/NScatterGather.Tests/coverage/coverage.net5.0.info
- name: Upload to Coveralls.io
uses: coverallsapp/github-action@v1.1.2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: tests/NScatterGather.Tests/coverage/coverage.net5.0.info
16 changes: 11 additions & 5 deletions .github/workflows/pack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1
with:
dotnet-version: 3.1.x
- run: dotnet restore src/NScatterGather/NScatterGather.csproj
- run: dotnet build src/NScatterGather/NScatterGather.csproj -c Release --no-restore
- name: Install .NET 5
run: |
sudo wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get install -y apt-transport-https && \
sudo apt-get update && \
sudo apt-get install -y dotnet-sdk-5.0
- name: Install dependencies
run: dotnet restore src/NScatterGather/NScatterGather.csproj
- name: Build
run: dotnet build src/NScatterGather/NScatterGather.csproj -c Release --no-restore
- name: Install requirements
run: |
sudo apt-get install -y unzip
Expand Down
25 changes: 13 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ This pattern helps to limit the coupling between the consumer and the recipients

The recipients compete in order to provide the best, or the fastest, response to the request. The consumer will then pick the best value from the aggregated response.

_e.g._ Get an item's price from a collection of suppliers:
[sample:](samples/NScatterGather.Samples.CompetingTasks/) get an item's best price from a collection of suppliers:

![competing-tasks-diagram](assets/images/competing-tasks-diagram.png)

## Task parallelization

Different operations are computed concurrently, and their results combined or used together. The result types could be different.

_e.g._ Get a user's data from different services, and then compose a view model:
[sample:](samples/NScatterGather.Samples.TaskParallelization/) get a user's data from different services, and then compose into a model:

![tasks-parallelization-diagram](assets/images/tasks-parallelization-diagram.png)
![tasks-parallelization-diagram](assets/images/task-parallelization-diagram.png)

# How to use
Use a `RecipientsCollection` to register the eligible recipients:
Expand All @@ -73,15 +73,16 @@ var aggregator = new Aggregator(collection);
AggregatedResponse<object> objects = await aggregator.Send(42);

// The following overload can be used when
// the return type is either known or binding:
// the return type is either known or binding.
// Only the recipients that accept an int and
// return a string will be invoked:
AggregatedResponse<string> strings = await aggregator.Send<int, string>(42);

// In the second case, only the recipients that accept
// an int and return a string will be invoked.
```

Inspect the `AggregatedResponse` containing the results of the scatter-gather operation, grouped by completed, faulted and incomplete:
Inspect the `AggregatedResponse` containing the results of the scatter-gather operation, grouped by _completed_, _faulted_ and _incomplete_:
```csharp
var response = await aggregator.Send<int, string>(42, cancellationToken);

var completed = response.Completed[0];
// (Type recipientType, string result) = completed;
Expand All @@ -104,10 +105,10 @@ class Foo

class Bar
{
public Task<string> ThisIsInvokedToo(int n) => Task.FromResult(n.ToString());
public int ThisIsInvokedToo(int n) => n * 2;
}

// Invoke each recipient that accepts an int.
// Invoke every recipient that accepts an int.
_ = await aggregator.Send(42);
```

Expand All @@ -117,7 +118,7 @@ _ = await aggregator.Send(42);

The `Aggregator` exposes async-only methods for sending requests.

Even if the consumer requested only results of type `TResponse`, a recipient that returns `Task<TResponse>` (or `ValueTask<TResponse>`) will still be invoked and its result awaited:
Even if the consumer requested only results of type `TResponse`, a recipient that returns `Task<TResponse>`, or `ValueTask<TResponse>`, or any task-like type, will still be invoked and its result awaited:

```csharp
class Foo { public int Echo(int n) => n; }
Expand Down Expand Up @@ -174,7 +175,7 @@ class Foo { public string Stringify(int n) => n.ToString(); }

class Bar
{
public Task<long> Longify(int n)
public async Task<long> Longify(int n)
{
await Task.Yield();
return n * 1L;
Expand Down
Binary file modified assets/images/competing-tasks-diagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/competing-tasks-sample.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/task-parallelization-diagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed assets/images/tasks-parallelization-diagram.png
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
Expand All @@ -12,4 +12,8 @@
<ProjectReference Include="..\..\src\NScatterGather\NScatterGather.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Spectre.Console" Version="0.31.0" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,18 +1,5 @@

namespace NScatterGather.Samples.CompetingTasks
{
class Product
{
public string Id { get; }

public string Name { get; }

public Product(
string id,
string name)
{
Id = id;
Name = name;
}
}
record Product(string Id, string Name);
}
Loading

0 comments on commit 28cb61a

Please sign in to comment.