Simplify optimistic write logic

This commit is contained in:
Jon Chambers 2021-08-03 11:54:26 -04:00 committed by GitHub
parent 23f9199439
commit bcb89924b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 13 additions and 37 deletions

View File

@ -293,47 +293,21 @@ public class AccountsManager {
try (Timer.Context ignored = updateTimer.time()) {
if (!updater.apply(account)) {
return account;
}
{
// optimistically increment version
final int originalVersion = account.getVersion();
account.setVersion(originalVersion + 1);
redisSet(account);
account.setVersion(originalVersion);
}
redisDelete(account);
final UUID uuid = account.getUuid();
updatedAccount = updateWithRetries(account, updater, this::databaseUpdate, () -> databaseGet(uuid).get());
if (dynamoWriteEnabled()) {
runSafelyAndRecordMetrics(() -> {
final Optional<Account> dynamoAccount = dynamoGet(uuid);
if (dynamoAccount.isPresent()) {
if (!updater.apply(dynamoAccount.get())) {
return dynamoAccount;
}
Account dynamoUpdatedAccount = updateWithRetries(dynamoAccount.get(),
updater,
this::dynamoUpdate,
() -> dynamoGet(uuid).get());
return Optional.of(dynamoUpdatedAccount);
}
return Optional.empty();
}, Optional.of(uuid), Optional.of(updatedAccount),
runSafelyAndRecordMetrics(() -> dynamoGet(uuid).map(dynamoAccount ->
updateWithRetries(dynamoAccount, updater, this::dynamoUpdate, () -> dynamoGet(uuid).get())),
Optional.of(uuid),
Optional.of(updatedAccount),
this::compareAccounts,
"update");
}
// set the cache again, so that all updates are coalesced
redisSet(updatedAccount);
}
@ -349,6 +323,10 @@ public class AccountsManager {
private Account updateWithRetries(Account account, Function<Account, Boolean> updater, Consumer<Account> persister,
Supplier<Account> retriever) {
if (!updater.apply(account)) {
return account;
}
final int maxTries = 10;
int tries = 0;

View File

@ -338,16 +338,14 @@ class AccountsManagerTest {
ArgumentCaptor<String> redisSetArgumentCapture = ArgumentCaptor.forClass(String.class);
verify(commands, times(4)).set(anyString(), redisSetArgumentCapture.capture());
verify(commands, times(2)).set(anyString(), redisSetArgumentCapture.capture());
Account firstAccountCached = JsonHelpers.fromJson(redisSetArgumentCapture.getAllValues().get(1), Account.class);
Account secondAccountCached = JsonHelpers.fromJson(redisSetArgumentCapture.getAllValues().get(3), Account.class);
Account accountCached = JsonHelpers.fromJson(redisSetArgumentCapture.getAllValues().get(1), Account.class);
// uuid is @JsonIgnore, so we need to set it for compareAccounts to work
firstAccountCached.setUuid(uuid);
secondAccountCached.setUuid(uuid);
accountCached.setUuid(uuid);
assertEquals(Optional.empty(), accountsManager.compareAccounts(Optional.of(firstAccountCached), Optional.of(secondAccountCached)));
assertEquals(Optional.empty(), accountsManager.compareAccounts(Optional.of(updatedAccount), Optional.of(accountCached)));
}
@Test