Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Duplicate ID exception on delete statement #281

Closed
FroMage opened this issue Jul 10, 2020 · 15 comments
Closed

Duplicate ID exception on delete statement #281

FroMage opened this issue Jul 10, 2020 · 15 comments
Assignees

Comments

@FroMage
Copy link
Contributor

FroMage commented Jul 10, 2020

This might be a user issue, but I don't get it.

I do a bunch of operations in my tests, then in the end I call "delete from Person" to delete all my entities, and I get this exception:

io.vertx.pgclient.PgException: duplicate key value violates unique constraint "person2_pkey"
	at io.vertx.pgclient.impl.codec.ErrorResponse.toException(ErrorResponse.java:29)
	at io.vertx.pgclient.impl.codec.QueryCommandBaseCodec.handleErrorResponse(QueryCommandBaseCodec.java:57)
	at io.vertx.pgclient.impl.codec.ExtendedQueryCommandBaseCodec.handleErrorResponse(ExtendedQueryCommandBaseCodec.java:70)
	at io.vertx.pgclient.impl.codec.PgDecoder.decodeError(PgDecoder.java:233)
	at io.vertx.pgclient.impl.codec.PgDecoder.decodeMessage(PgDecoder.java:122)
	at io.vertx.pgclient.impl.codec.PgDecoder.channelRead(PgDecoder.java:102)
	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:748)

I don't understand how I can get this issue because the id field is generated:

    @Id
    @GeneratedValue
    public Long id;

And I'm not testing duplicate IDs anywhere. This is without a transaction.

I can see in the logs that at this point HR is trying to insert an entity, but my last operation was a flush that failed due to a different (not the ID) unicity constraint.

I can't seem to figure out how to show the values it's trying to insert, so I'm not sure what entity HR is trying to persist, but I don't think it should be trying to persist anything at this point. This is pretty much a copy of an ORM test that doesn't have this symptom.

@FroMage
Copy link
Contributor Author

FroMage commented Jul 10, 2020

After having forced a flush just before I tried to persist the entity with the voluntary unicity constraint error, my delete from Person call now trips the same unicity constraint that I just tripped up.

So perhaps when I did flush it did not flag that entity for removal and it's trying to re-persist it? Or perhaps the delete from Person call does not remove it from the plan before it tries to send the delete operation in the DB?

TBH I'm not sure what the semantics of the session is when I try to persist an entity with a unicity constraint error that throws on flush: should subsequent operations re-try inserting it?

@gbadner
Copy link
Contributor

gbadner commented Jul 10, 2020

@FroMage, do you have a test case that reproduces this? If so, I can try to look at this next week.

@FroMage
Copy link
Contributor Author

FroMage commented Jul 13, 2020

Entity:

@Entity
public class MyPerson {

    @Id
    @GeneratedValue
    public Long id;
    public String name;
    @Column(unique = true)
    public String uniqueName;
    
    public MyPerson() {}
}

Test:

    @Test
    public void test() {
        // persistAndFlush
        MyPerson person1 = new MyPerson();
        person1.name = "testFLush1";
        person1.uniqueName = "unique";
        // get your Mutiny.Session however you like
        Panache.getEntityManager()
        .flatMap(session -> {
            return persistAndFlush(session, person1)
            .flatMap(v -> {
                MyPerson person2 = new MyPerson();
                person2.name = "testFLush2";
                person2.uniqueName = "unique";

                // FIXME should be PersistenceException see https://github.com/hibernate/hibernate-reactive/issues/280
                return assertThrows(PgException.class,
                                    () -> persistAndFlush(session, person2),
                        "Should have failed");
            }).flatMap(v -> {
                System.err.println("DONE before delete ?");
                return session.createQuery("DELETE FROM MyPerson").executeUpdate();
            })
            .map(v -> {
                System.err.println("deleted "+v);
                return "OK";
            });
        }).await().indefinitely();
    }

    private Uni<Void> persistAndFlush(Session session, MyPerson person) {
        return session.persist(person).flatMap(v -> session.flush()).map(v -> null);
    }



    private Uni<Void> assertThrows(Class<? extends Throwable> exceptionClass,
                                   Supplier<Uni<?>> f,
                                   String message) {
                               System.err.println("Asserting "+message+" hoping to get a "+exceptionClass);
                               Uni<?> uni;
                               try {
                                   uni = f.get();
                               }catch(Throwable t) {
                                   uni = Uni.createFrom().failure(t);
                               }
                               return uni
                                       .onItemOrFailure().invoke((r, t) -> {
                                           System.err.println("Got back val: "+r+" and exception "+t);
                                       })
                                       .onItem().invoke(v -> Assertions.fail(message))
                                       .onFailure(exceptionClass)
                                       .recoverWithItem(() -> null)
                                       .map(v -> null);
                           }

