|
1 |
| -[](https://github.com/abelbraaksma/TaskSeq/actions/workflows/main.yaml) |
2 |
| -[](https://github.com/abelbraaksma/TaskSeq/actions/workflows/test.yaml) |
| 1 | +[![build][buildstatus_img]][buildstatus] |
| 2 | +[![test][teststatus_img]][teststatus] |
3 | 3 |
|
4 | 4 | # TaskSeq
|
5 |
| -An implementation [`IAsyncEnumerable<'T>`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerable-1?view=net-7.0) as a `taskSeq` CE for F# with accompanying `TaskSeq` module. |
| 5 | +An implementation [`IAsyncEnumerable<'T>`][3] as a `taskSeq` CE for F# with accompanying `TaskSeq` module. |
6 | 6 |
|
7 |
| -The `IAsyncEnumerable` interface was added to .NET in `.NET Core 3.0` and is part of `.NET Standard 2.1`. The main use-case was for iterative asynchronous enumeration over some resource. For instance, an event stream or a REST API interface with pagination, where each page is a [`MoveNextAsync`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerator-1.movenextasync?view=net-7.0) call on the [`IAsyncEnumerator<'T>`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerator-1?view=net-7.0) given by a call to [`GetAsyncEnumerator()`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerable-1.getasyncenumerator?view=net-7.0). It has been relatively challenging to work properly with this type and dealing with each step being asynchronous, and the enumerator implementing [`IAsyncDisposable`](https://learn.microsoft.com/en-us/dotnet/api/system.iasyncdisposable?view=net-7.0) as well, which requires careful handling. |
| 7 | +The `IAsyncEnumerable` interface was added to .NET in `.NET Core 3.0` and is part of `.NET Standard 2.1`. The main use-case was for iterative asynchronous enumeration over some resource. For instance, an event stream or a REST API interface with pagination, where each page is a [`MoveNextAsync`][4] call on the [`IAsyncEnumerator<'T>`][5] given by a call to [`GetAsyncEnumerator()`][6]. It has been relatively challenging to work properly with this type and dealing with each step being asynchronous, and the enumerator implementing [`IAsyncDisposable`][7] as well, which requires careful handling. |
8 | 8 |
|
9 |
| -A good C#-based introduction on `IAsyncEnumerable` [can be found in this blog](https://stu.dev/iasyncenumerable-introduction/). Another resource is [this MSDN article shortly after its introductiono](https://learn.microsoft.com/en-us/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8). |
| 9 | +A good C#-based introduction on `IAsyncEnumerable` [can be found in this blog][8]. Another resource is [this MSDN article shortly after its introductiono][9]. |
| 10 | + |
| 11 | +## Building & testing |
| 12 | + |
| 13 | +TLDR: just run `build`. Or load the `sln` file in Visual Studio or VS Code and compile. |
| 14 | + |
| 15 | +### Prerequisites |
| 16 | + |
| 17 | +* .NET 6 or .NET 7 Preview |
| 18 | +* F# 6.0 compiler |
| 19 | +* To use `build.cmd`, the `dotnet` command must be accessible from your path. |
| 20 | + |
| 21 | +Just checkout this repo locally. Then, from the root of the repo, you can do: |
| 22 | + |
| 23 | +### Build the solution |
| 24 | + |
| 25 | +``` |
| 26 | +build [release|debug] |
| 27 | +``` |
| 28 | + |
| 29 | +### Run the tests |
| 30 | + |
| 31 | +``` |
| 32 | +build test [release|debug] |
| 33 | +``` |
| 34 | + |
| 35 | +By default, all tests are output to the console. If you don't want that, you can use `--logger console;verbosity=summary`. |
| 36 | +Furthermore, no TRX file is generated and the `--blame-xxx` flags aren't set. |
| 37 | + |
| 38 | +### Run the CI command |
| 39 | + |
| 40 | +``` |
| 41 | +build ci [release|debug] |
| 42 | +``` |
| 43 | + |
| 44 | +This will run `dotnet test` with the `--blame-xxx` settings enabled to [prevent hanging tests][1] caused by |
| 45 | +an [xUnit runner bug][2]. |
| 46 | + |
| 47 | +### Advanced |
| 48 | + |
| 49 | +You can pass any additional options that are valid for `dotnet test` and `dotnet build` respectively. However, |
| 50 | +these cannot be the very first argument, so you should either use `build build --myadditionalOptions fizz buzz`, or |
| 51 | +just specify the build-kind, i.e. this is fine: |
| 52 | + |
| 53 | +``` |
| 54 | +build debug --verbosity detailed |
| 55 | +build test --logger console;verbosity=summary |
| 56 | +``` |
| 57 | + |
| 58 | +At this moment, additional options cannot have quotes in them. |
| 59 | + |
| 60 | +Command modifiers, like `release` and `debug`, can be specified with `-` or `/` if you so prefer: `dotnet build /release`. |
| 61 | + |
| 62 | +### Get help (duh!) |
| 63 | + |
| 64 | +``` |
| 65 | +build help |
| 66 | +``` |
| 67 | + |
| 68 | +For more info, see this PR: https://github.com/abelbraaksma/TaskSeq/pull/29. |
10 | 69 |
|
11 | 70 | ## In progress!!!
|
12 | 71 |
|
13 |
| -It's based on [Don Symes `taskSeq.fs`](https://github.com/dotnet/fsharp/blob/d5312aae8aad650f0043f055bb14c3aa8117e12e/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerf/taskSeq.fs) |
| 72 | +It's based on [Don Symes `taskSeq.fs`][10] |
14 | 73 | but expanded with useful utility functions and a few extra binding overloads.
|
15 | 74 |
|
16 | 75 | ## Short-term feature planning
|
@@ -307,3 +366,19 @@ module TaskSeq =
|
307 | 366 | val foldAsync: folder: ('State -> 'T -> #Task<'State>) -> state: 'State -> taskSeq: taskSeq<'T> -> Task<'State>
|
308 | 367 |
|
309 | 368 | ```
|
| 369 | + |
| 370 | +[buildstatus]: https://github.com/abelbraaksma/TaskSeq/actions/workflows/main.yaml |
| 371 | +[buildstatus_img]: https://github.com/abelbraaksma/TaskSeq/actions/workflows/main.yaml/badge.svg |
| 372 | +[teststatus]: https://github.com/abelbraaksma/TaskSeq/actions/workflows/test.yaml |
| 373 | +[teststatus_img]: https://github.com/abelbraaksma/TaskSeq/actions/workflows/test.yaml/badge.svg |
| 374 | + |
| 375 | +[1]: https://github.com/abelbraaksma/TaskSeq/issues/25 |
| 376 | +[2]: https://github.com/xunit/xunit/issues/2587 |
| 377 | +[3]: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerable-1?view=net-7.0 |
| 378 | +[4]: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerator-1.movenextasync?view=net-7.0 |
| 379 | +[5]: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerator-1?view=net-7.0 |
| 380 | +[6]: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerable-1.getasyncenumerator?view=net-7.0 |
| 381 | +[7]: https://learn.microsoft.com/en-us/dotnet/api/system.iasyncdisposable?view=net-7.0 |
| 382 | +[8]: https://stu.dev/iasyncenumerable-introduction/ |
| 383 | +[9]: https://learn.microsoft.com/en-us/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8 |
| 384 | +[10]: https://github.com/dotnet/fsharp/blob/d5312aae8aad650f0043f055bb14c3aa8117e12e/tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerf/taskSeq.fs |
0 commit comments