EDIT: This also happens after reloading the emulator on React Native, in a very simple setup (see below https://github.com/realm/realm-js/issues/1248#issuecomment-328313637)
Get an error message when opening a synced realm if server not available or user is offline.
Realm.open() returns a promise that gets rejected with useful error message.
The promise simply stays in pending status indefinitely.
This callback does not get called:
Hence the promise never returns.
Run this code after log in with valid user:
const openRealm = (user, url, schema) => {
return Realm.open({
sync: { user, url },
schema,
schemaVersion: 1
});
};
This only happens on Android, iOS works fine.
@Damnum In the server log, can you see that the user is logged in?
Can you describe your set up (is it a physical device or an emulator? are you connecting to localhost? )?
@kneth by the time I make the Realm.open call, the server is silent. But every 10 minutes I'm getting this server log:
10:21:03 PMinfo
sync: Sync Connection[3174]: Sync connection closed due to being idle
10:21:03 PMinfo
sync: Sync Connection[3174]: Session[2]: Session terminated (session_ident=2).
10:20:52 PMerror
sync: Sync Connection[3180]: Session[2]: Client file already bound in other session (message_type='ident', path='/b07f92ab1e5344d5a256bdc7bbb8de7c/th').
10:20:52 PMinfo
sync: Sync Connection[3178]: Session[2]: Disabled
10:20:52 PMinfo
sync: Sync Connection[3180]: Session[2]: Received: IDENT(server_file_ident=1, client_file_ident=16, client_file_ident_secret=5264769406148302654, scan_server_version=70, scan_client_version=168, latest_server_version=70, latest_server_session_ident=7022817502712743451)
10:20:52 PMinfo
sync: HTTP Connection[3180]: Received: Sync HTTP request(protocol_version=18)
10:20:52 PMinfo
sync: Sync Connection[3180]: Session[2]: Session initiated (session_ident=2).
10:20:52 PMinfo
sync: Sync Connection[3180]: Session[2]: Received: BIND(server_path=/b07f92ab1e5344d5a256bdc7bbb8de7c/th, signed_user_token='...p4j/BfL1oyc1wI4RkJ0RzMAatp7w==', need_file_ident_pair=0)
10:20:52 PMinfo
sync: HTTP Connection[3180]: Connection from 127.0.0.1:56488
I suppose that happens when the user token is refreshed. Same error happens with iOS on the server, though it only hangs on Android.
Happens on Android physical device and simulator. I'm connecting to a server hosted on DigitalOcean. May be related to https://github.com/realm-demos/realm-tasks/issues/397
EDIT: I also setup the realm on a server running on localhost. Still hangs, and the server doesn't even show the error above, so the error is probably not related.
@kneth I tested the exact same configuration on Android (both simulator and device) and iOS, with both localhost and server.
Result: On iOS, everything works as expected.
On Android, function _waitForDownload is never called -> Promise never resolves.
Looks like this function is wrapped into CPP code: https://github.com/realm/realm-js/blob/85fb49b35455880763cf7f2e1b5722db5c6871e9/src/js_realm.hpp#L588
Please let me know how to debug this code. Is there a way to print out logs there?
@Damnum Sorry the the late reply. Is it possible for you to contribute a small project which can reproduce the issue?
@kneth I will try. Not sure if it's important but I'm using the Android Java SDK to pre-fill the data in the first place.
I now tried to switch to ROS 2.0.0 rc-2, and realm-js 2.0.0-rc5 (on Android Java site: 4.0.0-BETA2-afe7114-SNAPSHOT). Same result though.
I'm attaching the server log from the moment the client makes the Realm.open call. The client log is silent (just hangs).
EDIT: I'm also attaching the server log for the (working) Realm.open call on iOS.
Seems like the login takes place in both logs, but the actual synced realm (called shared.realm) is not mentioned in the Android log.
@kneth have you had the chance to look at the logs? I realized that the logs are identical until a point where on iOS, the log says:
4:14:36 PMdebug proxy: attempting to upgrade client.....
After that, the actual download starts.
On Android, the log is silent instead (apart from sending stats). (see time 3:50:13)
@kneth I could reproduce the bug with a very simple setup.
localhost:9080 to 10.0.2.2:9080 in config.js to make it work on Android): Everything works as expected.connect function in realm-tasks.js from synchronously opening via new Realm() to asynchronously opening via Realm.open (as recommended in the docs), see code belowRealm.open callback hangs.function connect(action, username, password, callback) {
username = username.trim();
password = password.trim();
if (username === "") {
return callback(new Error("Username cannot be empty"));
} else if (password === "") {
return callback(new Error("Password cannot be empty"));
}
Realm.Sync.User[
action
](config.auth_uri, username, password, (error, user) => {
if (error) {
return callback(new Error(error.message));
} else {
console.log("Opening realm...");
Realm.open({
schema: [Task, TaskList],
sync: {
user,
url: config.db_uri
},
path: config.db_path
}).then(realm => {
console.log("Realm successfully opened!");
callback(null, realm);
});
}
});
}
Guys, this maybe related to not invoking the promise rejection with settimeout. This maybe the fix for it
https://github.com/realm/realm-js/pull/1279/commits/3c5f28fb9ecce520fe6fcab728330d3a3f3887be
Long story short on RN we have a requirement to use this hack with setTimeout(func, 1) to allow the promise to continue. We have an issue to resolve this properly here https://github.com/realm/realm-js/issues/1255 until then this seems like the workaround to use.
You may try cherry picking this fix and testing if the rejection is causing the promise to be stuck
@blagoev I think that will not help in this case. When I debug in this code, the callback given to the _waitForDownload function does not get called: https://github.com/realm/realm-js/blob/416632c9adc7350cdca12dc792edcf3e9d0b30d8/lib/extensions.js#L47
That means, line 48 will not even get called at all, so your timeout will never be reached. mE the only way to fix this is inside the wrapping wait_for_download_completion function mentioned above. Or at least improving the logging/error handling there to find out what's causing the issue.
As far as I can tell, the server log is also silent about it.
I'm able to reproduce the issue and indeed the callback to _waitForDownload never gets called.
@Damnum I mentioned this maybe the reason for a hang. If the callback is not called then the hang is in c++ code and we need to debug it to know exactly why. Still a hang in Realm.open will happen in RN if setTimeout is not used for resolve and reject, until we fix the callback issue in RN.
Hopefully when we debug the c++ we will get more details why this happens.
@blagoev do you know how to add debug statements into the c++ code? I tried it with
#include <android/log.h>
...
__android_log_print(ANDROID_LOG_INFO, "JSRealm", "INSIDE wait_for_download_completion");
But no luck so far...
Probably the best way is to debug the c++ code in Android Studio, but these __android_log_print should be working as well. Check that this code is picked up when you build the android app. Probably this requires an npm uninstall realm realm-tests && npm install again before build. @ashwinphatak is looking into this as well.
Added some debugging statements and it appears that the callback to async_wait_for in realm-js/react-native/android/src/main/jni/core/include/realm/sync/client.hpp never gets called the 2nd time onward (after the refresh). That's about as far as I could debug as the implementation of async_wait_for is inside an object file librealm-sync-android-x86.a.


Thanks for the digging @ashwinphatak ! I'm not really familiar with these native components... do you know if the source code for them is open source?
@ashwinphatak any news on this? This is a real blocker for our project.
librealm-sync-android-x86.a isn't open source, so we might have to wait for @blagoev to take a look.
I'm using [email protected] and [email protected], also facing this issue on Android.
With even simpler setup code:
~
return Realm.open({
path: db.realm,
schema
});
~
I'm able to reproduce this as well, on android the first app load works, but reloading JS code makes realm.open never resolve.
@bmunkholm @kneth not sure why this has been marked as "optional"? Failing to open the database is pretty basic stuff because without it you can't do anything else?!
@Damnum I can see how that can be confusing :-)
It's not an absolute priority, but a relative priority to the next upcoming release. It means that we will not hold back the release if we can't this fixed before the target date for the release.
Ok thanks for clarifying, that makes sense!
is this fix available via npm yet?
yes it is