enable client side caching for plot requests
Doesn't work perfectly yet, because the height/width sometimes changes by one or two pixels.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package org.lucares.pdbui;
|
package org.lucares.pdbui;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.text.Collator;
|
import java.text.Collator;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -36,7 +37,9 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.http.CacheControl;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.util.StreamUtils;
|
import org.springframework.util.StreamUtils;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@@ -49,9 +52,13 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonParseException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
public class PdbController implements HardcodedValues {
|
public class PdbController implements HardcodedValues, PropertyKeys {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(PdbController.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(PdbController.class);
|
||||||
|
|
||||||
@@ -60,9 +67,12 @@ public class PdbController implements HardcodedValues {
|
|||||||
|
|
||||||
private final ReentrantLock plotterLock = new ReentrantLock();
|
private final ReentrantLock plotterLock = new ReentrantLock();
|
||||||
|
|
||||||
@Value("${mode.production:true}")
|
@Value("${" + PRODUCTION_MODE + ":true}")
|
||||||
private boolean modeProduction;
|
private boolean modeProduction;
|
||||||
|
|
||||||
|
@Value("${" + CACHE_IMAGES_DURATION_SECONDS + ":" + CACHE_IMAGES_DURATION_SECONDS_DEFAULT + "}")
|
||||||
|
private int cacheDurationInSeconds;
|
||||||
|
|
||||||
public PdbController(final PerformanceDb db, final Plotter plotter) {
|
public PdbController(final PerformanceDb db, final Plotter plotter) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.plotter = plotter;
|
this.plotter = plotter;
|
||||||
@@ -79,13 +89,29 @@ public class PdbController implements HardcodedValues {
|
|||||||
return new ModelAndView(view, model);
|
return new ModelAndView(view, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequestMapping(path = "/plots", //
|
||||||
|
method = RequestMethod.GET, //
|
||||||
|
consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, //
|
||||||
|
produces = MediaType.APPLICATION_JSON_UTF8_VALUE //
|
||||||
|
)
|
||||||
|
@ResponseBody
|
||||||
|
ResponseEntity<PlotResponse> createPlotGet(@RequestParam(name = "request") final String request)
|
||||||
|
throws InternalPlottingException, InterruptedException, JsonParseException, JsonMappingException,
|
||||||
|
IOException {
|
||||||
|
|
||||||
|
final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
final PlotRequest plotRequest = objectMapper.readValue(request, PlotRequest.class);
|
||||||
|
|
||||||
|
return createPlot(plotRequest);
|
||||||
|
}
|
||||||
|
|
||||||
@RequestMapping(path = "/plots", //
|
@RequestMapping(path = "/plots", //
|
||||||
method = RequestMethod.POST, //
|
method = RequestMethod.POST, //
|
||||||
consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, //
|
consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, //
|
||||||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE //
|
produces = MediaType.APPLICATION_JSON_UTF8_VALUE //
|
||||||
)
|
)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
PlotResponse createPlot(@RequestBody final PlotRequest request)
|
ResponseEntity<PlotResponse> createPlot(@RequestBody final PlotRequest request)
|
||||||
throws InternalPlottingException, InterruptedException {
|
throws InternalPlottingException, InterruptedException {
|
||||||
|
|
||||||
final PlotSettings plotSettings = PlotSettingsTransformer.toSettings(request);
|
final PlotSettings plotSettings = PlotSettingsTransformer.toSettings(request);
|
||||||
@@ -107,7 +133,11 @@ public class PdbController implements HardcodedValues {
|
|||||||
: imageUrl;
|
: imageUrl;
|
||||||
|
|
||||||
final PlotResponseStats stats = PlotResponseStats.fromDataSeries(result.getDataSeries());
|
final PlotResponseStats stats = PlotResponseStats.fromDataSeries(result.getDataSeries());
|
||||||
return new PlotResponse(stats, imageUrl, thumbnailUrl);
|
final PlotResponse plotResponse = new PlotResponse(stats, imageUrl, thumbnailUrl);
|
||||||
|
|
||||||
|
final CacheControl cacheControl = CacheControl.maxAge(cacheDurationInSeconds, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
return ResponseEntity.ok().cacheControl(cacheControl).body(plotResponse);
|
||||||
} catch (final NoDataPointsException e) {
|
} catch (final NoDataPointsException e) {
|
||||||
throw new NotFoundException(e);
|
throw new NotFoundException(e);
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -11,4 +11,20 @@ public interface PropertyKeys {
|
|||||||
* Path for temporary files
|
* Path for temporary files
|
||||||
*/
|
*/
|
||||||
String TMP_DIR = "path.tmp";
|
String TMP_DIR = "path.tmp";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of seconds generated images shall be cached.
|
||||||
|
*/
|
||||||
|
String CACHE_IMAGES_DURATION_SECONDS = "cache.images.duration.seconds";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default value for {@link PropertyKeys#CACHE_IMAGES_DURATION_SECONDS}
|
||||||
|
*/
|
||||||
|
String CACHE_IMAGES_DURATION_SECONDS_DEFAULT = "3600";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether or not this instance is running in production. This
|
||||||
|
* property is used to switch Vue.js into production or development mode.
|
||||||
|
*/
|
||||||
|
String PRODUCTION_MODE = "mode.production";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,25 @@
|
|||||||
package org.lucares.pdbui;
|
package org.lucares.pdbui;
|
||||||
|
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.CacheControl;
|
||||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class WebConfiguration extends WebMvcConfigurerAdapter implements HardcodedValues, PropertyKeys {
|
public class WebConfiguration implements WebMvcConfigurer, HardcodedValues, PropertyKeys {
|
||||||
|
|
||||||
private final String outputDir;
|
private final String outputDir;
|
||||||
|
private final int cacheDurationInSeconds;
|
||||||
|
|
||||||
public WebConfiguration(@Value("${" + PATH_GENERATED_IMAGES + "}") final String outputDir) {
|
public WebConfiguration(@Value("${" + PATH_GENERATED_IMAGES + "}") final String outputDir,
|
||||||
|
@Value("${" + CACHE_IMAGES_DURATION_SECONDS + ":" + CACHE_IMAGES_DURATION_SECONDS_DEFAULT
|
||||||
|
+ "}") final int cacheDurationInSeconds) {
|
||||||
this.outputDir = outputDir;
|
this.outputDir = outputDir;
|
||||||
|
this.cacheDurationInSeconds = cacheDurationInSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -22,6 +28,7 @@ public class WebConfiguration extends WebMvcConfigurerAdapter implements Hardcod
|
|||||||
final String pathPattern = "/" + WEB_IMAGE_OUTPUT_PATH + "/**";
|
final String pathPattern = "/" + WEB_IMAGE_OUTPUT_PATH + "/**";
|
||||||
final String resourceLocation = "file:" + Paths.get(outputDir).toAbsolutePath() + "/";
|
final String resourceLocation = "file:" + Paths.get(outputDir).toAbsolutePath() + "/";
|
||||||
|
|
||||||
registry.addResourceHandler(pathPattern).addResourceLocations(resourceLocation);
|
final CacheControl cacheControl = CacheControl.maxAge(cacheDurationInSeconds, TimeUnit.SECONDS);
|
||||||
|
registry.addResourceHandler(pathPattern).addResourceLocations(resourceLocation).setCacheControl(cacheControl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,4 +4,6 @@ db.base=${base.dir}/db
|
|||||||
path.tmp=${base.dir}/tmp
|
path.tmp=${base.dir}/tmp
|
||||||
path.output=${base.dir}/out
|
path.output=${base.dir}/out
|
||||||
|
|
||||||
|
cache.images.duration.seconds=3600
|
||||||
|
|
||||||
logging.config=classpath:log4j2.xml
|
logging.config=classpath:log4j2.xml
|
||||||
|
|||||||
@@ -908,7 +908,10 @@ function sendPlotRequest(query){
|
|||||||
};
|
};
|
||||||
|
|
||||||
data.searchBar.imagelink = '';
|
data.searchBar.imagelink = '';
|
||||||
postJson("plots", request, success, error);
|
const requestParam = {
|
||||||
|
'request': JSON.stringify(request)
|
||||||
|
};
|
||||||
|
getJson("plots", requestParam, success, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateImageLink(query) {
|
function updateImageLink(query) {
|
||||||
@@ -1002,7 +1005,10 @@ function createDashboardItem(originalQuery, field, imageHeight, imageWidth)
|
|||||||
data.dashboard.progress.value++;
|
data.dashboard.progress.value++;
|
||||||
createDashboardItem(originalQuery, field, imageHeight, imageWidth);
|
createDashboardItem(originalQuery, field, imageHeight, imageWidth);
|
||||||
};
|
};
|
||||||
postJson("plots", request, success, error);
|
var requestParam = {
|
||||||
|
request: JSON.stringify(request)
|
||||||
|
};
|
||||||
|
getJson("plots", requestParam, success, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1045,7 +1051,8 @@ function getJson(url, requestData, successCallback, errorCallback) {
|
|||||||
type: "GET",
|
type: "GET",
|
||||||
url: url,
|
url: url,
|
||||||
data: requestData,
|
data: requestData,
|
||||||
contentType: 'application/json'
|
contentType: 'application/json',
|
||||||
|
cache:true
|
||||||
})
|
})
|
||||||
.done(successCallback)
|
.done(successCallback)
|
||||||
.fail(errorCallback);
|
.fail(errorCallback);
|
||||||
|
|||||||
Reference in New Issue
Block a user