             }
         }
         
-        // Return a dummy observer, because read-only ValueObservation
-        // never changes.
-        return DummyObserver()
+        return observer
     }
 }
 
+// TODO: remove when we have proper support for cancellation
 /// Support for DatabaseReader.addReadonly(observation:onError:onChange:)
 private class DummyObserver: TransactionObserver {
     func observes(eventsOfKind eventKind: DatabaseEventKind) -> Bool { false }

                onError(error)
            }
        } else {
            asyncRead { dbResult in
                let result = dbResult.tryMap(observation.fetchValue)
                scheduler.impl.schedule {
                    do {
                        try onChange(result.get())
                    } catch {

        onChange: @escaping (Reducer.Value) -> Void)
        -> TransactionObserver
    {
        // A dummy observer is enough, because read-only ValueObservation
        // never changes.
        let observer = DummyObserver()
        
        if scheduler.impl.fetchOnStart() {
            do {
                try onChange(unsafeReentrantRead(observation.fetchValue))