@FroMage
Copy link
Contributor Author

FroMage commented Jul 13, 2020

Note that this test was run on ORM with a transaction originally, and if I make it run into a transaction, like this:

    @Test
    public void test() {
        // persistAndFlush
        MyPerson person1 = new MyPerson();
        person1.name = "testFLush1";
        person1.uniqueName = "unique";
        // get your Mutiny.Session however you like
        transactional(session ->
            persistAndFlush(session, person1)
            .flatMap(v -> {
                MyPerson person2 = new MyPerson();
                person2.name = "testFLush2";
                person2.uniqueName = "unique";

                // FIXME should be PersistenceException see https://github.com/hibernate/hibernate-reactive/issues/280
                return assertThrows(PgException.class,
                                    () -> persistAndFlush(session, person2),
                        "Should have failed");
            }).flatMap(v -> {
                System.err.println("DONE before delete ?");
                return session.createQuery("DELETE FROM MyPerson").executeUpdate();
            })
            .map(v -> {
                System.err.println("deleted "+v);
                return "OK";
            })
        ).await().indefinitely();
    }

    private <T> Uni<T> transactional(Function<Mutiny.Session, Uni<T>> work) {
        return Panache.getEntityManager().flatMap(session -> session.withTransaction(t -> work.apply(session)));
    }

    private Uni<Void> persistAndFlush(Session session, MyPerson person) {
        return session.persist(person).flatMap(v -> session.flush()).map(v -> null);
    }



    private Uni<Void> assertThrows(Class<? extends Throwable> exceptionClass,
                                   Supplier<Uni<?>> f,
                                   String message) {
                               System.err.println("Asserting "+message+" hoping to get a "+exceptionClass);
                               Uni<?> uni;
                               try {
                                   uni = f.get();
                               }catch(Throwable t) {
                                   uni = Uni.createFrom().failure(t);
                               }
                               return uni
                                       .onItemOrFailure().invoke((r, t) -> {
                                           System.err.println("Got back val: "+r+" and exception "+t);
                                       })
                                       .onItem().invoke(v -> Assertions.fail(message))
                                       .onFailure(exceptionClass)
                                       .recoverWithItem(() -> null)
                                       .map(v -> null);
                           }

I get slightly different results, in that now the delete all will yield this exception:

