Syncd MongoDB Realm Applications hangs at LoginAsync with no errors

I have 2 MongoDB Dot-net Syncd projects already working.

I created a new Cluster with a new Realm App.
Setup Network access as the other apps.
Added database user
Setup authentication for anonymous and user-pass
Create the App.taskApp from the AppId (hospicecare-wnzsw)
All Models and schemas validate.

On running the Application, it hangs at either anonymous or user-pass login stage:

return app.CurrentUser ?? await app.LogInAsync(Credentials.Anonymous());
or
return app.CurrentUser ?? await app.LogInAsync(Credentials.EmailPassword(username, password));

Logs show no error:
OK Feb 07 9:59:36+00:00 378ms Authenticationlogin local-userpass
However if I use an invalid userrname, the Logs shows “invalid password error” but never returns.

I’ve spent a day comparing the other apps but I’m jabberflastered.
What could be I be missing?

Interestingly, I can connect to the same database and populate it with data from another app in another cluster using the same AppId.

Any suggestions would be appreciated, I’m on the verge of scrapping the project and starting over.

Hi Richard,

I’d like to help you, but I need to see more of your code. Could it be possible for you to share the project with me? If it has sensitive information, I can provide you with a link to our secure upload tool.

Andrea

Hi Andrea
It should be possible, I have created another cluster and RealmApp mirroring the original.
Same problem - LoginAsync Hangs.
So I have the first app which I have ‘gutted’. There’s only one Collection with simple schema.
I can simplify it and get it to you.

First, a rather horrible idea: Two Other Synced apps I have are working fine.
However, these were both created a couple of months ago, probably earlier than Realm.beta.2 and Atlas 4.2.
The new projects have both been created using Atlas 4.4 and Realm beta.6. Could the issue be with creating Apps ground up with latest Realm versions?

btw I upgraded the naughty apps to realm.10.0.1 and they still hang.

I can’t help thinking I’m missing something embarrassingly simple, but the fact that the methods appear to be working and giving the expected logs is suspicious.

Please send me the upload link and I’ll prepare the Application.
Thanks

Yes, what you describe sounds a bit suspicious. It’s a good idea to take a look at it.
Here it’s the upload link to securely share your project with us.

That was easy.
The VS 2019 project interesting files are:

App.cs
MainWindow.cs (calls RealmConnector.Login method)
RealmConnector. cs

I inadvertently left a temporary username and password in but it’s just test stuff for this app.

Rich

Hi Richard,

I took a look at the code you sent me.
In the method MainWindow.OnLoaded at line 24 you do ConnectRealm().Result where ConnectRealm is an async method. By using Task.Result to run an async method synchronously, you’re blocking the UI thread. However, due to the way the runtime invokes continuations after an await, the execution context in ConnectRealm will try to return to the main thread. This causes a deadlock where the main thread waits for ConnectRealm to complete and ConnectRealm waits for the main thread to be yielded to continue execution after the first await.

You have 2 options:

1- (Recommended) Call the async method without awaiting it. And in order to be notified when it’s done you can use any messaging system that you prefer or you could manually set a boolean telling you when it’s done and at specific events check it and take the needed action. I mixed the 2 options below, I hope it’s clear:

class MainWindow : Window
{
    // ... you vars and other methods
    bool IsBusy = false;

    public void OnLoaded(object sender, RoutedEventArgs e)
    {
        MainFrame.Content = "     Opening Realm Database";

        // pseudo code
        yourMessagingSystem.notificationOfInterest += SetContent;
        
        _ = ConnectRealm();
    }

    private async Task<bool> ConnectRealm()
    {
        try
        {
            IsBusy = true;
            var user = App.taskApp.CurrentUser;
            if (user == null)
            {
                user = await RealmConnector.GetOrLoginAnonUser(App.taskApp);
            }
            var dlg = new MessageYesNoWindow("LoginAsync", "Success");

            //pseudo call to messaging system
            yourMessagingSystem.Notify(...);
        }
        catch (Exception ex)
        {
            App.ProcessException("MainWindow.ConnectRealm", ex.InnerException.Message);
        }
        finally
        {
            IsBusy = false;
        }
    }

    private void SetContent()
    {
        MainFrame.Content = "";
    }

    // more of your code

    private void Close_Click(object sender, RoutedEventArgs e)
    {
        // more pseudo code
        yourMessagingSystem.notificationOfInterest -= SetContent
        
        // ...
    }
}

2- (Not recommended) If you really can’t do this asynchronously, then you can use a trick where you spin up a background task to do the work and .Result that one. It’s generally discouraged because you’ll be blocking the main thread for a non-deterministic amount of time which can result in poor user experience. You should also be careful not to open Realm instances in the background method because those won’t be usable on the main thread.
The code would look something like this:

class MainWindow : Window
{
    // ... you vars and other methods

    public void OnLoaded(object sender, RoutedEventArgs e)
    {
        MainFrame.Content = "     Opening Realm Database";
        var connected = Task.Run(async () => await ConnectRealm()).Result;
        if (connected)
        {
            MainFrame.Content = "";
        }
    }

    // more of your code
}

Hope this helps,

Andrea

I see what you mean but the use of .Result was a late debug attempt to see what’s going on.
Please remover the .Result and you’ll have what still fails…

These are the calling methods I have used over the past year, without using Result, and they fail now:

In MainWindow, it just calls ConnectRealm(); (no if(ConnectRealm …)

var user = App.taskApp.CurrentUser;
if (user == null)
{
user = await RealmConnector.GetOrLoginAnonUser(App.taskApp);
}

and in RealmConnector:

public static async Task LoginRealmUser(Realms.Sync.App taskApp)
{
return taskApp.CurrentUser ?? await taskApp.LogInAsync(Credentials.EmailPassword(username, password));
}

If you try this then it will fail in the code I provided.

Could you be more specific in what you mean by “it will fail”?
Do you mean that you are able to connect to the database but then you aren’t able to perform actions on it? Or something else?

Async calls to LoginAsync never returns, the program stalls, no User is returned.
RegisterUserAsync also stalls.

Hi Andrea
I spent days staring at the code comparing the various apps, trying not to get egg on my face.
Thanks for your all your efforts, the difference was the ConnectRealm method which for various reasons I converted to Task bool instead of void. Aargh 4 days!
But we got there, and at least I can now knock up a cluster and Apps like a pro.
“If it ain’t broke - then don’t fix it”.
Thanks again
Yours Humbly
Rich

Hi Richard,

I’m glad to hear that you discovered what the issue was and you’re now unblocked.
Happy coding! :slight_smile:

Regards,
Andrea

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.