@@ -155,7 +155,8 @@ extension ValueWriteOnlyObserver {
155
155
( self . notificationCallbacks, self . databaseAccess)
156
156
}
157
157
guard let notificationCallbacks = notificationCallbacksOpt, let writer = databaseAccessOpt? . writer else {
158
- // Likely a GRDB bug
158
+ // Likely a GRDB bug: during a synchronous start, user is not
159
+ // able to cancel observation.
159
160
fatalError ( " can't start a cancelled or failed observation " )
160
161
}
161
162
@@ -198,7 +199,11 @@ extension ValueWriteOnlyObserver {
198
199
// from a database access.
199
200
try writer. unsafeReentrantWrite { db in
200
201
// Fetch & Start observing the database
201
- let fetchedValue = try fetchAndStartObservation ( db)
202
+ guard let fetchedValue = try fetchAndStartObservation ( db) else {
203
+ // Likely a GRDB bug: during a synchronous start, user is not
204
+ // able to cancel observation.
205
+ fatalError ( " can't start a cancelled or failed observation " )
206
+ }
202
207
203
208
// Reduce
204
209
return reduceQueue. sync {
@@ -218,12 +223,11 @@ extension ValueWriteOnlyObserver {
218
223
// Start from a write access, so that self can register as a
219
224
// transaction observer.
220
225
writer. asyncWriteWithoutTransaction { db in
221
- let isNotifying = self . lock. synchronized { self . notificationCallbacks != nil }
222
- guard isNotifying else { return /* Cancelled */ }
223
-
224
226
do {
225
227
// Fetch & Start observing the database
226
- let fetchedValue = try self . fetchAndStartObservation ( db)
228
+ guard let fetchedValue = try self . fetchAndStartObservation ( db) else {
229
+ return /* Cancelled */
230
+ }
227
231
228
232
// Reduce
229
233
//
@@ -257,17 +261,19 @@ extension ValueWriteOnlyObserver {
257
261
258
262
/// Fetches the initial value, and start observing the database.
259
263
///
264
+ /// Returns nil if the observation was cancelled before database observation
265
+ /// could start.
266
+ ///
260
267
/// By grouping the initial fetch and the beginning of observation in a
261
268
/// single database access, we are sure that no concurrent write can happen
262
269
/// during the initial fetch, and that we won't miss any future change.
263
- private func fetchAndStartObservation( _ db: Database ) throws -> Reducer . Fetched {
270
+ private func fetchAndStartObservation( _ db: Database ) throws -> Reducer . Fetched ? {
264
271
// TODO: [SR-214] remove -Opt suffix when we only support Xcode 12.5.1+
265
272
let ( eventsOpt, fetchOpt) = lock. synchronized {
266
273
( notificationCallbacks? . events, databaseAccess? . fetch)
267
274
}
268
275
guard let events = eventsOpt, let fetch = fetchOpt else {
269
- // Likely a GRDB bug
270
- fatalError ( " can't start a cancelled or failed observation " )
276
+ return nil /* Cancelled */
271
277
}
272
278
273
279
switch trackingMode {
0 commit comments