Test that read-modify-write is atomic on account updates

When updating an account the account updater gets the current
AccountState provided so that based on this account state it can be
decided which update should be done. If a concurrent request updates the
account after the account updater is invoked it is expected that the
account update fails with LockFailure because the HEAD of the user
branch was updated and no longer matches the revision from which the
account was read. The LockFailure then causes a retry of the account
update and the account updater is invoked again, this time with a new
AccountState that includes the modifications that were done by the
concurrent update. This way the full read-modify-write sequence is
atomic on account updates.

Change-Id: Ia570cd2e99557bf942c1571eae3ef72dd07663dd
Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
Edwin Kempin
2018-01-11 15:47:44 +01:00
parent dc22ac98ba
commit a0bc739b29
2 changed files with 78 additions and 4 deletions

View File

@@ -285,8 +285,13 @@ public class AccountsUpdate {
private final ExternalIdNotesLoader extIdNotesLoader;
private final PersonIdent committerIdent;
private final PersonIdent authorIdent;
// Invoked after reading the account config.
private final Runnable afterReadRevision;
// Invoked after updating the account but before committing the changes.
private final Runnable beforeCommit;
private AccountsUpdate(
GitRepositoryManager repoManager,
GitReferenceUpdated gitRefUpdated,
@@ -309,6 +314,7 @@ public class AccountsUpdate {
extIdNotesLoader,
committerIdent,
authorIdent,
Runnables.doNothing(),
Runnables.doNothing());
}
@@ -324,7 +330,8 @@ public class AccountsUpdate {
ExternalIdNotesLoader extIdNotesLoader,
PersonIdent committerIdent,
PersonIdent authorIdent,
Runnable afterReadRevision) {
Runnable afterReadRevision,
Runnable beforeCommit) {
this.repoManager = checkNotNull(repoManager, "repoManager");
this.gitRefUpdated = checkNotNull(gitRefUpdated, "gitRefUpdated");
this.currentUser = currentUser;
@@ -336,7 +343,8 @@ public class AccountsUpdate {
this.extIdNotesLoader = checkNotNull(extIdNotesLoader, "extIdNotesLoader");
this.committerIdent = checkNotNull(committerIdent, "committerIdent");
this.authorIdent = checkNotNull(authorIdent, "authorIdent");
this.afterReadRevision = afterReadRevision;
this.afterReadRevision = checkNotNull(afterReadRevision, "afterReadRevision");
this.beforeCommit = checkNotNull(beforeCommit, "beforeCommit");
}
/**
@@ -491,6 +499,8 @@ public class AccountsUpdate {
}
private void commit(Repository allUsersRepo, UpdatedAccount updatedAccount) throws IOException {
beforeCommit.run();
BatchRefUpdate batchRefUpdate = allUsersRepo.getRefDatabase().newBatchUpdate();
if (updatedAccount.isCreated()) {
commitNewAccountConfig(