¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.config; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.boot.error.ErrorType; |
| | | import org.springblade.core.boot.error.ErrorUtil; |
| | | import org.springblade.core.context.BladeContext; |
| | | import org.springblade.core.context.BladeRunnableWrapper; |
| | | import org.springblade.core.launch.props.BladeProperties; |
| | | import org.springblade.core.log.constant.EventConstant; |
| | | import org.springblade.core.log.event.ErrorLogEvent; |
| | | import org.springblade.core.log.model.LogError; |
| | | import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; |
| | | import org.springframework.boot.task.TaskExecutorCustomizer; |
| | | import org.springframework.boot.task.TaskSchedulerCustomizer; |
| | | import org.springframework.context.ApplicationEventPublisher; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.lang.NonNull; |
| | | import org.springframework.scheduling.annotation.AsyncConfigurerSupport; |
| | | import org.springframework.scheduling.annotation.EnableAsync; |
| | | import org.springframework.scheduling.annotation.EnableScheduling; |
| | | import org.springframework.util.ErrorHandler; |
| | | |
| | | import java.lang.reflect.Method; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.concurrent.ThreadPoolExecutor; |
| | | |
| | | /** |
| | | * 弿¥å¤ç |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Slf4j |
| | | @Configuration |
| | | @EnableAsync |
| | | @EnableScheduling |
| | | @AllArgsConstructor |
| | | public class BladeExecutorConfiguration extends AsyncConfigurerSupport { |
| | | |
| | | private final BladeContext bladeContext; |
| | | private final BladeProperties bladeProperties; |
| | | private final ApplicationEventPublisher publisher; |
| | | |
| | | @Bean |
| | | public TaskExecutorCustomizer taskExecutorCustomizer() { |
| | | return taskExecutor -> { |
| | | taskExecutor.setThreadNamePrefix("async-task-"); |
| | | taskExecutor.setTaskDecorator(BladeRunnableWrapper::new); |
| | | taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); |
| | | }; |
| | | } |
| | | |
| | | @Bean |
| | | public TaskSchedulerCustomizer taskSchedulerCustomizer() { |
| | | return taskExecutor -> { |
| | | taskExecutor.setThreadNamePrefix("async-scheduler"); |
| | | taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); |
| | | taskExecutor.setErrorHandler(new BladeErrorHandler(bladeContext, bladeProperties, publisher)); |
| | | }; |
| | | } |
| | | |
| | | @Override |
| | | public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { |
| | | return new BladeAsyncUncaughtExceptionHandler(bladeContext, bladeProperties, publisher); |
| | | } |
| | | |
| | | @RequiredArgsConstructor |
| | | private static class BladeAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler { |
| | | private final BladeContext bladeContext; |
| | | private final BladeProperties bladeProperties; |
| | | private final ApplicationEventPublisher eventPublisher; |
| | | |
| | | @Override |
| | | public void handleUncaughtException(@NonNull Throwable error, @NonNull Method method, @NonNull Object... params) { |
| | | log.error("Unexpected exception occurred invoking async method: {}", method, error); |
| | | LogError logError = new LogError(); |
| | | // æå¡ä¿¡æ¯ãç¯å¢ãå¼å¸¸ç±»å |
| | | logError.setParams(ErrorType.ASYNC.getType()); |
| | | logError.setEnv(bladeProperties.getEnv()); |
| | | logError.setServiceId(bladeProperties.getName()); |
| | | logError.setRequestUri(bladeContext.getRequestId()); |
| | | // å æ ä¿¡æ¯ |
| | | ErrorUtil.initErrorInfo(error, logError); |
| | | Map<String, Object> event = new HashMap<>(16); |
| | | event.put(EventConstant.EVENT_LOG, logError); |
| | | eventPublisher.publishEvent(new ErrorLogEvent(event)); |
| | | } |
| | | } |
| | | |
| | | @RequiredArgsConstructor |
| | | private static class BladeErrorHandler implements ErrorHandler { |
| | | private final BladeContext bladeContext; |
| | | private final BladeProperties bladeProperties; |
| | | private final ApplicationEventPublisher eventPublisher; |
| | | |
| | | @Override |
| | | public void handleError(@NonNull Throwable error) { |
| | | log.error("Unexpected scheduler exception", error); |
| | | LogError logError = new LogError(); |
| | | // æå¡ä¿¡æ¯ãç¯å¢ãå¼å¸¸ç±»å |
| | | logError.setParams(ErrorType.SCHEDULER.getType()); |
| | | logError.setServiceId(bladeProperties.getName()); |
| | | logError.setEnv(bladeProperties.getEnv()); |
| | | logError.setRequestUri(bladeContext.getRequestId()); |
| | | // å æ ä¿¡æ¯ |
| | | ErrorUtil.initErrorInfo(error, logError); |
| | | Map<String, Object> event = new HashMap<>(16); |
| | | event.put(EventConstant.EVENT_LOG, logError); |
| | | eventPublisher.publishEvent(new ErrorLogEvent(event)); |
| | | } |
| | | } |
| | | |
| | | } |