package com.utic.center.utic.ptis.server.config;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
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;

import javax.annotation.PostConstruct;
import java.util.concurrent.Executor;

@Slf4j
@Getter
@Setter
@EnableAsync
@Configuration
@ConfigurationProperties(prefix = "application.thread-pool")
public class ThreadPoolInitializer extends AsyncConfigurerSupport {

    private int schedule = 0;

    @PostConstruct
    private void init() {
        int MAX_CORE = Math.max(8, Runtime.getRuntime().availableProcessors());
        if (this.schedule <= 0) {
            this.schedule = MAX_CORE;
        }
        log.info("{}", this);
    }

    public ThreadPoolTaskExecutor getDefaultExecutor(int poolSize) {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(poolSize);              // 인스턴스 되면서 기본적으로 띄울 스레드 개수.
        // 아무작업이 없어도 corePoolSize 만큼 스레드가 생성
        threadPoolTaskExecutor.setMaxPoolSize(poolSize*2);   // 풀 최대개수, Queue Capacity 까지 꽉차는 경우 maxPoolSize 만큼 넓혀감
        threadPoolTaskExecutor.setQueueCapacity(2000);          // 스레드 대기큐, Queue Capacity 가 꽉차면 스레드가 추가로 생성됨. Async 처리시 Queue Size
        // (설정하지 않으면 Integer.MAX 이기 때문에 성능에 문제가 발생함)
        return threadPoolTaskExecutor;
    }

    @Bean(name="scheduleExecutor")
    public Executor getScheduleExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = getDefaultExecutor(this.schedule);
        threadPoolTaskExecutor.setThreadNamePrefix("schedule-pool-");
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }

}
