Ensure in-memory model matches state committed to All-Projects

Evict the All-Projects project cache entry after committing changes
to All-Projects in order to ensure the in-memory model and committed
state always match.

If commit() fails we observed that the in-memory model and the commit
state may diverge which has the effect that a user will see a new
service user entry in the UI which disappears when the service user
plugin is reloaded or the All-Projects project cache entry is evicted
for another reason.

Change-Id: Iab01a178bd2e9e90fc491f7c1132c161f39dc631
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUser.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUser.java
index 7f8b3de..296ffef 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUser.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/CreateServiceUser.java
@@ -34,6 +34,7 @@
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountLoader;
+import com.google.gerrit.server.config.AllProjectsName;
 import com.google.gerrit.server.config.ConfigResource;
 import com.google.gerrit.server.config.PluginConfig;
 import com.google.gerrit.server.config.PluginConfigFactory;
@@ -84,6 +85,7 @@
   private final Provider<GetConfig> getConfig;
   private final AccountLoader.Factory accountLoader;
   private final BlockedNameFilter blockedNameFilter;
+  private final ProjectCache projectCache;
 
   @Inject
   CreateServiceUser(
@@ -94,6 +96,7 @@
       @GerritPersonIdent PersonIdent gerritIdent,
       MetaDataUpdate.User metaDataUpdateFactory,
       ProjectCache projectCache,
+      AllProjectsName allProjects,
       Provider<GetConfig> getConfig,
       AccountLoader.Factory accountLoader,
       BlockedNameFilter blockedNameFilter) {
@@ -101,8 +104,9 @@
     this.createAccount = createAccount;
     this.userProvider = userProvider;
     this.metaDataUpdateFactory = metaDataUpdateFactory;
+    this.projectCache = projectCache;
     this.storage = projectCache.getAllProjects().getConfig(pluginName + ".db");
-    this.allProjects = projectCache.getAllProjects().getProject().getNameKey();
+    this.allProjects = allProjects;
     this.rfc2822DateFormatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
     this.rfc2822DateFormatter.setCalendar(
         Calendar.getInstance(gerritIdent.getTimeZone(), Locale.US));
@@ -168,16 +172,20 @@
     Account.Id creatorId = ((IdentifiedUser) user).getAccountId();
     String creationDate = rfc2822DateFormatter.format(new Date());
 
-    Config db = storage.get();
-    db.setInt(USER, username, KEY_CREATOR_ID, creatorId.get());
-    if (creator != null) {
-      db.setString(USER, username, KEY_CREATED_BY, creator);
-    }
-    db.setString(USER, username, KEY_CREATED_AT, creationDate);
+    try {
+      Config db = storage.get();
+      db.setInt(USER, username, KEY_CREATOR_ID, creatorId.get());
+      if (creator != null) {
+        db.setString(USER, username, KEY_CREATED_BY, creator);
+      }
+      db.setString(USER, username, KEY_CREATED_AT, creationDate);
 
-    MetaDataUpdate md = metaDataUpdateFactory.create(allProjects);
-    md.setMessage("Create service user '" + username + "'\n");
-    storage.commit(md);
+      MetaDataUpdate md = metaDataUpdateFactory.create(allProjects);
+      md.setMessage("Create service user '" + username + "'\n");
+      storage.commit(md);
+    } finally {
+      projectCache.evict(allProjects);
+    }
     ServiceUserInfo info = new ServiceUserInfo(response);
     AccountLoader al = accountLoader.create(true);
     info.createdBy = al.get(creatorId);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/RegisterServiceUser.java b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/RegisterServiceUser.java
index c1ebb9a..6bca1ff 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/serviceuser/RegisterServiceUser.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/serviceuser/RegisterServiceUser.java
@@ -40,6 +40,7 @@
 import com.google.gerrit.server.account.AccountLoader;
 import com.google.gerrit.server.account.AccountResolver;
 import com.google.gerrit.server.account.AccountResolver.UnresolvableAccountException;
+import com.google.gerrit.server.config.AllProjectsName;
 import com.google.gerrit.server.config.ConfigResource;
 import com.google.gerrit.server.git.meta.MetaDataUpdate;
 import com.google.gerrit.server.group.GroupResolver;
@@ -83,6 +84,7 @@
   private final AccountLoader.Factory accountLoader;
   private final PermissionBackend permissionBackend;
   private final BlockedNameFilter blockedNameFilter;
+  private final ProjectCache projectCache;
 
   @Inject
   RegisterServiceUser(
@@ -93,6 +95,7 @@
       @GerritPersonIdent PersonIdent gerritIdent,
       MetaDataUpdate.User metaDataUpdateFactory,
       ProjectCache projectCache,
+      AllProjectsName allProjects,
       AccountLoader.Factory accountLoader,
       PermissionBackend permissionBackend,
       BlockedNameFilter blockedNameFilter) {
@@ -100,8 +103,9 @@
     this.groupResolver = groupResolver;
     this.userProvider = userProvider;
     this.metaDataUpdateFactory = metaDataUpdateFactory;
+    this.projectCache = projectCache;
     this.storage = projectCache.getAllProjects().getConfig(pluginName + ".db");
-    this.allProjects = projectCache.getAllProjects().getProject().getNameKey();
+    this.allProjects = allProjects;
     this.rfc2822DateFormatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
     this.rfc2822DateFormatter.setCalendar(
         Calendar.getInstance(gerritIdent.getTimeZone(), Locale.US));
@@ -164,19 +168,22 @@
       }
     }
 
-    db.setInt(USER, input.username, KEY_CREATOR_ID, creatorId.get());
-    if (creator != null) {
-      db.setString(USER, input.username, KEY_CREATED_BY, creator);
-    }
-    if (owner != null) {
-      db.setString(USER, input.username, KEY_OWNER, owner);
-    }
-    db.setString(USER, input.username, KEY_CREATED_AT, creationDate);
+    try {
+      db.setInt(USER, input.username, KEY_CREATOR_ID, creatorId.get());
+      if (creator != null) {
+        db.setString(USER, input.username, KEY_CREATED_BY, creator);
+      }
+      if (owner != null) {
+        db.setString(USER, input.username, KEY_OWNER, owner);
+      }
+      db.setString(USER, input.username, KEY_CREATED_AT, creationDate);
 
-    MetaDataUpdate md = metaDataUpdateFactory.create(allProjects);
-    md.setMessage("Create service user '" + input.username + "'\n");
-    storage.commit(md);
-
+      MetaDataUpdate md = metaDataUpdateFactory.create(allProjects);
+      md.setMessage("Create service user '" + input.username + "'\n");
+      storage.commit(md);
+    } finally {
+      projectCache.evict(allProjects);
+    }
     ServiceUserInfo info = new ServiceUserInfo(new AccountInfo(user.getAccountId().get()));
     AccountLoader al = accountLoader.create(true);
     info.createdBy = al.get(creatorId);