package cn.quantgroup.xyqb.config.event;

import cn.quantgroup.tech.brave.service.ITechExecutorServiceBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.support.TaskUtils;

import javax.annotation.Resource;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
@Configuration
public class EventConfig {

    @Resource
    private ITechExecutorServiceBuilder techExecutorServiceBuilder;

    @Bean
    public ApplicationEventMulticaster applicationEventMulticaster(Executor taskExecutor) {
        SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster();
        simpleApplicationEventMulticaster.setTaskExecutor(taskExecutor);
        simpleApplicationEventMulticaster.setErrorHandler(TaskUtils.LOG_AND_PROPAGATE_ERROR_HANDLER);
        return simpleApplicationEventMulticaster;
    }


    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor poolTaskExecutor = new ThreadPoolTaskExecutor();
        poolTaskExecutor.setCorePoolSize(10);
        poolTaskExecutor.setMaxPoolSize(50);
        poolTaskExecutor.setQueueCapacity(100);
        poolTaskExecutor.setThreadNamePrefix("Spring-UserLogin-Event-");
        poolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        poolTaskExecutor.setRejectedExecutionHandler(new RejectedHandler());
        poolTaskExecutor.initialize();
        return techExecutorServiceBuilder.buildExecutorService(poolTaskExecutor.getThreadPoolExecutor());
    }

    public static class RejectedHandler implements RejectedExecutionHandler {

        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            log.error("rejected : {}", r);
        }
    }

}
