-
Notifications
You must be signed in to change notification settings - Fork 173
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
Support unique constraint exceptions when running Vitess. #3386
base: master
Are you sure you want to change the base?
Conversation
transacter.transaction { session -> | ||
session.save(DbMovie("Cinderella", LocalDate.of(1950, 3, 4))) | ||
} | ||
assertFailsWith<ConstraintViolationException> { | ||
transacter.transaction { session -> | ||
session.save(DbMovie("Beauty and the Beast", LocalDate.of(1991, 11, 22))) | ||
session.save(DbMovie("Cinderella", LocalDate.of(2015, 3, 13))) | ||
repeat(5) { // Repeat 5 times to trigger Vitess constraint on a single shard |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should something in the stack be doing these retries automatically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was just to ensure we get at least two writes on a single shard. The unique constraint is limited to each shard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NVM, a single insert causes the constraint violation. Not sure why I needed additional inserts before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LG
use(previous) | ||
try { | ||
use(previous) | ||
} catch (th: GenericJDBCException) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} catch (th: GenericJDBCException) { | |
} catch (exception: GenericJDBCException) { |
use(previous) | ||
} catch (th: GenericJDBCException) { | ||
// Ignore the exception if the connection is already closed. | ||
if (!isConnectionClosed(th)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (!isConnectionClosed(th)) { | |
if (!isConnectionClosed(exception)) { |
} catch (th: GenericJDBCException) { | ||
// Ignore the exception if the connection is already closed. | ||
if (!isConnectionClosed(th)) { | ||
throw th |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw th | |
throw exception |
} | ||
} else { | ||
function() | ||
} | ||
} | ||
|
||
private fun isConnectionClosed(th: GenericJDBCException) = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private fun isConnectionClosed(th: GenericJDBCException) = | |
private fun isConnectionClosed(exception: GenericJDBCException) = |
} | ||
} else { | ||
function() | ||
} | ||
} | ||
|
||
private fun isConnectionClosed(th: GenericJDBCException) = | ||
th.cause?.javaClass == SQLException::class.java && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
th.cause?.javaClass == SQLException::class.java && | |
exception.cause?.javaClass == SQLException::class.java && |
} | ||
} else { | ||
function() | ||
} | ||
} | ||
|
||
private fun isConnectionClosed(th: GenericJDBCException) = | ||
th.cause?.javaClass == SQLException::class.java && | ||
th.cause?.message.equals("Connection is closed") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
th.cause?.message.equals("Connection is closed") | |
exception.cause?.message.equals("Connection is closed") |
@@ -368,9 +367,6 @@ abstract class TransacterTest { | |||
|
|||
@Test | |||
fun constraintViolationCausesTransactionToRollback() { | |||
// Uniqueness constraints aren't reliably enforced on Vitess | |||
assumeTrue(!transacter.config().type.isVitess) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this test is run on non-Vitess databases, should it stay and within an if block that stops it from running for Vitess?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I follow. This block was skipping this test when we're running Vitess. We want to run this test for Vitess as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, thanks
Is this PR still active / wanting to be merged? Or has it been superceded by another one? |
Description
misk-hibernate didn't properly handle
ConstraintViolationException
s when running with Vitess.After the retries are complete, the
ConstraintViolationException
should be thrown, but in the case of Vitess, asession.target(previous)
throws aGenericJDBCException
because the connection is already closed.This PR catches the
GenericJDBCException
and ignores it.Testing Strategy
Update the existing test to include Vitess.
Thank you for contributing to Misk! 🎉