-
Notifications
You must be signed in to change notification settings - Fork 934
Enable no-floating-promises lint check and fix / suppress violations. #1087
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
Conversation
/** | ||
* Adds a new operation to the queue. Returns a promise that will be resolved | ||
* when the promise returned by the new operation is (with its value). | ||
*/ | ||
enqueue<T extends Unknown>(op: () => Promise<T>): Promise<T> { | ||
enqueueAndWait<T extends Unknown>(op: () => Promise<T>): Promise<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The common case (and thus most likely to have a parallel on the other platforms) would be to enqueue without dropping the promise, no?
If so I'd prefer we continue to name this enqueue and call the somewhat danergous enqueue and drop promise something else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually there is no enqueueAndWait() on the other platforms (dispatchAsync on iOS and enqueue on Android both return void and don't block). Instead you have to monkey with completions / TaskCompletionSource to plumb the async operation result back to the caller.
enableNetwork on web:
enableNetwork(): Promise<void> {
return this.asyncQueue.enqueueAndWait(() => {
return this.remoteStore.enableNetwork();
});
}
enableNetwork on iOS:
- (void)enableNetworkWithCompletion:(nullable FSTVoidErrorBlock)completion {
[self.workerDispatchQueue dispatchAsync:^{
[self.remoteStore enableNetwork];
if (completion) {
self->_userExecutor->Execute([=] { completion(nil); });
}
}];
}
enableNetwork on Android:
public Task<Void> enableNetwork() {
final TaskCompletionSource<Void> source = new TaskCompletionSource<>();
asyncQueue.enqueue(
() -> {
remoteStore.enableNetwork();
source.setResult(null);
});
return source.getTask();
}
So I think enqueue() is arguably the common case and is named consistently with the other platforms.
Also, I can't think of a good name if I make enqueue() the "blocking" one. enqueueAndForget()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I consider enqueue-that-returns-a-promise on web to be equivalent to enqueue-that-plumbs-through-callbacks on iOS and equivalent to enqueue-with-a-manually-wrapping TaskCompletionSource on Android.
We could have Android's enqueue do the TaskCompletionSource monkeying as well (TaskCompletionSource being the equivalent of a Promise), which would bring it further into line with web.
In any case, I think we generally want to tie actions enqueued with a user-visible promise so this should be be the shorter, more obvious name.
Regarding naming: enqueueAndWait suggests actually waiting, which isn't what's happening. Meanwhile enqueueAndForget seems to reasonably suggest what it's doing to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough. Renamed!
I'll take a look at the Android change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@@ -435,7 +435,9 @@ export class FirestoreClient { | |||
|
|||
write(mutations: Mutation[]): Promise<void> { | |||
const deferred = new Deferred<void>(); | |||
this.asyncQueue.enqueue(() => this.syncEngine.write(mutations, deferred)); | |||
this.asyncQueue.enqueueAndForget(() => | |||
this.syncEngine.write(mutations, deferred) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could syncEngine hide this Deferred?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not quite. The spec tests need to be able to wait for the write() to complete locally without waiting for the user callback (after the server ack of the write). So there are two separate async things you might want to wait on.
@@ -396,6 +396,7 @@ export class IndexedDbPersistence implements Persistence { | |||
|
|||
// Attempt graceful shutdown (including releasing our owner lease), but | |||
// there's no guarantee it will complete. | |||
// tslint:disable-next-line:no-floating-promises | |||
this.shutdown(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This runs on the queue in the multi-tab branch. Should we change it here to also use enqueueAndForget
?
This code is somewhat untested and I am a little afraid of its raciness if we don't enqueue it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried but we don't have access to the async queue here right now. Maybe you should get around to merging multi-tab. 😛
new FirestoreError(Code.UNAUTHENTICATED, '') | ||
); | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason you added the extra .then()
instead of using await
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. If I changed this then() callback to async/await then I'd feel compelled to convert the whole test, and then I'd feel compelled to convert the whole file, and at that point I may as well go ahead and convert the rest of our codebase. At that point I'd be so good at it I might as well start tackling other open source projects. And then I'd never get anything done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm disinclined to acquiesce to your requests. Thanks anyway!
@@ -435,7 +435,9 @@ export class FirestoreClient { | |||
|
|||
write(mutations: Mutation[]): Promise<void> { | |||
const deferred = new Deferred<void>(); | |||
this.asyncQueue.enqueue(() => this.syncEngine.write(mutations, deferred)); | |||
this.asyncQueue.enqueueAndForget(() => | |||
this.syncEngine.write(mutations, deferred) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not quite. The spec tests need to be able to wait for the write() to complete locally without waiting for the user callback (after the server ack of the write). So there are two separate async things you might want to wait on.
@@ -396,6 +396,7 @@ export class IndexedDbPersistence implements Persistence { | |||
|
|||
// Attempt graceful shutdown (including releasing our owner lease), but | |||
// there's no guarantee it will complete. | |||
// tslint:disable-next-line:no-floating-promises | |||
this.shutdown(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried but we don't have access to the async queue here right now. Maybe you should get around to merging multi-tab. 😛
new FirestoreError(Code.UNAUTHENTICATED, '') | ||
); | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. If I changed this then() callback to async/await then I'd feel compelled to convert the whole test, and then I'd feel compelled to convert the whole file, and at that point I may as well go ahead and convert the rest of our codebase. At that point I'd be so good at it I might as well start tackling other open source projects. And then I'd never get anything done.
I noticed that we were failing to wait for promises in a couple places so I enabled no-floating-promises lint check and cleaned up all the violations. To make this a bit easier I introduced enqueue() vs enqueueAndWait() on the AsyncQueue, with the former returning void instead of a Promise.