package com.bb.config;

import java.util.concurrent.Executor;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@EnableAsync
public class AsyncConfig extends AsyncConfigurerSupport {

	// 기본 실행 대기하는 Thread의 수
	private final int CORE_POOL_SIZE = 10;
	
	// 동시 동작하는 최대 Thread의 수
    private final int MAX_POOL_SIZE = 50;
    
    // MaxPoolSize 초과 요청에서 Thread 생성 요청 시, 해당 요청을 Queue에 저장하는데 이때 최대 수용 가능한 Queue의 수
    private final int QUEUE_CAPACITY = 500;		
    
    // maxPoolSize가 모두 사용되다가 idle(쓰레드 휴식상태)로 돌아갔을 때 종료하기까지 대기하는 걸리는 시간
    private final int KEEP_ALIVE_SECONDS = 60;
    
    // 생성되는 Thread 접두사 지정
    private final String CUSTOM_THREAD_NAME_PREFIX = "HSLOT-ASYNC-";
    
    // 시스템을 종료(shutdown)할 때 queue에 남아있는 작업을 모두 완료한 후 종료 하도록 처리
    private final boolean WAIT_FOR_TASKS_TO_COMPLETE_ON_SHOUTDOWN = true;
	
	@Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(CORE_POOL_SIZE);
        executor.setMaxPoolSize(MAX_POOL_SIZE);
        executor.setQueueCapacity(QUEUE_CAPACITY);
        executor.setKeepAliveSeconds(KEEP_ALIVE_SECONDS);
        executor.setThreadNamePrefix(CUSTOM_THREAD_NAME_PREFIX);
        executor.setWaitForTasksToCompleteOnShutdown(WAIT_FOR_TASKS_TO_COMPLETE_ON_SHOUTDOWN);
        executor.initialize();
        return executor;
    }
    
    // 포인트 처리 전용 Executor 추가
    @Bean(name = "pointTaskExecutor")
    public Executor pointTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("PointAsync-");
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.initialize();
        return executor;
    }
}