Merge "Start caching top-menus and version"
diff --git a/Documentation/config-plugins.txt b/Documentation/config-plugins.txt
index cda02fb..3a80910 100644
--- a/Documentation/config-plugins.txt
+++ b/Documentation/config-plugins.txt
@@ -9,6 +9,10 @@
 link:config-gerrit.html#plugins.checkFrequency[a few minutes] until
 the server picks up new and updated plugins.
 
+Due to caching, you might need to flush your browser cache after
+installing a plugin. Users will usually see the result within
+several minutes.
+
 Plugins can also be installed via
 link:rest-api-plugins.html#install-plugin[REST] and
 link:cmd-plugin-install.html[SSH].
diff --git a/java/com/google/gerrit/server/config/ConfigResource.java b/java/com/google/gerrit/server/config/ConfigResource.java
index ec0e0c2..4275dc4 100644
--- a/java/com/google/gerrit/server/config/ConfigResource.java
+++ b/java/com/google/gerrit/server/config/ConfigResource.java
@@ -14,11 +14,22 @@
 
 package com.google.gerrit.server.config;
 
+import com.google.gerrit.extensions.restapi.CacheControl;
 import com.google.gerrit.extensions.restapi.RestResource;
 import com.google.gerrit.extensions.restapi.RestView;
 import com.google.inject.TypeLiteral;
+import java.util.concurrent.TimeUnit;
 
 public class ConfigResource implements RestResource {
   public static final TypeLiteral<RestView<ConfigResource>> CONFIG_KIND =
       new TypeLiteral<RestView<ConfigResource>>() {};
+
+  /**
+   * Default cache control that gets set on the 'Cache-Control' header for responses on this
+   * resource that are cachable.
+   *
+   * <p>Not all resources are cacheable and in fact the vast majority might not be. Caching is a
+   * trade-off between the freshness of data and the number of QPS that the web UI sends.
+   */
+  public static CacheControl DEFAULT_CACHE_CONTROL = CacheControl.PRIVATE(300, TimeUnit.SECONDS);
 }
diff --git a/java/com/google/gerrit/server/restapi/config/GetVersion.java b/java/com/google/gerrit/server/restapi/config/GetVersion.java
index 8135719..ee206d6 100644
--- a/java/com/google/gerrit/server/restapi/config/GetVersion.java
+++ b/java/com/google/gerrit/server/restapi/config/GetVersion.java
@@ -15,19 +15,22 @@
 package com.google.gerrit.server.restapi.config;
 
 import com.google.gerrit.common.Version;
+import com.google.gerrit.extensions.restapi.CacheControl;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
+import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.gerrit.server.config.ConfigResource;
 import com.google.inject.Singleton;
+import java.util.concurrent.TimeUnit;
 
 @Singleton
 public class GetVersion implements RestReadView<ConfigResource> {
   @Override
-  public String apply(ConfigResource resource) throws ResourceNotFoundException {
+  public Response<String> apply(ConfigResource resource) throws ResourceNotFoundException {
     String version = Version.getVersion();
     if (version == null) {
       throw new ResourceNotFoundException();
     }
-    return version;
+    return Response.ok(version).caching(CacheControl.PRIVATE(30, TimeUnit.SECONDS));
   }
 }
diff --git a/java/com/google/gerrit/server/restapi/config/ListTopMenus.java b/java/com/google/gerrit/server/restapi/config/ListTopMenus.java
index c296a7d..2feb580 100644
--- a/java/com/google/gerrit/server/restapi/config/ListTopMenus.java
+++ b/java/com/google/gerrit/server/restapi/config/ListTopMenus.java
@@ -14,8 +14,10 @@
 
 package com.google.gerrit.server.restapi.config;
 
+import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.gerrit.extensions.webui.TopMenu;
+import com.google.gerrit.extensions.webui.TopMenu.MenuEntry;
 import com.google.gerrit.server.config.ConfigResource;
 import com.google.gerrit.server.plugincontext.PluginSetContext;
 import com.google.inject.Inject;
@@ -33,9 +35,9 @@
   }
 
   @Override
-  public List<TopMenu.MenuEntry> apply(ConfigResource resource) {
+  public Response<List<MenuEntry>> apply(ConfigResource resource) {
     List<TopMenu.MenuEntry> entries = new ArrayList<>();
     extensions.runEach(extension -> entries.addAll(extension.getEntries()));
-    return entries;
+    return Response.ok(entries).caching(ConfigResource.DEFAULT_CACHE_CONTROL);
   }
 }