Commit 35346e80 authored by Piotr Gawron's avatar Piotr Gawron
Browse files

vacuum postgres every night

parent a2c02570
Pipeline #51085 failed with stage
in 11 minutes and 5 seconds
......@@ -3,6 +3,8 @@ minerva (16.0.6) stable; urgency=medium
reactions and elements are fetched in parallel (#1605)
* Bug fix (performance): showing data overlay is faster on projects with
multiple maps
* Bug fix (performance): postgres database is vacuumed every night at 2:15 to
improve performance (#1589)
* Bug fix: REST API did not respect mapId when listing overlay elements in a
project
* Bug fix: log4j2 updated to address security issue CVE-2021-44832
......
package lcsb.mapviewer.persist;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Observable;
......@@ -9,7 +11,9 @@ import org.apache.logging.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.PostgreSQL81Dialect;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.jdbc.Work;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......@@ -48,8 +52,8 @@ public class DbUtils extends Observable {
* <ol>
* <li>when autoflushing is set to false, then the data consistency could be
* broken (even in the same thread/transaction)</li>,
* <li>we have to automatically take care of the flushing, therefore there might
* be some problems with long transactions.</li>
* <li>we have to automatically take care of the flushing, therefore there
* might be some problems with long transactions.</li>
* </ol>
*/
private static Map<Long, Boolean> autoFlushForThread = new HashMap<>();
......@@ -64,7 +68,7 @@ public class DbUtils extends Observable {
* @param sessionFactory
*/
@Autowired
public DbUtils(SessionFactory sessionFactory) {
public DbUtils(final SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
......@@ -188,7 +192,7 @@ public class DbUtils extends Observable {
* the sessionFactory to set
* @see #sessionFactory
*/
public void setSessionFactory(SessionFactory sessionFactory) {
public void setSessionFactory(final SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
......@@ -196,8 +200,8 @@ public class DbUtils extends Observable {
* Returns info if the flush is automatically done or not in current
* {@link Thread}.
*
* @return <code>true</code> if flush is automatically done, <code>false</code>
* otherwise
* @return <code>true</code> if flush is automatically done,
* <code>false</code> otherwise
* @see #autoFlushForThread
*/
public boolean isAutoFlush() {
......@@ -223,7 +227,7 @@ public class DbUtils extends Observable {
* the new autoflush value
* @see #autoFlushForThread
*/
public void setAutoFlush(boolean autoFlush) {
public void setAutoFlush(final boolean autoFlush) {
Long id = Thread.currentThread().getId();
synchronized (autoFlushForThread) {
autoFlushForThread.put(id, autoFlush);
......@@ -234,7 +238,23 @@ public class DbUtils extends Observable {
return ((SessionFactoryImpl) sessionFactory).getDialect();
}
public void detach(Object entity) {
public void detach(final Object entity) {
getSessionForCurrentThread().evict(entity);
}
public void vaccuum() throws SQLException {
if (getDialect() instanceof PostgreSQL81Dialect) {
getSessionForCurrentThread().doWork(new Work() {
@Override
public void execute(final Connection connection) throws SQLException {
boolean autoCommit = connection.getAutoCommit();
connection.setAutoCommit(true);
connection.prepareStatement("VACUUM FULL").execute();
connection.setAutoCommit(autoCommit);
}
});
} else {
logger.warn("Vacuum is not supported for dialect: " + getDialect().getClass());
}
}
}
package lcsb.mapviewer.persist;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
......@@ -43,4 +45,8 @@ public class DbUtilsTest extends PersistTestFunctions {
dbUtils.setAutoFlush(autoflush);
}
@Test
public void testVacuumDontCrash() throws Exception {
dbUtils.vaccuum();
}
}
package lcsb.mapviewer.web.bean.utils;
import java.sql.SQLException;
import javax.transaction.Transactional;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import lcsb.mapviewer.persist.DbUtils;
@Component
public class AutoVacuumBean {
private final transient Logger logger = LogManager.getLogger();
private transient DbUtils dbUtils;
@Autowired
public AutoVacuumBean(
final DbUtils dbUtils) {
this.dbUtils = dbUtils;
}
@Transactional
@Scheduled(cron = "0 15 2 * * ?")
public void scheduleTaskUsingCronExpression() {
try {
logger.info("VACUUM started");
dbUtils.vaccuum();
} catch (SQLException e) {
logger.error("Problem with vacuum", e);
} finally {
logger.info("VACUUM finished");
}
}
}
......@@ -3,10 +3,19 @@ package lcsb.mapviewer.web.config;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import com.fasterxml.jackson.databind.ObjectMapper;
......@@ -15,6 +24,7 @@ import lcsb.mapviewer.api.SpringRestApiConfig;
@Configuration
@EnableWebMvc
@EnableScheduling
@Import(SpringRestApiConfig.class)
@ComponentScan(basePackages = { "lcsb.mapviewer.web" })
public class SpringWebConfig implements WebMvcConfigurer {
......@@ -22,7 +32,7 @@ public class SpringWebConfig implements WebMvcConfigurer {
private List<HandlerInterceptor> interceptors;
@Autowired
public SpringWebConfig(List<HandlerInterceptor> interceptors) {
public SpringWebConfig(final List<HandlerInterceptor> interceptors) {
this.interceptors = interceptors;
}
......@@ -35,24 +45,24 @@ public class SpringWebConfig implements WebMvcConfigurer {
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
public void addInterceptors(final InterceptorRegistry registry) {
interceptors.forEach(registry::addInterceptor);
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
@Override
public void addCorsMappings(CorsRegistry registry) {
public void addCorsMappings(final CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
public void addViewControllers(final ViewControllerRegistry registry) {
registry
.addViewController("/")
.setViewName("index");
......@@ -60,8 +70,8 @@ public class SpringWebConfig implements WebMvcConfigurer {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
ObjectMapper mapper = new ObjectMapper();
return mapper;
return mapper;
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment