Search in sources :

Example 1 with LockTestRow

use of com.cadenzauk.siesta.model.LockTestRow in project siesta by cadenzauk.

the class LockingIntegrationTest method updateWithoutTimeout.

@Test
void updateWithoutTimeout() throws InterruptedException {
    long id = newId();
    Database database = TestDatabase.testDatabase(dataSource);
    Synchronization thread1 = new Synchronization();
    Synchronization thread2 = new Synchronization();
    database.insert(new LockTestRow(id, 1, "Initial"));
    CompletableFuture<Boolean> update1 = CompletableFuture.supplyAsync(() -> performUpdate(false, database, id, thread1));
    CompletableFuture<Boolean> update2 = CompletableFuture.supplyAsync(() -> performUpdate(false, database, id, thread2));
    thread1.select();
    thread2.select();
    thread1.update();
    thread2.updateAsync();
    TimeUnit.MILLISECONDS.sleep(100);
    thread1.commit();
    boolean update1Succeeded = update1.join();
    boolean update2Succeeded = update2.join();
    assertThat(update1Succeeded, is(true));
    assertThat(update2Succeeded, is(false));
}
Also used : TestDatabase(com.cadenzauk.siesta.model.TestDatabase) LockTestRow(com.cadenzauk.siesta.model.LockTestRow) Test(org.junit.jupiter.api.Test)

Example 2 with LockTestRow

use of com.cadenzauk.siesta.model.LockTestRow in project siesta by cadenzauk.

the class LockingIntegrationTest method updateWithTimeout1.

@Test
void updateWithTimeout1() {
    assumeTrue(dialect.supportsLockTimeout(), "Database does not support lock timeouts.");
    long id = newId();
    Database database = TestDatabase.testDatabase(dataSource);
    Synchronization thread1 = new Synchronization();
    Synchronization thread2 = new Synchronization();
    CompletableFuture<Boolean> update1 = CompletableFuture.supplyAsync(() -> performUpdate(true, database, id, thread1));
    CompletableFuture<Boolean> update2 = CompletableFuture.supplyAsync(() -> performUpdate(true, database, id, thread2));
    database.insert(new LockTestRow(id, 1, "Initial"));
    thread1.select();
    thread1.update();
    thread2.select();
    thread2.update();
    thread1.commit();
    boolean update2Succeeded = update2.join();
    boolean update1Succeeded = update1.join();
    assertThat(update1Succeeded, is(true));
    assertThat(update2Succeeded, is(false));
}
Also used : TestDatabase(com.cadenzauk.siesta.model.TestDatabase) LockTestRow(com.cadenzauk.siesta.model.LockTestRow) Test(org.junit.jupiter.api.Test)

Example 3 with LockTestRow

use of com.cadenzauk.siesta.model.LockTestRow in project siesta by cadenzauk.

the class LockingIntegrationTest method performUpdate.

private boolean performUpdate(boolean setLockTimeout, Database database, long id, Synchronization synchronization) {
    try (CompositeAutoCloseable closeable = new CompositeAutoCloseable()) {
        synchronization.waitToSelect();
        Transaction transaction = closeable.add(database.beginTransaction());
        Optional<Integer> currentRevision = database.from(LockTestRow.class).select(LockTestRow::revision).where(LockTestRow::id).isEqualTo(id).optional(transaction);
        LOG.info("Current revision = {}", currentRevision);
        Optional<Integer> uncommittedRevision = database.from(LockTestRow.class).select(LockTestRow::revision).where(LockTestRow::id).isEqualTo(id).withIsolation(IsolationLevel.UNCOMMITTED_READ).optional(transaction);
        LOG.info("Uncommitted revision = {}", uncommittedRevision);
        if (uncommittedRevision.orElse(0) > currentRevision.orElse(0)) {
            LOG.info("Updated by another transaction - could bail at this point", currentRevision, uncommittedRevision);
        }
        synchronization.waitToUpdate();
        if (setLockTimeout) {
            closeable.add(database.withLockTimeout(transaction, 0, TimeUnit.SECONDS));
        }
        int updateCount = currentRevision.map(curr -> database.update(LockTestRow.class).set(LockTestRow::updatedBy).to(Thread.currentThread().getName()).set(LockTestRow::revision).to(curr + 1).where(LockTestRow::id).isEqualTo(id).and(LockTestRow::revision).isEqualTo(curr).execute(transaction)).orElseGet(() -> database.insert(transaction, new LockTestRow(id, 1, Thread.currentThread().getName())));
        LOG.info("Update count = {}", updateCount);
        if (updateCount == 0) {
            synchronization.finished();
            return false;
        }
        synchronization.waitToCommit();
        transaction.commit();
        LOG.info("Committed");
        synchronization.finished();
        return true;
    } catch (RuntimeSqlException e) {
        LOG.error("Update failed", e);
        synchronization.updateFailed();
        return false;
    }
}
Also used : Logger(org.slf4j.Logger) LockTestRow(com.cadenzauk.siesta.model.LockTestRow) TestDatabase(com.cadenzauk.siesta.model.TestDatabase) LoggerFactory(org.slf4j.LoggerFactory) CompletableFuture(java.util.concurrent.CompletableFuture) CompositeAutoCloseable(com.cadenzauk.core.lang.CompositeAutoCloseable) Test(org.junit.jupiter.api.Test) TimeUnit(java.util.concurrent.TimeUnit) RuntimeSqlException(com.cadenzauk.core.sql.RuntimeSqlException) Assumptions.assumeTrue(org.junit.jupiter.api.Assumptions.assumeTrue) Optional(java.util.Optional) Matchers.is(org.hamcrest.Matchers.is) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) RuntimeSqlException(com.cadenzauk.core.sql.RuntimeSqlException) CompositeAutoCloseable(com.cadenzauk.core.lang.CompositeAutoCloseable) LockTestRow(com.cadenzauk.siesta.model.LockTestRow)

Example 4 with LockTestRow

use of com.cadenzauk.siesta.model.LockTestRow in project siesta by cadenzauk.

the class LockingIntegrationTest method updateWithTimeout3.

@Test
void updateWithTimeout3() {
    assumeTrue(dialect.supportsLockTimeout(), "Database does not support lock timeouts.");
    Database database = TestDatabase.testDatabase(dataSource);
    long id = newId();
    Synchronization thread1 = new Synchronization();
    Synchronization thread2 = new Synchronization();
    CompletableFuture<Boolean> update1 = CompletableFuture.supplyAsync(() -> performUpdate(true, database, id, thread1));
    CompletableFuture<Boolean> update2 = CompletableFuture.supplyAsync(() -> performUpdate(true, database, id, thread2));
    database.insert(new LockTestRow(id, 1, "Initial"));
    thread1.select();
    thread1.update();
    thread2.select();
    thread1.commit();
    thread2.update();
    boolean update2Succeeded = update2.join();
    boolean update1Succeeded = update1.join();
    assertThat(update1Succeeded, is(true));
    assertThat(update2Succeeded, is(false));
}
Also used : TestDatabase(com.cadenzauk.siesta.model.TestDatabase) LockTestRow(com.cadenzauk.siesta.model.LockTestRow) Test(org.junit.jupiter.api.Test)

Example 5 with LockTestRow

use of com.cadenzauk.siesta.model.LockTestRow in project siesta by cadenzauk.

the class LockingIntegrationTest method updateWithTimeout2.

@Test
void updateWithTimeout2() {
    assumeTrue(dialect.supportsLockTimeout(), "Database does not support lock timeouts.");
    Database database = TestDatabase.testDatabase(dataSource);
    long id = newId();
    Synchronization thread1 = new Synchronization();
    Synchronization thread2 = new Synchronization();
    CompletableFuture<Boolean> update1 = CompletableFuture.supplyAsync(() -> performUpdate(true, database, id, thread1));
    CompletableFuture<Boolean> update2 = CompletableFuture.supplyAsync(() -> performUpdate(true, database, id, thread2));
    database.insert(new LockTestRow(id, 1, "Initial"));
    thread1.select();
    thread2.select();
    thread1.update();
    thread2.update();
    thread1.commit();
    boolean update2Succeeded = update2.join();
    boolean update1Succeeded = update1.join();
    assertThat(update1Succeeded, is(true));
    assertThat(update2Succeeded, is(false));
}
Also used : TestDatabase(com.cadenzauk.siesta.model.TestDatabase) LockTestRow(com.cadenzauk.siesta.model.LockTestRow) Test(org.junit.jupiter.api.Test)

Aggregations

LockTestRow (com.cadenzauk.siesta.model.LockTestRow)5 TestDatabase (com.cadenzauk.siesta.model.TestDatabase)5 Test (org.junit.jupiter.api.Test)5 CompositeAutoCloseable (com.cadenzauk.core.lang.CompositeAutoCloseable)1 RuntimeSqlException (com.cadenzauk.core.sql.RuntimeSqlException)1 Optional (java.util.Optional)1 CompletableFuture (java.util.concurrent.CompletableFuture)1 TimeUnit (java.util.concurrent.TimeUnit)1 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)1 Matchers.is (org.hamcrest.Matchers.is)1 Assumptions.assumeTrue (org.junit.jupiter.api.Assumptions.assumeTrue)1 Logger (org.slf4j.Logger)1 LoggerFactory (org.slf4j.LoggerFactory)1