package cn.reghao.tnb.user.app.hystrix.observable;

import cn.reghao.tnb.user.app.service.UserServiceHystrix;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixObservableCommand;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import rx.Observable;
import rx.Subscriber;

/**
 * 使用HystrixObservableCommand时，默认会使用信号量隔离
 * 但是，即使这里强制使用了线程隔离，但是线程池不能控制了。
 * {@link Setter}里，没把控制线程池的方法提供出来
 *
 * @author reghao
 * @date 2025-07-23 17:53:30
 */
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class HaloThreadIsolationCommand extends HystrixObservableCommand<String> {
    private final UserServiceHystrix userServiceHystrix;

    public HaloThreadIsolationCommand(UserServiceHystrix userServiceHystrix) {
        super(setter());
        this.userServiceHystrix = userServiceHystrix;
    }

    private static Setter setter() {
        // 服务分组
        HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("halo");

        // 服务标识
        HystrixCommandKey commandKey = HystrixCommandKey.Factory.asKey("halo");

        // 命令属性配置Hystrix 开启超时
        HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter()
                // 采用线程池方式实现服务隔离
                .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
                // 禁止
                .withExecutionTimeoutEnabled(false);

        return Setter.withGroupKey(groupKey).andCommandKey(commandKey)
                .andCommandPropertiesDefaults(commandProperties);
    }

    @Override
    protected Observable<String> construct() {
        return Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> observer) {
                try {
                    if (!observer.isUnsubscribed()) {
                        // a real example would do work like a network call here
                        String s = userServiceHystrix.getResult();
                        observer.onNext(s);
                        observer.onCompleted();
                    }
                } catch (Exception e) {
                    observer.onError(e);
                }
            }
        });
    }
}
