Accquire pessimistic account locks by sets of identifiers instead of lists

This commit is contained in:
Jon Chambers
2025-07-14 12:12:10 -04:00
committed by Jon Chambers
parent 1a8ebf80b5
commit e62b3d390f
7 changed files with 27 additions and 25 deletions

View File

@@ -10,7 +10,7 @@ import static org.mockito.Mockito.verify;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBLockClient;
import com.amazonaws.services.dynamodbv2.ReleaseLockOptions;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
@@ -48,7 +48,7 @@ class AccountLockManagerTest {
@Test
void withLock() throws Exception {
accountLockManager.withLock(List.of(FIRST_PNI, SECOND_PNI), () -> null, executor);
accountLockManager.withLock(Set.of(FIRST_PNI, SECOND_PNI), () -> null, executor);
verify(lockClient, times(2)).acquireLock(any());
verify(lockClient, times(2)).releaseLock(any(ReleaseLockOptions.class));
@@ -56,7 +56,7 @@ class AccountLockManagerTest {
@Test
void withLockTaskThrowsException() throws InterruptedException {
assertThrows(RuntimeException.class, () -> accountLockManager.withLock(List.of(FIRST_PNI, SECOND_PNI), () -> {
assertThrows(RuntimeException.class, () -> accountLockManager.withLock(Set.of(FIRST_PNI, SECOND_PNI), () -> {
throw new RuntimeException();
}, executor));
@@ -68,7 +68,7 @@ class AccountLockManagerTest {
void withLockEmptyList() {
final Runnable task = mock(Runnable.class);
assertThrows(IllegalArgumentException.class, () -> accountLockManager.withLock(Collections.emptyList(), () -> null,
assertThrows(IllegalArgumentException.class, () -> accountLockManager.withLock(Collections.emptySet(), () -> null,
executor));
verify(task, never()).run();
}
@@ -76,7 +76,7 @@ class AccountLockManagerTest {
@Test
void withLockAsync() throws InterruptedException {
accountLockManager.withLockAsync(
List.of(FIRST_PNI, SECOND_PNI), () -> CompletableFuture.completedFuture(null), executor).join();
Set.of(FIRST_PNI, SECOND_PNI), () -> CompletableFuture.completedFuture(null), executor).join();
verify(lockClient, times(2)).acquireLock(any());
verify(lockClient, times(2)).releaseLock(any(ReleaseLockOptions.class));
@@ -86,7 +86,7 @@ class AccountLockManagerTest {
void withLockAsyncTaskThrowsException() throws InterruptedException {
assertThrows(RuntimeException.class,
() -> accountLockManager.withLockAsync(
List.of(FIRST_PNI, SECOND_PNI), () -> CompletableFuture.failedFuture(new RuntimeException()), executor)
Set.of(FIRST_PNI, SECOND_PNI), () -> CompletableFuture.failedFuture(new RuntimeException()), executor)
.join());
verify(lockClient, times(2)).acquireLock(any());
@@ -98,7 +98,7 @@ class AccountLockManagerTest {
final Runnable task = mock(Runnable.class);
assertThrows(IllegalArgumentException.class,
() -> accountLockManager.withLockAsync(Collections.emptyList(), () -> CompletableFuture.completedFuture(null),
() -> accountLockManager.withLockAsync(Collections.emptySet(), () -> CompletableFuture.completedFuture(null),
executor));
verify(task, never()).run();

View File

@@ -10,8 +10,8 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doAnswer;
@@ -112,9 +112,9 @@ class AccountsManagerConcurrentModificationIntegrationTest {
doAnswer(invocation -> {
final Callable<?> task = invocation.getArgument(1);
return task.call();
}).when(accountLockManager).withLock(anyList(), any(), any());
}).when(accountLockManager).withLock(anySet(), any(), any());
when(accountLockManager.withLockAsync(anyList(), any(), any())).thenAnswer(invocation -> {
when(accountLockManager.withLockAsync(anySet(), any(), any())).thenAnswer(invocation -> {
final Supplier<CompletableFuture<?>> taskSupplier = invocation.getArgument(1);
taskSupplier.get().join();

View File

@@ -16,8 +16,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyByte;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.notNull;
@@ -218,9 +218,9 @@ class AccountsManagerTest {
doAnswer(invocation -> {
final Callable<?> task = invocation.getArgument(1);
return task.call();
}).when(accountLockManager).withLock(anyList(), any(), any());
}).when(accountLockManager).withLock(anySet(), any(), any());
when(accountLockManager.withLockAsync(anyList(), any(), any())).thenAnswer(invocation -> {
when(accountLockManager.withLockAsync(anySet(), any(), any())).thenAnswer(invocation -> {
final Supplier<CompletableFuture<?>> taskSupplier = invocation.getArgument(1);
return taskSupplier.get();
});

View File

@@ -11,7 +11,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -131,9 +131,9 @@ class AccountsManagerUsernameIntegrationTest {
doAnswer(invocation -> {
final Callable<?> task = invocation.getArgument(1);
return task.call();
}).when(accountLockManager).withLock(anyList(), any(), any());
}).when(accountLockManager).withLock(anySet(), any(), any());
when(accountLockManager.withLockAsync(anyList(), any(), any())).thenAnswer(invocation -> {
when(accountLockManager.withLockAsync(anySet(), any(), any())).thenAnswer(invocation -> {
final Supplier<CompletableFuture<?>> taskSupplier = invocation.getArgument(1);
taskSupplier.get().join();