eclipse-vertx / vertx-sql-client

High performance reactive SQL Client written in Java
Apache License 2.0
891 stars 199 forks source link

Connection error using virtual threads #1398

Closed jonrosner closed 9 months ago

jonrosner commented 9 months ago

I am trying to use vert.x + postgres using the new virtual threads feature. Unfortunately I cannot get it to work (look at the code below). Note that when I switch to an event-loop model everything works normally.

Things I have already tried:

Version

4.5.1

Do you have a reproducer?

I use the following example code:

package test;

import java.util.UUID;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Future;
import io.vertx.core.ThreadingModel;
import io.vertx.core.Vertx;
import io.vertx.pgclient.PgConnectOptions;
import io.vertx.sqlclient.Pool;
import io.vertx.sqlclient.PoolOptions;
import io.vertx.sqlclient.SqlClient;

public class App {

    public static void main(String[] args) {
        Vertx.vertx().deployVerticle(new MockDataCreator(),
                new DeploymentOptions()
                        .setThreadingModel(ThreadingModel.VIRTUAL_THREAD));

        while (true) {
        }
    }

    public static class MockDataCreator extends AbstractVerticle {

        @Override
        public void start() {
            try {
                PgConnectOptions connectOptions = new PgConnectOptions()
                        .setPort(5432)
                        .setHost("127.0.0.1")
                        .setDatabase("db")
                        .setUser("user")
                        .setPassword("password");

                PoolOptions poolOptions = new PoolOptions()
                        .setMaxSize(5);

                SqlClient client = Pool.pool(vertx, connectOptions, poolOptions);

                for (int i = 0; i < 10; i++) {
                    String id = UUID.randomUUID().toString();

                    String query = String.format(
                            "INSERT INTO users (id, name) VALUES (%s, %s)",
                            id,
                            "user" + i);

                    Future.await(client.query(query).execute());

                    if (i % 100 == 0)
                        System.out.println("created user" + i);
                }
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
    }

}

I use the following dependencies:

implementation platform("io.vertx:vertx-stack-depchain:4.5.1")
implementation "io.vertx:vertx-core"
implementation "io.vertx:vertx-web"
implementation "io.vertx:vertx-web-openapi"
implementation "io.vertx:vertx-web-validation"
implementation "io.vertx:vertx-pg-client:4.5.1"

Steps to reproduce

  1. ./gradlew run
  2. Observe the error:
java.lang.NoClassDefFoundError: com/ongres/scram/common/stringprep/StringPreparation
        at io.vertx.pgclient.impl.codec.InitCommandCodec.handleAuthenticationSasl(InitCommandCodec.java:60)
        at io.vertx.pgclient.impl.codec.PgDecoder.decodeAuthentication(PgDecoder.java:377)
        at io.vertx.pgclient.impl.codec.PgDecoder.decodeMessage(PgDecoder.java:151)
        at io.vertx.pgclient.impl.codec.PgDecoder.channelRead(PgDecoder.java:123)
        at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.ClassNotFoundException: com.ongres.scram.common.stringprep.StringPreparation
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
        ... 21 more

Extra

I use Java 21

tsegismont commented 9 months ago

I can't reproduce. Can you share a reproducer project on GitHub? Including instructions to setup the database in a container? Thank you

jonrosner commented 9 months ago

https://github.com/jonrosner/vertx-virtual-test/tree/main

In the readme I wrote how I started the DB

tsegismont commented 9 months ago

Thanks for providing a complete reproducer.

This doesn't seem to be virtual threads problem: I can see the same errors using the event loop threading model.

On the different issues reported: