Skip to content

[Repo Assist] Add AsyncSeq.withCancellation (design parity with TaskSeq, #277)#278

Draft
github-actions[bot] wants to merge 2 commits intomainfrom
repo-assist/fix-issue-277-withcancellation-28eaf2827bc5b11a
Draft

[Repo Assist] Add AsyncSeq.withCancellation (design parity with TaskSeq, #277)#278
github-actions[bot] wants to merge 2 commits intomainfrom
repo-assist/fix-issue-277-withcancellation-28eaf2827bc5b11a

Conversation

@github-actions
Copy link
Contributor

🤖 This PR was created by Repo Assist, an automated AI assistant.

Summary

Adds AsyncSeq.withCancellation, which returns a new AsyncSeq<'T> that passes a given CancellationToken to GetAsyncEnumerator, overriding whatever token would otherwise be supplied by the caller.

This mirrors TaskSeq.withCancellation and is part of the ongoing design-parity effort tracked in #277.

Motivation

When consuming IAsyncEnumerable<'T> sequences from external libraries (e.g. Entity Framework Core), the library often uses the token passed to GetAsyncEnumerator for cancellation. Previously there was no direct way to inject a specific token into an AsyncSeq pipeline. withCancellation fills this gap.

Implementation

let withCancellation (cancellationToken: CancellationToken) (source: AsyncSeq<'T>) : AsyncSeq<'T> =
    { new IAsyncEnumerable<'T> with
        member _.GetAsyncEnumerator(_ct) = source.GetAsyncEnumerator(cancellationToken) }

This is the same approach as TaskSeq.withCancellation: wrap the source in a new IAsyncEnumerable<'T> that ignores the incoming token and passes the specified one instead. Simple, zero-allocation wrapper (beyond the object allocation for the interface).

Changes

  • src/FSharp.Control.AsyncSeq/AsyncSeq.fs — implementation (inside #if !FABLE_COMPILER)
  • src/FSharp.Control.AsyncSeq/AsyncSeq.fsi — public signature with XML-doc
  • tests/FSharp.Control.AsyncSeq.Tests/AsyncSeqTests.fs — 4 new tests
  • RELEASE_NOTES.md — 4.10.0 entry
  • version.props — bumped to 4.10.0

Design Parity Research

As part of researching #277, here is a summary of the broader gap between TaskSeq and AsyncSeq. Items in TaskSeq but missing from AsyncSeq (highest priority first):

Function Notes
withCancellation ✅ Added in this PR
partition / partitionAsync Split into two arrays by predicate
compareWith / compareWithAsync Lexicographic sequence comparison
tryTail Safe tail returning option
skipWhileInclusive / skipWhileInclusiveAsync Mirrors existing takeWhileInclusive
takeWhileInclusiveAsync Async variant of existing takeWhileInclusive
appendSeq / prependSeq Convenience: append/prepend seq<'T>
collectAsync Async variant of collect (bind)
delay Delay sequence creation
lengthBy / lengthByAsync / lengthOrMax Count with projection / capped count
insertManyAt / removeManyAt Bulk insert/remove
where / whereAsync Aliases for filter/filterAsync

Note: AsyncSeq has richer reactive/event-stream features not present in TaskSeq (observables, channels, merge/interleave, combineLatest, parallel map/iter, zapp, cache, etc.) — these are intentional additions that reflect AsyncSeq's broader use cases.

Test Status

✅ Build succeeded (0 errors, pre-existing warnings only — NU1605, FS9999 for groupByAsync, FS0044 for deprecated toAsyncEnum/ofAsyncEnum in existing tests).

✅ All 321 tests pass (dotnet test FSharp.Control.AsyncSeq.sln).

Generated by Repo Assist for issue #277 ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@346204513ecfa08b81566450d7d599556807389f

Adds AsyncSeq.withCancellation, which returns a new AsyncSeq<'T> that
passes the given CancellationToken to GetAsyncEnumerator, overriding
whatever token would otherwise be supplied during iteration.

This mirrors TaskSeq.withCancellation and is useful when consuming
sequences from libraries (e.g. Entity Framework) that accept a
CancellationToken through GetAsyncEnumerator.

Closes #277 (partial - withCancellation addressed; further design parity
investigation tracked in the issue).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

We want design parity with FSharp.Control.TaskSeq

0 participants