Skip to content

[Observations] Subsequent iteration on Observations receives double values #85683

@bernoulliconvergenator

Description

@bernoulliconvergenator

Description

After cancelling a Task containing an iteration over an Observations, a second iteration in a new Task over the same Observations receives new values twice.

Reproduction

@MainActor @Observable final class TickerODMO {
   private(set) var tick: Int = 0
   @ObservationIgnored private var tickerTask: Task<Void, Error>?

   func startTicking() {
      guard tickerTask == nil else { return }
      tickerTask = Task {
         while !Task.isCancelled {
            try await Task.sleep(for: .milliseconds(500))
            tick += 1
         }
      }
   }

   func stopTicking() {
      tickerTask?.cancel()
      tickerTask = nil
   }
}

@MainActor func observe(ticker: TickerODMO) async throws {
   let observations = Observations { ticker.tick }
   print("creating observer task 1")
   let task1 = Task {
      for await tick in observations {
         print("task 1 observed tick=\(tick)")
      }
   }
   print("starting ticker and sleeping for 2 seconds")
   ticker.startTicking()
   try await Task.sleep(for: .seconds(2))
   print("cancelling task 1, then sleeping for 3 seconds")
   task1.cancel()
   try await Task.sleep(for: .seconds(3))
   print("creating observer task 2")
   let task2 = Task {
      for await tick in observations {
         print("task 2 observed tick=\(tick)")
      }
   }
   try await Task.sleep(for: .seconds(3))
   task2.cancel()
   ticker.stopTicking()
}

Output:

creating observer task 1
starting ticker and sleeping for 2 seconds
task 1 observed tick=0
task 1 observed tick=1
task 1 observed tick=2
task 1 observed tick=3
cancelling task 1, then sleeping for 3 seconds
creating observer task 2
task 2 observed tick=9
task 2 observed tick=9
task 2 observed tick=10
task 2 observed tick=10
task 2 observed tick=11
task 2 observed tick=11
task 2 observed tick=12
task 2 observed tick=12
task 2 observed tick=13
task 2 observed tick=13
task 2 observed tick=14
task 2 observed tick=14
task 2 observed tick=15
task 2 observed tick=15

Expected behavior

The subsequent iteration in task2 should only receive each new value once.

Environment

swift-driver version: 1.127.14.1 Apple Swift version 6.2.1 (swiftlang-6.2.1.4.8 clang-1700.4.4.1)
Target: arm64-apple-macosx26.0

Xcode 26.1.1

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.triage neededThis issue needs more specific labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions