meteor-react-native
meteor-react-native copied to clipboard
Method call is not working after resuming from the background
Describe the bug
Unable to do a method call after resuming from the background after 10-15 mins. Meteor connection status(meteor.status()=true) is true. But no responsce from server. Can anyone help me?
To Reproduce
Steps to reproduce the behavior:
- Open the app
- Minimize the app
- Open the app after 10-15 mins
Expected behavior
Should be able to call the methods and get the results from the server even after resuming the app from the background.
Hi @midhunchandran97,
Could you check the following:
- Are the data from your publications continuing to appear?
- Is
Meteor.user()defined? - Is the socket connected (you can access the Socket via
Meteor.ddp.socket)
Hi @TheRealNate,
Thanks for the quick response, We have checked all three items, all are working fine. We are calling a method call just after resuming the app. There was no response from the server. After sometime DDP connected and working fine except for the first method call. No response to the first method call.
What could be the problem?
I'm wondering if this could be the issue: https://github.com/TheRealNate/meteor-react-native/blob/85924c2e32793198c4d5d1601ff726f187460ec3/lib/queue.js#L21-L25
Basically, the way the methods queue was designed, if the socket is connected the method is called and the next one is processed. I'm wondering if when the app gets resumed, if the socket was disconnected when Meteor.call was called, it does not retry it.
To test this theory, can you try another method call a bit after the first one? That should cause the queue to restart, and you original method should return as well.
Thanks!
Hey @midhunchandran97, any updates on this?
@TheRealNate ,
Sorry for the late reply, I have tried all steps as you told me. But there is no response from the first method call after resuming the app from a minimized state. After a successful DDP connection, I called a method and I got a response. But no response for the first method call even after the successful DDP connection. Whats next ? :(
@TheRealNate , Any updates?
@FaridSafi @spencercarli @sandeepjain @TheRealNate Can anyone help me?
Hey @midhunchandran97. Sorry about the delayed reply, notifications seem to be running a little weird lately.
Could you try wrapping your method call in waitDdpConnected? E.g.:
Meteor.waitDdpConnected(() => {
Meteor.call(...);
});
Hi @TheRealNate, this didn't work for me.
the meteor connection status is 'connected' while resuming the app. So I think Meteor.waitDdpConnected() has no use here.
Can we have any time out for a method call? Waiting for your reply. Thanks
Hey @midhunchandran97,
For a method call timeout I could add a add-on package (we try not to deviate from the meteor web spec on the core package), but I'd like to see if I can fix your issue.
So from what I understand, after reconnecting you've tried this:
- make a method call (Call 1)
- make another method call (Call 2)
- Call 2 gets a response
- Call 1 never gets a response
Is that right?
Sorry for the double replies. I've noticed that the current ddp implementation doesn't handle websocket errors. Could you try doing this:
Meteor.getData().ddp.socket.rawSocket.onerror = e => console.error(e);
And see if it is logging any errors
Hey @midhunchandran97,
For a method call timeout I could add a add-on package (we try not to deviate from the meteor web spec on the core package), but I'd like to see if I can fix your issue.
So from what I understand, after reconnecting you've tried this:
- make a method call (Call 1) - make another method call (Call 2) - Call 2 gets a response - Call 1 never gets a responseIs that right?
Yes, but there is a change
- make a method call (Call 1)-just after resuming the app from minimized state.
- make another method call (Call 2)- after 4-5 sec resuming the app from minimized state. (meteor will reconnect automatically)
- Call 2 gets a response
- Call 1 never gets a response
Hey @midhunchandran97,
I see you marked this issue as closed. Were you able to fix this issue?
Thanks
Hi @TheRealNate,
Sorry, I accidentally closed the issue
@midhunchandran97 I see, no problem.
Were you able to try this:
Meteor.getData().ddp.socket.rawSocket.onerror = e => console.error(e);
@midhunchandran97 I see, no problem.
Were you able to try this:
Meteor.getData().ddp.socket.rawSocket.onerror = e => console.error(e);
I have tried this, but nothing is consoled.
Hey @midhunchandran97,
Sorry for the delayed reply. I think there may be a flaw in the way the package is handling reconnecting. I'm going to do some more digging into it.
Meanwhile, could you try looking at:
Meteor.getData().ddp.status
At the exact moment of your first method call. In fact if you can get a log of the whole Meteor.getData().ddp object and post it that would be helpful.
Thanks
Hi @TheRealNate
Sorry for the delayed reply. I have checked the code
- Result of 'Meteor.getData().ddp.status' is "connected"
- Log of 'Meteor.getData().ddp' is attached below.
Hey @midhunchandran97, is this right before or right after running Meteor.call.
It looks like the socket is definitely open. Could you check on the server if the first method call reached the server or not? It's possible that the first method call is reaching the server but the response isn't making it back. This could help us narrow down the issue.
Also, are you using localhost? It should work, but are you experiencing the same issue with production (or any server not on your lan)?
Hi @TheRealNate
- The result is right after running the first Meteor.call.
- The first method call never reached the server. I have checked it with a console. nothing shows up.
- We are facing the same issue in localhost and in the production server
@TheRealNate Is there any way to solve this issue?
Hi @midhunchandran97, sorry about the delay in replying.
Is the method call being triggered by an automatic process as soon as the app returns from background, or is it triggered by a button press a little bit after (is there enough time for the connection to be reestablished).
Could you also try seeing if the socket is opening and closing:
Meteor.getData().ddp.socket.addListener("open", () => console.log("open"));
Meteor.getData().ddp.socket.addListener("close", () => console.log("close"));
Hi @TheRealNate ,
- Method call is triggered by a button press.
- When resuming application from minimized state 1. 'Meteor.getData().ddp.socket.addListener("close", () => console.log("close"))' is triggered first. 2. After a bit of time 'Meteor.getData().ddp.socket.addListener("open", () => console.log("open"))' is triggered.
Hi @midhunchandran97,
Thanks for the info. I think we're getting closer to a fix. Could you try running your Meteor call after "open" is called?
Hi @TheRealNate
I tried running the Meteor call after "open" is called, Meteor call worked successfully.
Great!
For a fix, looks like all that needs to be done is:
- When socket is closed, wait for reopen before trying to send calls
I'll start on a fix for this. I'll keep this issue open till it is released.
Updates:
So it looks like when the socket is closed, all pending messages are dropped. This could be the root cause of your issue (the method was coming in before the close event was fired), however before I change this I want to check the Meteor spec and see how Meteor handles ddp connection drops. I believe if you start a meteor call while the connection is offline, it will execute once connection is restored, but I wan't to confirm the behavior.
In the meantime, here's a somewhat simple workaround (please excuse any typos as I whipped this up quickly):
let isOpen = true, onOpen = [];
Meteor.getData().ddp.socket.addListener("close", () => {
isOpen = false;
});
Meteor.getData().ddp.socket.addListener("open", () => {
isOpen = true;
onOpen.forEach(f => f());
});
const whenConnected = func => {
if(isOpen) {
func();
}
else {
onOpen.push(func);
}
}
Basically, monitoring the websocket status, and queueing any calls if the socket is closed. Usage:
whenConnected(() => {
Meteor.call("abc", ...);
});
Let me know if there are any issues with the workaround.
@TheRealNate Sorry for the delayed reply,
- When I made a normal method call,
Meteor.getData().ddp.socket.addListener("open", () => { isOpen = true; onOpen.forEach(f => f()); }) executed Then 'whenConnected' called and method call successfully executed.
- I made a method call just after resuming the app from minimized state.
At that time isOpen variable is true, so 'whenConnected' is executed. After this the following code has executed. Meteor.getData().ddp.socket.addListener("close", () => { isOpen = false; });
This solution is not worked for me.
Hey @midhunevolvier, so you're saying the close event is firing a short time after the app resumes, but not immediately; which is causing your call which executes immediately to run before the close event is fired. Is that right?
Hey @midhunevolvier, so you're saying the close event is firing a short time after the app resumes, but not immediately; which is causing your call which executes immediately to run before the close event is fired. Is that right?
Yes
@TheRealNate Is there any solution? We are stuck.
Hi @midhunevolvier,
I'm looking into a built in solution for this package, but for now a quick fix for you may be to use the AppState API to detect a resume from background and wait before sending the call.
@TheRealNate Ok. But how can I understand whether the Meteor is connected or not? Then only I can wait before sending the call. When I resume from background meteor connection status is 'CONNECTED'.
Hey @midhunevolvier, sorry again for the delayed reply. I don't know why GitHub doesn't seem to be sending me notifications for this issue.
Could you try directly reading the socket object's status (Meteor.getData().ddp.socket) and let me know if the socket displays as closed upon resume (even if Meteor's connection status hasn't been updated)? If not, I'll need to see why react native has a delay in flagging the socket as closed.
@TheRealNate I have checked the status after resuming the application and attaching the screenshots for your reference. I can't find any difference in the result of application on 'NORMAL' and 'RESUMING' stages
-
Result of 'Meteor.getData().ddp' (NORMAL)

-
Result of 'Meteor.getData().ddp' (RESUMING)

-
Result of 'Meteor.getData().ddp.socket (NORMAL)

-
Result of 'Meteor.getData().ddp.socket (RESUMING)
'
Hi @midhunevolvier,
Could you try Meteor.getData().ddp.socket.rawSocket as this should be the socket implementation at the React Native level? If you're not seeing any change here then we may have to look at other options for a fix.
Thanks!
@TheRealNate I have checked 'Meteor.getData().ddp.socket.rawSocket', I can't find any differences.I think the same issue will be there even if we keep the application idle for some time without minimizing it.
- Result of 'Meteor.getData().ddp.socket.rawSocket' (NORMAL)
- Result of 'Meteor.getData().ddp.socket.rawSocket' (RESUMING)
@TheRealNate Is there any solution? We are stuck.
@midhunevolvier do you possibly have a minimal reproduction that shows this issue that I could clone and explore the issue?
@copleykj Sorry for the delayed reply. I am busy with my project release. I will upload a sample project as soon as possible.
@midhunevolvier no apology necessary. Delays are in the nature of our work. When ever you get around to it just let me know and I'll see about digging into this. If I'm not responsive here, feel free to get in touch on the Meteor Community Slack.
I will tackle this, once the PR #83 is merged, which is close to completion (currently User, Accounts and Meteor files remain to be tested).