[JAVA-3855] No diagnostic of connect fault to database Created: 09/Oct/20  Updated: 09/Oct/20  Resolved: 09/Oct/20

Status: Closed
Project: Java Driver
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Major - P3
Reporter: Andrew Kaplanov Assignee: Unassigned
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

That is fragment of Scala program that calls objects from com.mongodb.reactivestreams:

val client = MongoClients.create()
val db = client.getDatabase("test")

db.listCollectionNames().subscribe(new Subscriber[String]

{   def onSubscribe(s: Subscription) =  println("onSubscribe")   def onNext(elem: String) = println("onNext")   def onError(t: Throwable) = println("onError")   def onComplete() = println("onComplete") }

)

 

When database is not exist, I see on console:

onSubscribe

00:27:13.696 INFO  org.mongodb.driver.cluster - Exception in monitor thread while connecting to server localhost:27017
00:27:13.696 

...

But OnError is not called.

How can I handle this error?



 Comments   
Comment by Andrew Kaplanov [ 09/Oct/20 ]

Thank you. But the reason is not only in back-pressure in my test.

You sample contains setting to MongoClient "builder.serverSelectionTimeout(1, TimeUnit.SECONDS)".

So onError() prints the error "com.mongodb.MongoTimeoutException: Timed out after 1000 ms while waiting for a server ..."

In case when MongoClient creates with default settings, onError() is called after 30 sec, that is default timeout.

I think it is wrong. Database connection error should return immediately.

 

Comment by Jeffrey Yemin [ 09/Oct/20 ]

I think there is a misunderstanding about how reactive publishers work; the Subscriber has to first request events from the publisher before anything will actually start happening. It's easier for me to show using the Java Reactive Streams driver, so please forgive me for not using Scala:

        var client = MongoClients.create(MongoClientSettings.builder()
                // shorten the timeout to make it fail quicker
                .applyToClusterSettings(builder -> builder.serverSelectionTimeout(1, TimeUnit.SECONDS))
                .build());
        var db = client.getDatabase("test");
 
        var latch = new CountDownLatch(1);
        db.listCollectionNames().subscribe(new Subscriber<>() {
            @Override
            public void onSubscribe(final Subscription subscription) {
                // Must request events from the publisher explicitly
                subscription.request(Long.MAX_VALUE);
            }
 
            @Override
            public void onNext(final String s) {
                System.out.println(s);
            }
 
            @Override
            public void onError(final Throwable throwable) {
                // this shows that onError is called 
                throwable.printStackTrace();
                latch.countDown();
            }
 
            @Override
            public void onComplete() {
                System.out.println("Complete");
                latch.countDown();
            }
        });
 
        latch.await(5, TimeUnit.SECONDS);
        System.out.println("Exiting");

When I run this program with no mongod available, I get the following output:

com.mongodb.MongoTimeoutException: Timed out after 1000 ms while waiting for a server that matches ReadPreferenceServerSelector{readPreference=primary}. Client view of cluster state is {type=UNKNOWN, servers=[{address=127.0.0.1:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.ConnectException: Connection refused}}]
	at com.mongodb.internal.connection.BaseCluster.createTimeoutException(BaseCluster.java:407)
	at com.mongodb.internal.connection.BaseCluster.handleServerSelectionRequest(BaseCluster.java:311)
	at com.mongodb.internal.connection.BaseCluster.access$800(BaseCluster.java:62)
	at com.mongodb.internal.connection.BaseCluster$WaitQueueHandler.run(BaseCluster.java:478)
	at java.base/java.lang.Thread.run(Thread.java:832)
Exiting

Comment by Andrew Kaplanov [ 09/Oct/20 ]

Thanks to you.

It is unacceptable for me that I see connection error only on console, but I can't handle this error in my program.

I can't check result of getDatabase() call.

Other calls return Publisher. Attempting to read Publisher hangs because not either onError or onComplete called.

Comment by Jeffrey Yemin [ 09/Oct/20 ]

Hi akaplanov@gmail.com

Thanks for your question. I moved this to the JAVA project as that is where we are now tracking all Scala and Reactive Streams issues.

We'll take a look at it soon and get back to you.

Generated at Thu Feb 08 09:00:36 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.