Page MenuHomePhabricator

[native] add function to initialize `DatabaseQueryExecutor`
ClosedPublic

Authored by kamil on Dec 22 2022, 2:41 AM.
Tags
None
Referenced Files
Unknown Object (File)
Sat, Dec 14, 8:11 AM
Unknown Object (File)
Sat, Dec 14, 8:11 AM
Unknown Object (File)
Sat, Dec 14, 8:11 AM
Unknown Object (File)
Sat, Dec 14, 8:11 AM
Unknown Object (File)
Sat, Dec 14, 8:10 AM
Unknown Object (File)
Sat, Dec 14, 8:10 AM
Unknown Object (File)
Sat, Dec 14, 8:05 AM
Unknown Object (File)
Fri, Dec 6, 9:55 AM
Subscribers

Details

Summary

Implementing approach described in ENG-1974.
This function will be called separately in iOS and Android so this time separating function from it's call to make it easier for reviewers.

Test Plan
  1. Make it possible to throw and exception on migrate() function on demand.
  2. Call this function.
  3. Build the app for both platforms
  4. Check if:
  5. getQueryExecutor() works properly -> db status = WORKABLE
  6. getQueryExecutor() throws exception and there is nothing in store -> db status = 'FIRST_FAILURE' and app is terminated
  7. getQueryExecutor() throws exception and there WORKABLE -> db status = 'FIRST_FAILURE' and app is terminated
  8. getQueryExecutor() throws exception and there FIRST_FAILURE -> db status = 'SECOND_FAILURE' and app proceed
  9. getQueryExecutor() throws exception and there SECOND_FAILURE -> db status = 'SECOND_FAILURE' and app proceed

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.Dec 22 2022, 3:30 AM
native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.cpp
9 ↗(On Diff #20014)

Why not enum?

29 ↗(On Diff #20014)

I may be wrong in this particular case, but I am always sceptical about catch statement with such a broad scope. We do not always want to catch everything. Scope of errors that should be resolved with actions taken inside this catch statement might be quite narrow. If something else throws we will ignore it, take wrong steps to resolve it and make debugging much harder. If possible then please, specify most narrow class of errors that we want to resolve by actions implemented below.

41 ↗(On Diff #20014)

Looks like this if statement results in the same action as previous. Perhaps they could be merged? If the reason those if statements are not merged is that we want to log databaseManagerStatusValue then we can keep the separate but call same private method inside. (that is one possible solution).

remove log, extract code duplication to separate function

native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.cpp
9 ↗(On Diff #20014)

Two reasons:

  • we need to store string values inside Secore Store - see SecureStore::set declarations
  • I want to make those strings meaningful, not 1, 2, 3... (probably we will need to check what's inside the secure store from JS side)

And as I know there is no need to do that with enums in c++: The values of the constants are values of an integral type known as the underlying type of the enumeration. (docs). And for me having 3 well-defined string constants it's more readable than e.g map and some sort of mapping int -> string which will make adding, reading, and comparing values more complex.

29 ↗(On Diff #20014)

Overall I agree with you, but I am somewhat skeptical.
My intention was to make the process of creating and migrating database reliable for the user. I don't think letting throwing exceptions and probably killing the app (but without our knowledge and data in secure store) will be better. This method will be called from native code at the very begging of app launch.

If we will narrow the scope there will be an error that will not expect, which will be continuously thrown - user will try to open the app and get the app killed or malformed schema and we will not have tools to fix that by deleting the database and creating a new one.

41 ↗(On Diff #20014)

If the reason those if statements are not merged is that we want to log databaseManagerStatusValue

whoops this is the log after debugging, I will remove it, sorry

native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.cpp
29 ↗(On Diff #20014)

Your statement is solid, but on the other hand we loose an opportunity to receive meaningful crash log with detailed stack trace, that would allow us to find and fix the error at its origin. The best solution here is to enable on the C++ side something similar to if(__DEV__ || isStaffUser(...)) that we use in JS. We could decide whether to catch or propagate exception based on whether we are running a DEV build or user is a staff member. If you agree, please create a task before landing and link it in a comment under this differential.

native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.cpp
39 ↗(On Diff #20411)

Shouldn't we return here? This if statement executes when databaseManagerStatus doesn't have value, but we proceed with the code that tries to access it afterwards.

42 ↗(On Diff #20411)

We should probably return here as well. Additionally can't we merge those if statements? !databaseManagerStatus.hasValue() || databaseManagerStatus.value() == .. ?

merge conditions

native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.cpp
39 ↗(On Diff #20411)

I can add return for clarity but if this condition will be true app will be killed, which means code will not proceed.

29 ↗(On Diff #20014)
marcin added a reviewer: tomek.
tomek added inline comments.
native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.cpp
10–12 ↗(On Diff #20682)

Shouldn't these be const?

28 ↗(On Diff #20682)

Do we have to initialize with brackets?

41 ↗(On Diff #20682)

Another option might be to rethrow here - that would give us a useful crash log after the first failure.

This revision is now accepted and ready to land.Jan 9 2023, 9:10 AM

use throw instead of terminate, add SQLiteQueryExecutor::initialize to DatabaseManager::initializeQueryExecutor

native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.cpp
10–12 ↗(On Diff #20682)

As discussed IRL: const is inside typedef line 9, but it'll be better to move const to each definition separately to improve clarity and to allow modifying DatabaseManagerStatus in future while returning from a function or something similar.

28 ↗(On Diff #20682)

We don't, but I found this in our C++ coding standards and it was requested in previous diffs where commSecureStore is used (see D4728) so I tried to match existing conventions

41 ↗(On Diff #20682)

Good call, tested this on a physical device in release mode, and app exited gracefully instead of eg. hanging so let's do it