提交 be15d8ce 编写于 作者: J Jason Song

Manually close the entity manager for async requests.

上级 f17e7ea8
package com.ctrip.apollo.biz.utils;
import org.springframework.orm.jpa.EntityManagerFactoryAccessor;
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
import org.springframework.orm.jpa.EntityManagerHolder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Component
public class EntityManagerUtil extends EntityManagerFactoryAccessor {
/**
* close the entity manager.
* Use it with caution! This is only intended for use with async request, which Spring won't
* close the entity manager until the async request is finished.
*/
public void closeEntityManager() {
EntityManagerHolder emHolder = (EntityManagerHolder)
TransactionSynchronizationManager.getResource(getEntityManagerFactory());
logger.debug("Closing JPA EntityManager in EntityManagerUtil");
EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager());
}
}
......@@ -12,6 +12,7 @@ import com.ctrip.apollo.biz.entity.AppNamespace;
import com.ctrip.apollo.biz.message.MessageListener;
import com.ctrip.apollo.biz.message.Topics;
import com.ctrip.apollo.biz.service.AppNamespaceService;
import com.ctrip.apollo.biz.utils.EntityManagerUtil;
import com.ctrip.apollo.core.ConfigConsts;
import com.ctrip.apollo.core.dto.ApolloConfigNotification;
import com.dianping.cat.Cat;
......@@ -49,6 +50,9 @@ public class NotificationController implements MessageListener {
@Autowired
private AppNamespaceService appNamespaceService;
@Autowired
private EntityManagerUtil entityManagerUtil;
@RequestMapping(method = RequestMethod.GET)
public DeferredResult<ResponseEntity<ApolloConfigNotification>> pollNotification(
@RequestParam(value = "appId") String appId,
......@@ -94,6 +98,13 @@ public class NotificationController implements MessageListener {
String dataCenter) {
List<String> publicWatchedKeys = Lists.newArrayList();
AppNamespace appNamespace = appNamespaceService.findByNamespaceName(namespace);
/**
* Manually close the entity manager.
* Since for async request, Spring won't do so until the request is finished,
* which is unacceptable since we are doing long polling - means the db connection would be hold
* for a very long time
*/
entityManagerUtil.closeEntityManager();
//check whether the namespace's appId equals to current one
if (Objects.isNull(appNamespace) || Objects.equals(applicationId, appNamespace.getAppId())) {
......
......@@ -7,6 +7,7 @@ import com.google.common.collect.Multimap;
import com.ctrip.apollo.biz.entity.AppNamespace;
import com.ctrip.apollo.biz.message.Topics;
import com.ctrip.apollo.biz.service.AppNamespaceService;
import com.ctrip.apollo.biz.utils.EntityManagerUtil;
import com.ctrip.apollo.core.ConfigConsts;
import com.ctrip.apollo.core.dto.ApolloConfigNotification;
......@@ -15,6 +16,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.util.ReflectionTestUtils;
......@@ -39,6 +41,8 @@ public class NotificationControllerTest {
private String someDataCenter;
@Mock
private AppNamespaceService appNamespaceService;
@Mock
private EntityManagerUtil entityManagerUtil;
private Multimap<String, DeferredResult<ResponseEntity<ApolloConfigNotification>>>
deferredResults;
......@@ -46,6 +50,7 @@ public class NotificationControllerTest {
public void setUp() throws Exception {
controller = new NotificationController();
ReflectionTestUtils.setField(controller, "appNamespaceService", appNamespaceService);
ReflectionTestUtils.setField(controller, "entityManagerUtil", entityManagerUtil);
someAppId = "someAppId";
someCluster = "someCluster";
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册