KubernetesLock#lockInterruptibly()

This commit is contained in:
Gytis Trikleris
2018-05-24 18:54:52 +02:00
committed by Ioannis Canellos
parent 52e82796ba
commit 7e92d8a03a
2 changed files with 60 additions and 25 deletions

View File

@@ -22,7 +22,7 @@ import java.util.concurrent.locks.Lock;
public class KubernetesLock implements Lock {
private static final int RETRY_PERIOD = 100;
private static final int LOCK_RETRY_INTERVAL = 100;
private final ConfigMapLockRepository repository;
@@ -47,7 +47,7 @@ public class KubernetesLock implements Lock {
if (repository.create(name, holder, expiration)) {
return;
}
Thread.sleep(RETRY_PERIOD);
Thread.sleep(LOCK_RETRY_INTERVAL);
} catch (InterruptedException e) {
// This method cannot be interrupted
}
@@ -56,7 +56,18 @@ public class KubernetesLock implements Lock {
@Override
public void lockInterruptibly() throws InterruptedException {
// TODO same as lock(), but thread can be interrupted
repository.deleteIfExpired(name);
while (true) {
try {
if (repository.create(name, holder, expiration)) {
return;
}
Thread.sleep(LOCK_RETRY_INTERVAL);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw e;
}
}
}
@Override

View File

@@ -33,15 +33,8 @@ public class KubernetesLockTest {
}
@Test
public void shouldWaitUntilLockCanBeAcquired() {
given(repository.create(NAME, HOLDER, 0)).will(new Answer<Boolean>() {
private int callsCounter = 0;
@Override
public Boolean answer(InvocationOnMock invocationOnMock) {
return callsCounter++ > 0;
}
});
public void lockShouldWaitUntilLockCanBeAcquired() {
given(repository.create(NAME, HOLDER, 0)).will(new LockInSecondCall());
KubernetesLock lock = new KubernetesLock(repository, NAME, HOLDER, 0);
lock.lock();
@@ -52,17 +45,7 @@ public class KubernetesLockTest {
@Test
public void lockShouldNotBeInterrupted() {
given(repository.create(NAME, HOLDER, 0)).will(new Answer<Boolean>() {
private int callsCounter = 0;
@Override
public Boolean answer(InvocationOnMock invocationOnMock) throws InterruptedException {
if (callsCounter++ > 0) {
return true;
}
throw new InterruptedException("test exception");
}
});
given(repository.create(NAME, HOLDER, 0)).will(new InterrupFirstCall());
KubernetesLock lock = new KubernetesLock(repository, NAME, HOLDER, 0);
lock.lock();
@@ -72,13 +55,33 @@ public class KubernetesLockTest {
}
@Test
public void shouldLockWithLockInterruptibly() {
public void shouldLockWithLockInterruptibly() throws InterruptedException {
given(repository.create(NAME, HOLDER, 0)).willReturn(true);
KubernetesLock lock = new KubernetesLock(repository, NAME, HOLDER, 0);
lock.lockInterruptibly();
verify(repository).deleteIfExpired(NAME);
verify(repository).create(NAME, HOLDER, 0);
}
@Test
public void lockInterruptiblyShouldBeInterrupted() {
public void lockInterruptiblyShouldWaitUntilLockCanBeAcquired() throws InterruptedException {
given(repository.create(NAME, HOLDER, 0)).will(new LockInSecondCall());
KubernetesLock lock = new KubernetesLock(repository, NAME, HOLDER, 0);
lock.lockInterruptibly();
verify(repository).deleteIfExpired(NAME);
verify(repository, times(2)).create(NAME, HOLDER, 0);
}
@Test(expected = InterruptedException.class)
public void lockInterruptiblyShouldBeInterrupted() throws InterruptedException {
given(repository.create(NAME, HOLDER, 0)).will(new InterrupFirstCall());
KubernetesLock lock = new KubernetesLock(repository, NAME, HOLDER, 0);
lock.lockInterruptibly();
}
@Test
@@ -107,4 +110,25 @@ public class KubernetesLockTest {
lock.newCondition();
}
private static class LockInSecondCall implements Answer<Boolean> {
private int callsCounter = 0;
@Override
public Boolean answer(InvocationOnMock invocationOnMock) {
return callsCounter++ > 0;
}
}
private static class InterrupFirstCall implements Answer<Boolean> {
private int callsCounter = 0;
@Override
public Boolean answer(InvocationOnMock invocationOnMock) throws InterruptedException {
if (callsCounter++ > 0) {
return true;
}
throw new InterruptedException("test exception");
}
}
}