Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(firestore): support waitForPendingWrites() API #4176

Merged
merged 10 commits into from
Aug 30, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ Task<Void> clearPersistence(String appName) {
return getFirestoreForApp(appName).clearPersistence();
}

Task<Void> waitForPendingWrites(String appName) {
return getFirestoreForApp(appName).waitForPendingWrites();
}

Task<Void> terminate(String appName) {
FirebaseFirestore firebaseFirestore = getFirestoreForApp(appName);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@ public void clearPersistence(String appName, Promise promise) {
});
}

@ReactMethod
public void waitForPendingWrites(String appName, Promise promise) {
module.waitForPendingWrites(appName).addOnCompleteListener(task -> {
if (task.isSuccessful()) {
promise.resolve(null);
} else {
rejectPromiseFirestoreException(promise, task.getException());
}
});
}

@ReactMethod
public void disableNetwork(String appName, Promise promise) {
module.disableNetwork(appName).addOnCompleteListener(task -> {
Expand Down
54 changes: 54 additions & 0 deletions packages/firestore/e2e/firestore.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -364,4 +364,58 @@ describe('firestore()', () => {
}
});
});

describe('wait for pending writes', () => {
it('waits for pending writes', async () => {
const waitForPromiseMs = 500;
const testTimeoutMs = 10000;

await firebase.firestore().disableNetwork();

//set up a pending write

const db = firebase.firestore();
const id = 'foobar';
const ref = db.doc(`v6/${id}`);
ref.set({ foo: 'bar' });

//waitForPendingWrites should never resolve, but unfortunately we can only
//test that this is not returning within X ms
mikehardy marked this conversation as resolved.
Show resolved Hide resolved

let rejected = false;
const timedOutWithNetworkDisabled = await Promise.race([
firebase
.firestore()
.waitForPendingWrites()
.then(
() => false,
() => {
rejected = true;
},
),
Utils.sleep(waitForPromiseMs).then(() => true),
]);

should(timedOutWithNetworkDisabled).equal(true);
should(rejected).equal(false);

//if we sign in as a different user then it should reject the promise
await firebase.auth().signOut();
await firebase.auth().signInAnonymously();
should(rejected).equal(true);

//now if we enable the network then waitForPendingWrites should return immediately
await firebase.firestore().enableNetwork();

const timedOutWithNetworkEnabled = await Promise.race([
firebase
.firestore()
.waitForPendingWrites()
.then(() => false),
Utils.sleep(testTimeoutMs).then(() => true),
]);

should(timedOutWithNetworkEnabled).equal(false);
});
});
});
14 changes: 14 additions & 0 deletions packages/firestore/ios/RNFBFirestore/RNFBFirestoreModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,20 @@ + (BOOL)requiresMainQueueSetup {
}];
}

RCT_EXPORT_METHOD(waitForPendingWrites:
(FIRApp *) firebaseApp
: (RCTPromiseResolveBlock) resolve
: (RCTPromiseRejectBlock)reject
) {
[[RNFBFirestoreCommon getFirestoreForApp:firebaseApp] waitForPendingWritesWithCompletion:^(NSError *error) {
if (error) {
[RNFBFirestoreCommon promiseRejectFirestoreException:reject error:error];
} else {
resolve(nil);
}
}];
}

RCT_EXPORT_METHOD(terminate:
(FIRApp *) firebaseApp
: (RCTPromiseResolveBlock) resolve
Expand Down
18 changes: 18 additions & 0 deletions packages/firestore/lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1969,6 +1969,24 @@ export namespace FirebaseFirestoreTypes {
* ```
*/
clearPersistence(): Promise<void>;
/**
mikehardy marked this conversation as resolved.
Show resolved Hide resolved
* Waits until all currently pending writes for the active user have been acknowledged by the
* backend.
*
* The returned Promise resolves immediately if there are no outstanding writes. Otherwise, the
* Promise waits for all previously issued writes (including those written in a previous app
* session), but it does not wait for writes that were added after the method is called. If you
* want to wait for additional writes, call `waitForPendingWrites()` again.
*
* Any outstanding `waitForPendingWrites()` Promises are rejected when the logged-in user changes.
*
* #### Example
*
*```js
* await firebase.firestore().waitForPendingWrites();
* ```
*/
waitForPendingWrites(): Promise<void>;
/**
* Typically called to ensure a new Firestore instance is initialized before calling
* `firebase.firestore().clearPersistence()`.
Expand Down
4 changes: 4 additions & 0 deletions packages/firestore/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ class FirebaseFirestoreModule extends FirebaseModule {
await this.native.clearPersistence();
}

async waitForPendingWrites() {
await this.native.waitForPendingWrites();
}

async terminate() {
await this.native.terminate();
}
Expand Down