package com.qiuguo.iot.admin.http.api.filter;

import lombok.extern.slf4j.Slf4j;
import org.reactivestreams.Subscription;
import org.slf4j.MDC;
import org.springframework.context.annotation.Configuration;
import reactor.core.CoreSubscriber;
import reactor.core.publisher.Hooks;
import reactor.core.publisher.Operators;
import reactor.util.context.Context;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * <p>
 * </p>*日志上下文切换配置
 * @author wulin
 * @since 2023-08-07
 */
@Configuration
@Slf4j
public class LogMdcConfiguration {
    public static String PRINT_LOG_ID = "logid";
    @PostConstruct
    public void contextOperatorHook() {
        Hooks.onEachOperator(PRINT_LOG_ID, Operators.lift((r, c) ->{
            Context ctx = c.currentContext();
            if(ctx.hasKey(PRINT_LOG_ID)){
                MDC.put(PRINT_LOG_ID, ctx.get(PRINT_LOG_ID));
            }
            return new MdcContextSubscriber(c);
        }));
    }
    @PreDestroy
    public void cleanupHook() {
        Hooks.resetOnEachOperator(PRINT_LOG_ID);
    }

    class MdcContextSubscriber<T> implements CoreSubscriber<T> {
        private CoreSubscriber<T> coreSubscriber;
        public MdcContextSubscriber(CoreSubscriber<T> c){
            coreSubscriber = c;
        }

        @Override
        public void onComplete() {
            coreSubscriber.onComplete();
            MDC.remove(PRINT_LOG_ID);
        }

        @Override
        public void onError(Throwable throwable) {
            coreSubscriber.onError(throwable);
            MDC.remove(PRINT_LOG_ID);

        }

        @Override
        public void onSubscribe(Subscription subscription) {
            coreSubscriber.onSubscribe(subscription);
        }

        @Override
        public void onNext(T t) {

            coreSubscriber.onNext(t);
        }


        @Override
        public Context currentContext() {
            return coreSubscriber.currentContext();
        }
    }
}