io.vertx.core.VertxException: Transaction already completed
	at io.vertx.sqlclient.impl.TransactionImpl.checkPending(TransactionImpl.java:95)
	at io.vertx.sqlclient.impl.TransactionImpl.schedule(TransactionImpl.java:119)
	at io.vertx.sqlclient.impl.TransactionImpl.schedule(TransactionImpl.java:112)
	at io.vertx.sqlclient.impl.SqlClientBase$PreparedQueryImpl.execute(SqlClientBase.java:103)
	at org.hibernate.reactive.pool.impl.SqlClientConnection.lambda$preparedQuery$3(SqlClientConnection.java:117)
	at org.hibernate.reactive.pool.impl.Handlers.toCompletionStage(Handlers.java:24)
	at org.hibernate.reactive.pool.impl.SqlClientConnection.preparedQuery(SqlClientConnection.java:116)
	at org.hibernate.reactive.pool.impl.SqlClientConnection.update(SqlClientConnection.java:100)
	at org.hibernate.reactive.pool.impl.SqlClientConnection.update(SqlClientConnection.java:55)
	at org.hibernate.reactive.persister.entity.impl.ReactiveAbstractEntityPersister.insertReactive(ReactiveAbstractEntityPersister.java:225)
	at org.hibernate.reactive.persister.entity.impl.ReactiveAbstractEntityPersister.lambda$insertReactive$7(ReactiveAbstractEntityPersister.java:163)
	at java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:981)
	at java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2124)
	at java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:110)
	at org.hibernate.reactive.persister.entity.impl.ReactiveAbstractEntityPersister.insertReactive(ReactiveAbstractEntityPersister.java:162)
	at org.hibernate.reactive.engine.impl.ReactiveEntityRegularInsertAction.lambda$reactiveExecute$2(ReactiveEntityRegularInsertAction.java:70)
	at java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:981)
	at java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2124)
	at java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:110)
	at org.hibernate.reactive.engine.impl.ReactiveEntityRegularInsertAction.reactiveExecute(ReactiveEntityRegularInsertAction.java:55)
	at org.hibernate.reactive.engine.ReactiveActionQueue.lambda$executeActions$7(ReactiveActionQueue.java:646)
	at java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:981)
	at java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2124)
	at java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:110)
	at org.hibernate.reactive.engine.ReactiveActionQueue.executeActions(ReactiveActionQueue.java:646)
	at org.hibernate.reactive.engine.ReactiveActionQueue.lambda$executeActions$5(ReactiveActionQueue.java:546)
	at java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:981)
	at java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2124)
	at java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:110)
	at org.hibernate.reactive.engine.ReactiveActionQueue.executeActions(ReactiveActionQueue.java:546)
	at org.hibernate.reactive.event.impl.AbstractReactiveFlushingEventListener.lambda$performExecutions$0(AbstractReactiveFlushingEventListener.java:65)
	at java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:981)
	at java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2124)
	at java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:110)
	at org.hibernate.reactive.event.impl.AbstractReactiveFlushingEventListener.performExecutions(AbstractReactiveFlushingEventListener.java:59)
	at org.hibernate.reactive.event.impl.DefaultReactiveAutoFlushEventListener.lambda$reactiveOnAutoFlush$3(DefaultReactiveAutoFlushEventListener.java:51)
	at java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:981)
	at java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2124)
	at java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:110)
	at org.hibernate.reactive.event.impl.DefaultReactiveAutoFlushEventListener.reactiveOnAutoFlush(DefaultReactiveAutoFlushEventListener.java:46)
	at org.hibernate.reactive.session.impl.ReactiveSessionImpl.lambda$fire$39(ReactiveSessionImpl.java:1038)
	at java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:981)
	at java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2124)
	at java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:110)
	at org.hibernate.reactive.session.impl.ReactiveSessionImpl.fire(ReactiveSessionImpl.java:1038)
	at org.hibernate.reactive.session.impl.ReactiveSessionImpl.reactiveAutoFlushIfRequired(ReactiveSessionImpl.java:417)
	at org.hibernate.reactive.session.impl.ReactiveSessionImpl.executeReactiveUpdate(ReactiveSessionImpl.java:606)
	at org.hibernate.reactive.session.impl.ReactiveQueryImpl.doExecuteReactiveUpdate(ReactiveQueryImpl.java:93)
	at org.hibernate.reactive.session.impl.ReactiveQueryImpl.executeReactiveUpdate(ReactiveQueryImpl.java:85)
	at org.hibernate.reactive.mutiny.impl.MutinyQueryImpl.executeUpdate(MutinyQueryImpl.java:134)
	at io.quarkus.it.panache.reactive.PanacheFunctionalityTest.lambda$3(PanacheFunctionalityTest.java:90)
	at io.smallrye.mutiny.operators.UniOnItemFlatMap.invokeAndSubstitute(UniOnItemFlatMap.java:31)
	at io.smallrye.mutiny.operators.UniOnItemFlatMap$2.onItem(UniOnItemFlatMap.java:75)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onItem$1(ContextPropagationUniInterceptor.java:35)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onItem(ContextPropagationUniInterceptor.java:35)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onItem(UniSerializedSubscriber.java:72)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onItem$1(ContextPropagationUniInterceptor.java:35)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onItem(ContextPropagationUniInterceptor.java:35)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onItem(UniSerializedSubscriber.java:72)
	at io.smallrye.mutiny.operators.UniDelegatingSubscriber.onItem(UniDelegatingSubscriber.java:24)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onItem$1(ContextPropagationUniInterceptor.java:35)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onItem(ContextPropagationUniInterceptor.java:35)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onItem(UniSerializedSubscriber.java:72)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onItem$1(ContextPropagationUniInterceptor.java:35)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onItem(ContextPropagationUniInterceptor.java:35)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onItem(UniSerializedSubscriber.java:72)
	at io.smallrye.mutiny.operators.UniOnItemMap$1.onItem(UniOnItemMap.java:39)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onItem$1(ContextPropagationUniInterceptor.java:35)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onItem(ContextPropagationUniInterceptor.java:35)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onItem(UniSerializedSubscriber.java:72)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onItem$1(ContextPropagationUniInterceptor.java:35)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onItem(ContextPropagationUniInterceptor.java:35)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onItem(UniSerializedSubscriber.java:72)
	at io.smallrye.mutiny.operators.UniDelegatingSubscriber.onItem(UniDelegatingSubscriber.java:24)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onItem$1(ContextPropagationUniInterceptor.java:35)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onItem(ContextPropagationUniInterceptor.java:35)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onItem(UniSerializedSubscriber.java:72)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onItem$1(ContextPropagationUniInterceptor.java:35)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onItem(ContextPropagationUniInterceptor.java:35)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onItem(UniSerializedSubscriber.java:72)
	at io.smallrye.mutiny.operators.DefaultUniEmitter.complete(DefaultUniEmitter.java:36)
	at io.smallrye.mutiny.groups.UniCreate.lambda$item$2(UniCreate.java:205)
	at io.smallrye.mutiny.operators.UniCreateWithEmitter.subscribing(UniCreateWithEmitter.java:22)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.subscribe(UniSerializedSubscriber.java:43)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.subscribe(UniSerializedSubscriber.java:38)
	at io.smallrye.mutiny.groups.UniSubscribe.withSubscriber(UniSubscribe.java:49)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$2.lambda$subscribing$0(ContextPropagationUniInterceptor.java:51)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$2.subscribing(ContextPropagationUniInterceptor.java:51)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.subscribe(UniSerializedSubscriber.java:43)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.subscribe(UniSerializedSubscriber.java:38)
	at io.smallrye.mutiny.groups.UniSubscribe.withSubscriber(UniSubscribe.java:49)
	at io.smallrye.mutiny.operators.UniOnItemFlatMap.handleInnerSubscription(UniOnItemFlatMap.java:58)
	at io.smallrye.mutiny.operators.UniOnItemFlatMap.invokeAndSubstitute(UniOnItemFlatMap.java:43)
	at io.smallrye.mutiny.operators.UniOnFailureFlatMap$1.onFailure(UniOnFailureFlatMap.java:47)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onFailure$2(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onFailure(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onFailure(UniSerializedSubscriber.java:85)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onFailure$2(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onFailure(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onFailure(UniSerializedSubscriber.java:85)
	at io.smallrye.mutiny.operators.UniOnItemConsume$1.onFailure(UniOnItemConsume.java:50)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onFailure$2(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onFailure(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onFailure(UniSerializedSubscriber.java:85)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onFailure$2(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onFailure(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onFailure(UniSerializedSubscriber.java:85)
	at io.smallrye.mutiny.operators.UniOnItemOrFailureConsume$1.onFailure(UniOnItemOrFailureConsume.java:31)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onFailure$2(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onFailure(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onFailure(UniSerializedSubscriber.java:85)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onFailure$2(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onFailure(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onFailure(UniSerializedSubscriber.java:85)
	at io.smallrye.mutiny.operators.UniDelegatingSubscriber.onFailure(UniDelegatingSubscriber.java:29)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onFailure$2(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onFailure(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onFailure(UniSerializedSubscriber.java:85)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onFailure$2(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onFailure(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onFailure(UniSerializedSubscriber.java:85)
	at io.smallrye.mutiny.operators.UniDelegatingSubscriber.onFailure(UniDelegatingSubscriber.java:29)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onFailure$2(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onFailure(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onFailure(UniSerializedSubscriber.java:85)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onFailure$2(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onFailure(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onFailure(UniSerializedSubscriber.java:85)
	at io.smallrye.mutiny.operators.UniDelegatingSubscriber.onFailure(UniDelegatingSubscriber.java:29)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onFailure$2(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onFailure(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onFailure(UniSerializedSubscriber.java:85)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.lambda$onFailure$2(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.context.SmallRyeThreadContext.lambda$withContext$0(SmallRyeThreadContext.java:217)
	at io.smallrye.mutiny.context.ContextPropagationUniInterceptor$1.onFailure(ContextPropagationUniInterceptor.java:40)
	at io.smallrye.mutiny.operators.UniSerializedSubscriber.onFailure(UniSerializedSubscriber.java:85)
	at io.smallrye.mutiny.operators.UniCreateFromCompletionStage.lambda$forwardFromCompletionStage$1(UniCreateFromCompletionStage.java:25)
	at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:760)
	at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:736)
	at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474)
	at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1977)
	at org.hibernate.reactive.pool.impl.Handlers.lambda$toCompletionStage$0(Handlers.java:29)
	at io.vertx.sqlclient.impl.SqlResultHandler.fail(SqlResultHandler.java:102)
	at io.vertx.sqlclient.impl.SqlResultHandler.handle(SqlResultHandler.java:88)
	at io.vertx.sqlclient.impl.SqlResultHandler.handle(SqlResultHandler.java:33)
	at io.vertx.sqlclient.impl.TransactionImpl.lambda$schedule$1(TransactionImpl.java:110)
	at io.vertx.sqlclient.impl.TransactionImpl.lambda$null$2(TransactionImpl.java:139)
	at io.vertx.sqlclient.impl.TransactionImpl.lambda$doQuery$6(TransactionImpl.java:215)
	at io.vertx.sqlclient.impl.SocketConnectionBase.handleMessage(SocketConnectionBase.java:188)
	at io.vertx.sqlclient.impl.SocketConnectionBase.lambda$init$0(SocketConnectionBase.java:78)
	at io.vertx.core.net.impl.NetSocketImpl.lambda$new$2(NetSocketImpl.java:101)
	at io.vertx.core.streams.impl.InboundBuffer.handleEvent(InboundBuffer.java:237)
	at io.vertx.core.streams.impl.InboundBuffer.write(InboundBuffer.java:127)
	at io.vertx.core.net.impl.NetSocketImpl.handleMessage(NetSocketImpl.java:357)
	at io.vertx.core.impl.ContextImpl.executeTask(ContextImpl.java:366)
	at io.vertx.core.impl.EventLoopContext.execute(EventLoopContext.java:43)
	at io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:229)
	at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:173)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
	at io.vertx.pgclient.impl.codec.PgEncoder.lambda$write$0(PgEncoder.java:78)
	at io.vertx.pgclient.impl.codec.PgCommandCodec.handleReadyForQuery(PgCommandCodec.java:136)
	at io.vertx.pgclient.impl.codec.PgDecoder.decodeReadyForQuery(PgDecoder.java:227)
	at io.vertx.pgclient.impl.codec.PgDecoder.channelRead(PgDecoder.java:86)
	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:748)

Which may or may not be the same problem. Looks like the first insert that tripped up the unicity constraint invalidated the transaction? Perhaps it's a hint.

@DavideD
Copy link
Member

DavideD commented Jul 13, 2020

THanks, I will have a look

DavideD added a commit to DavideD/hibernate-reactive that referenced this issue Jul 14, 2020
  When an exception occurs we want to wrap it in a PersistenceException
  following the Hibernate ORM behavior.
DavideD added a commit to DavideD/hibernate-reactive that referenced this issue Jul 14, 2020
DavideD added a commit to DavideD/hibernate-reactive that referenced this issue Jul 14, 2020
@DavideD
Copy link
Member

DavideD commented Jul 14, 2020

I've sent a PR for the case without the transaction: #283

Wrong issue

@DavideD
Copy link
Member

DavideD commented Jul 14, 2020

Using

return session
             .clear()
             .createQuery("DELETE FROM MyPerson").executeUpdate();

seems to work for me.

I think what's happening is that the constraint violation doesn't clear the queue and when you try to execute the query it tries to persist the entity again.

@gavinking , @gbadner: I'm still checking but I assume that if this is what's happening then it's a bug, isn't it?

@DavideD
Copy link
Member

DavideD commented Jul 14, 2020

Also, @FroMage, the exception thrown is going to be a CompletionException and not a PgException (PgException is going to be the cause):

return assertThrows(CompletionException.class, () -> persistAndFlush(session, person2), "Should have failed");

@gavinking
Copy link
Member

Well when I initially read the problem description I wondered if @FroMage was continuing to use a hosed session after an exception occurred.

The rule is that if a session operation throws an exception, you're supposed to obtain a new one.

@DavideD
Copy link
Member

DavideD commented Jul 14, 2020

Yes, he's using the same session

@DavideD
Copy link
Member

DavideD commented Jul 14, 2020

@FroMage Could you let me know if it works if you account for those things, please?

@FroMage
Copy link
Contributor Author

FroMage commented Jul 16, 2020

Mmm, but the same works for the ORM version, so are you saying the Quarkus ORM extension automatically renews the session if an exception occurs?

@FroMage
Copy link
Contributor Author

FroMage commented Jul 16, 2020

@DavideD I don't get a CompeltionException because those get unwrapped by Mutiny (or by HR I don't know).

@DavideD
Copy link
Member

DavideD commented Jul 21, 2020

Mmm, but the same works for the ORM version, so are you saying the Quarkus ORM extension automatically renews the session if an exception occurs?

I guess it might work but I don't think you are supposed to rely on it

@DavideD
Copy link
Member

DavideD commented Jul 21, 2020

I'm closing this one because reusing the session after an exception is a no-no (even if it might work in some cases).

Thanks everybody.

@DavideD DavideD closed this as completed Jul 21, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants