You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
6.5 KiB
150 lines
6.5 KiB
package com.fr.plugin.pack.http; |
|
|
|
import com.finebi.activate.foundation.StableManager; |
|
import com.finebi.base.concurrent.DefaultThreadFactory; |
|
import com.finebi.common.api.vo.table.parameter.Parameters; |
|
import com.finebi.dashboard.api.bean.widget.WidgetBean; |
|
import com.finebi.dashboard.api.service.FineDashBoardService; |
|
import com.finebi.dashboard.api.service.FineWidgetExecutorService; |
|
import com.finebi.dashboard.api.structure.result.preview.BIPreViewResult; |
|
import com.finebi.dashboard.impl.helper.FineDashBoardUtils; |
|
import com.finebi.foundation.api.reponse.FineRespond; |
|
import com.finebi.foundation.api.service.FineService; |
|
import com.finebi.selector.api.DirectSourceEngineFactory; |
|
import com.finebi.utils.CollectionUtils; |
|
import com.finebi.utils.StringUtils; |
|
import com.finebi.web.action.v5.BaseAction; |
|
import com.fr.decision.authority.data.User; |
|
import com.fr.decision.fun.impl.BaseHttpHandler; |
|
import com.fr.general.IOUtils; |
|
import com.fr.invoke.Reflect; |
|
import com.fr.log.FineLoggerFactory; |
|
import com.fr.plugin.pack.bean.WidgetsBean; |
|
import com.fr.plugin.pack.conf.PackPluginConfig; |
|
import com.fr.plugin.pack.exception.ReportExceedException; |
|
import com.fr.plugin.pack.exception.WidgetExceedException; |
|
import com.fr.plugin.pack.source.PackDBSourceEngine; |
|
import com.fr.plugin.pack.traffic.PackTraffic; |
|
import com.fr.plugin.pack.traffic.PackTrafficFactory; |
|
import com.fr.third.fasterxml.jackson.databind.ObjectMapper; |
|
import com.fr.third.springframework.web.bind.annotation.RequestMethod; |
|
import com.fr.web.utils.WebUtils; |
|
|
|
import javax.servlet.http.HttpServletRequest; |
|
import javax.servlet.http.HttpServletResponse; |
|
import java.util.ArrayList; |
|
import java.util.HashMap; |
|
import java.util.List; |
|
import java.util.Map; |
|
import java.util.Set; |
|
import java.util.concurrent.ExecutorService; |
|
import java.util.concurrent.Executors; |
|
import java.util.concurrent.Future; |
|
import java.util.concurrent.TimeUnit; |
|
import java.util.concurrent.TimeoutException; |
|
import java.util.stream.Collectors; |
|
|
|
/** |
|
* @author Jonas |
|
* @version 5.1.3 |
|
* Created by Jonas on 2020-10-19 |
|
*/ |
|
public class PackHttpHandler extends BaseHttpHandler { |
|
private PackTraffic reportTraffic = PackTrafficFactory.getReportTraffic(); |
|
public static String PATH = "/widgets/data"; |
|
private ExecutorService executorService = Executors.newCachedThreadPool(new DefaultThreadFactory("pack-widget-execute")); |
|
|
|
{ |
|
DirectSourceEngineFactory.INSTANCE.register(new PackDBSourceEngine()); |
|
} |
|
|
|
@Override |
|
public RequestMethod getMethod() { |
|
return RequestMethod.POST; |
|
} |
|
|
|
@Override |
|
public String getPath() { |
|
return PATH; |
|
} |
|
|
|
@Override |
|
public boolean isPublic() { |
|
return false; |
|
} |
|
|
|
@Override |
|
public void handle(HttpServletRequest request, HttpServletResponse response) throws Exception { |
|
ObjectMapper mapper = new ObjectMapper(); |
|
String reportId = null; |
|
try { |
|
String body = IOUtils.inputStream2String(request.getInputStream()); |
|
WidgetsBean widgetsBean = mapper.readValue(body, WidgetsBean.class); |
|
|
|
Map<String, Object> result = new HashMap<>(); |
|
Set<String> reportIds = widgetsBean.getWidgets().values().stream().map(WidgetBean::getReportId).collect(Collectors.toSet()); |
|
if (CollectionUtils.isEmpty(reportIds)) { |
|
throw new UnsupportedOperationException(); |
|
} else { |
|
reportId = reportIds.iterator().next(); |
|
if (StringUtils.isEmpty(reportId)) { |
|
throw new UnsupportedOperationException("reportId must be not emtpy"); |
|
} |
|
} |
|
if (!reportTraffic.offer(reportId)) { |
|
throw new ReportExceedException(); |
|
} |
|
try { |
|
List<Future<?>> futures = new ArrayList<>(); |
|
for (Map.Entry<String, WidgetBean> entry : widgetsBean.getWidgets().entrySet()) { |
|
WidgetBean widgetBean = entry.getValue(); |
|
User user = FineDashBoardUtils.getUserFromReq(request, widgetBean.getReportId()); |
|
boolean mobile = FineDashBoardUtils.isMobile(request); |
|
Parameters parameterFromRequest = FineDashBoardUtils.getParameterFromRequest(request); |
|
String widgetId = entry.getKey(); |
|
Future<?> future = executorService.submit(() -> { |
|
try { |
|
BIPreViewResult widgetData = Reflect.on(FineDashBoardUtils.class) |
|
.call("getWidgetData", widgetBean, user, mobile, parameterFromRequest, |
|
getBean(FineDashBoardService.class), getBean(FineWidgetExecutorService.class)) |
|
.get(); |
|
result.put(widgetId, FineRespond.success(widgetData)); |
|
} catch (Exception e) { |
|
FineLoggerFactory.getLogger().debug(e.getMessage(), e); |
|
result.put(widgetId, handleException(e)); |
|
} |
|
}); |
|
futures.add(future); |
|
} |
|
for (Future<?> future : futures) { |
|
try { |
|
// 设置超时时间,不能一直在等着 |
|
future.get(PackPluginConfig.getInstance().getWidgetQueryTimeout(), TimeUnit.MILLISECONDS); |
|
} catch (TimeoutException e) { |
|
future.cancel(true); |
|
} |
|
} |
|
WebUtils.printAsString(response, mapper.writeValueAsString(FineRespond.success(result))); |
|
} finally { |
|
reportTraffic.release(reportId); |
|
} |
|
} catch (Exception e) { |
|
e.printStackTrace(); |
|
WebUtils.printAsString(response, mapper.writeValueAsString(FineRespond.fail("500", mapper.writeValueAsString(handleException(e))))); |
|
} |
|
} |
|
|
|
private static FineRespond handleException(Exception e) { |
|
if (e instanceof ReportExceedException) { |
|
return FineRespond.fail(((ReportExceedException) e).errorCode(), e.getMessage()); |
|
} |
|
if (e instanceof WidgetExceedException) { |
|
return FineRespond.fail(((WidgetExceedException) e).errorCode(), e.getMessage()); |
|
} |
|
return Reflect.on(BaseAction.class).call("getExceptionRespond", e).get(); |
|
} |
|
|
|
private static <T extends FineService> T getBean(Class<T> annotatedClass) { |
|
return StableManager.getContext().getServiceBean(annotatedClass); |
|
} |
|
}
|
|
|