Page MenuHomePhabricator

[native] implement method to run synchronous cancellable task in CommCoreModule
ClosedPublic

Authored by kamil on Nov 9 2022, 2:57 AM.
Tags
None
Referenced Files
Unknown Object (File)
Sun, Nov 10, 11:03 PM
Unknown Object (File)
Sun, Nov 10, 6:16 AM
Unknown Object (File)
Wed, Oct 30, 7:46 AM
Unknown Object (File)
Oct 25 2024, 5:17 PM
Unknown Object (File)
Oct 25 2024, 5:17 PM
Unknown Object (File)
Oct 25 2024, 5:17 PM
Unknown Object (File)
Oct 25 2024, 5:17 PM
Unknown Object (File)
Oct 25 2024, 5:17 PM

Details

Summary

context: ENG-2139

Introduced scheduleOrRunCancellable which will allow scheduling a task from the synchronous call that could be canceled while atomic flag in database singleton tasksCancelled will be set to true.

Using the error message as constant TASK_CANCELLED not a meaningful string because later in javascript we will need to indicate an error only by detecting if its message is equal to a given string or contain a given string.

Test Plan
  1. Build app for both iOS and Android
  2. Add changes with CommCoreModule methods which will simplify testing: D5582
  3. Run this code to check if this works as supposed to:
try {
  commCoreModule.printMessageAndWaitSync('sync task 1');
} catch (e) {
  console.log('caught: ', e);
}
try {
  commCoreModule.printMessageAndWaitSync('sync task 2');
} catch (e) {
  console.log('caught: ', e);
}
try {
  await commCoreModule.cancelTasks();
} catch (e) {
  console.log('caught: ', e);
}
try {
  commCoreModule.printMessageAndWaitSync('sync task 3');
} catch (e) {
  console.log('caught: ', e);
}
try {
  commCoreModule.printMessageAndWaitSync('sync task 4');
} catch (e) {
  console.log('caught: ', e);
}
try {
  await commCoreModule.runTasks();
} catch (e) {
  console.log('caught: ', e);
}
try {
  commCoreModule.printMessageAndWaitSync('sync task 5');
} catch (e) {
  console.log('caught: ', e);
}

result:

2022-11-09 14:17:50.568369+0100 Comm[88845:5799175] COMM: Starting sync task: sync task 1
2022-11-09 14:17:50.572780+0100 Comm[88845:5799175] COMM: Ending sync task: sync task 1
2022-11-09 14:17:50.579646+0100 Comm[88845:5799175] COMM: Starting sync task: sync task 2
2022-11-09 14:17:50.582453+0100 Comm[88845:5799175] COMM: Ending sync task: sync task 2
2022-11-09 14:17:50.631433+0100 Comm[88845:5799137] [javascript] 'caught: ', [Error: Exception in HostFunction: TASK_CANCELLED]
2022-11-09 14:17:50.631909+0100 Comm[88845:5799137] [javascript] 'caught: ', [Error: Exception in HostFunction: TASK_CANCELLED]
2022-11-09 14:17:51.078927+0100 Comm[88845:5799175] COMM: Starting sync task: sync task 5
2022-11-09 14:17:51.082612+0100 Comm[88845:5799175] COMM: Ending sync task: sync task 5

Diff Detail

Repository
rCOMM Comm
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

kamil held this revision as a draft.
kamil published this revision for review.Nov 9 2022, 5:30 AM
native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
22 ↗(On Diff #18255)

Are there really no other callsites we need to update from scheduleOrRun to scheduleOrRunCancellable?

native/ios/Comm/GlobalDBSingleton.mm
31 ↗(On Diff #18255)

Shouldn't this be scheduleOrRunCancellableCommonImpl?

native/ios/Comm/GlobalDBSingleton.mm
31 ↗(On Diff #18255)

It might be confusing here but we should use scheduleOrRunCommonImpl here. If we dispatch database task on the main queue it means that GlobalDBSingleton was called on iOS before JavaScript started (before CommCoreModule was created/before we enabled multithreading). Task cancellation takes place when clearSensitiveData is called in JavaScript which means we need to have CommCoreModule and multithreading enabled to call it.

native/cpp/CommonCpp/NativeModules/InternalModules/GlobalDBSingleton.h
24 ↗(On Diff #18255)

I think the order here is confusing for the reader. It would be better to either move call to task() from line 38 to be below this if statement, or to move this if statement to be just above the call to task().

native/ios/Comm/GlobalDBSingleton.mm
31 ↗(On Diff #18255)

Your point seems to be "there's no reason to make the task cancellable, since the only case for main-queue execution is on iOS before the JS thread starts, which means clearSensitiveData won't be called". But in the future, perhaps it's possible that some other code (eg. C++ code) will call clearSensitiveData.

Is there any downside to using scheduleOrRunCancellableCommonImpl here?

native/ios/Comm/GlobalDBSingleton.mm
31 ↗(On Diff #18255)

There are not technical downsides of calling scheduleOrRunCancellableCommonImpl here. But I find it more consistent with our current logics.

native/ios/Comm/GlobalDBSingleton.mm
31 ↗(On Diff #18255)

I can't understand why you would think that. The method is called scheduleOrRunCancellable. It should clearly be calling scheduleOrRunCancellableCommonImpl...

native/ios/Comm/GlobalDBSingleton.mm
31 ↗(On Diff #18255)

I've made a mistake here, I thought about this code in terms of "who will execute this task" but right now I see it's "who will schedule this" so I agree with @ashoat, I should have used scheduleOrRunCancellableCommonImpl

use scheduleOrRunCancellableCommonImpl, improve readabillity

native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
22 ↗(On Diff #18255)

Added later on this stack in D5579.
I wanted to implement js handling first and spilt adding this function/using this function into separate diffs - there are a lot of changes to review.

native/cpp/CommonCpp/NativeModules/InternalModules/GlobalDBSingleton.h
25 ↗(On Diff #18316)

I think it would be highly beneficial to extract this string into some constant or static attribute of this class. It is repeated in many places (in this diff and in D5578).

26 ↗(On Diff #18316)

I do not think this return is necessary. If you throw function execution is terminated.

reabse, introduce const, simplify logic

thanks for the suggestions @marcin, applied

marcin added a reviewer: tomek.
marcin added inline comments.
native/cpp/CommonCpp/NativeModules/InternalModules/GlobalDBSingleton.h
9 ↗(On Diff #18375)

If you look through the codebase of C++ in native you will see that we follow a convention of initialization via curly brackets. Something like this:
const std::string TASK_CANCELLED_FLAG{"TASK_CANCELLED"};
I think we should follow it here as well.

Accepting, because my comments are only suggestions, but probably worth doing

native/cpp/CommonCpp/NativeModules/InternalModules/GlobalDBSingleton.h
9 ↗(On Diff #18375)
30–39 ↗(On Diff #18375)

I'm not sure if I'm missing something, but it seems like we should use our existing logic

native/ios/Comm/GlobalDBSingleton.mm
13–31 ↗(On Diff #18375)

It should be possible to reuse the logic a bit

This revision is now accepted and ready to land.Nov 14 2022, 9:19 AM

initialize via curly brackets, simplify logic

native/cpp/CommonCpp/NativeModules/InternalModules/GlobalDBSingleton.h
30–39 ↗(On Diff #18375)

definitely, thanks for suggestion

native/ios/Comm/GlobalDBSingleton.mm
13–31 ↗(On Diff #18375)

It is possible but it introduces another function, and in the next diff from the stack D5578 task type changes from const std::function<void(taskType)> because it takes additional arguments (promise and jsInvoker) which mean we will need to overlead scheduleOrRunBase or wrap this task in yet another lambda which after implementing this made feel confused wht's going on,
but if you think it's still better I am okay doing this the way you suggested!

This revision now requires review to proceed.Nov 16 2022, 2:36 AM

(Removing myself as blocking since I don't think I have enough context to give this a proper review)

This revision is now accepted and ready to land.Nov 17 2022, 9:16 AM