All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.aeon.experiment.specification.app.HES Maven / Gradle / Ivy

The newest version!
package io.aeon.experiment.specification.app;

import io.aeon.runtime.CRunning;
import io.horizon.atom.app.KApp;
import io.horizon.eon.VValue;
import io.horizon.spi.cloud.HET;
import io.horizon.uca.log.Annal;
import io.macrocosm.atom.HOI;
import io.vertx.core.Future;
import io.vertx.core.json.JsonObject;
import io.vertx.up.eon.KName;
import io.vertx.up.unity.Ux;
import io.vertx.up.util.Ut;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * 「环境工厂」
 * 静态环境工厂专用方法,替换原始的 Highway 部分的连接,并且从接口中剥离出来,可直接调用
 *
 * @author Lang
 */
public final class HES {
    private static final String MSG_HOI = "[HES] Environment Tenant initialized: {0} with parameters: {1}, mode = {2}";
    private static final Annal LOGGER = Annal.get(HES.class);

    private HES() {
    }


    // ------------------ Owner Environment --------------------
    /*
     * 拥有者环境配置,内置于 Envelop 在绑定环境时执行,Hoi和KApp的支持维度如
     *               Hoi             KApp
     * name           x               o
     * code           x               o
     * appId          x               o
     * appKey         x               o
     * sigma          o               o ( 反向引用 )
     * tenant         o               x
     *
     * 输入数据只有三个:tenant / appId ( appKey ) / sigma,其中 appKey 不用于租户鉴别
     * 当前容器环境中有两个固定维度:
     * 1. tenant / language 是已经固定好的,都只有一个
     * 2. 上层维度:tenant
     *    下层维度:appId
     * 3. 最终计算看 sigma 是表示上层还是下层
     */
    public static Future configure() {
        return Ux.channel(HET.class,
            () -> Boolean.FALSE,
            // 1. 初始化所有应用(CRunning.CC_APP就绪)
            het -> het.initialize().compose(initialized -> {
                /*
                 * 先计算当前应用类型,基础维度是 sigma(统一标识符),根据 sigma 执行缓存创建
                 * 1. 「单机环境」下 sigma 只有一个,Hoi也只有一个(tenant可null)
                 * 2. 「多租户环境」 sigma = tenant 维度,Hoi也只有一个(tenant不为空,且children为空)
                 * 3. 「多层租户环境」无等价维度,Hoi会存在多个,且某些Hoi会出现子租户映射表
                 *
                 * 任何场景下都执行的是 sigma 的缓存处理,且可直接根据 sigma 的值执行 Hoi 提取
                 */
                CRunning.CC_APP.store().values().forEach(app -> {
                    final JsonObject inputJ = app.dataJ();
                    /*
                     * CC_APP / CC_HOI 不同点
                     * 1)(应用级)CC_APP的键值是跨越级的,有多个,保证每个都可以提取数据
                     * 2)(租户级)CC_HOI则不然,它包含了 sigma(开启租户时的租户标识)
                     */
                    final String sigma = Ut.valueString(inputJ, KName.SIGMA);
                    CRunning.CC_OI.pick(() -> {
                        final HOI hoi = het.configure(inputJ);
                        LOGGER.info(MSG_HOI, sigma, inputJ.encode(), hoi.mode());
                        return hoi;
                    }, sigma);
                });
                return Ux.futureT();
            })
        );
    }

    public static HOI caller(final String sigma) {
        return CRunning.CC_OI.store(sigma);
    }

    public static HOI callee(final String sigma, final String tenant) {
        if (Objects.isNull(tenant) || Objects.isNull(sigma)) {
            return null;
        }
        // 提取租户,此时 sigma 必定和 tenant 同维度,而
        // 传入的 tenant 可能是「空间租户」
        final HOI hoi = caller(sigma);
        if (Objects.isNull(hoi)) {
            return null;
        }
        return hoi.child(tenant);
    }

    // ------------------ 提取和初始化处理上下文应用 --------------------
    /*
     * HAtom 建模上下文专用
     * 1. 内置调用 H3H 核心数据结构
     * 2. 按 name 提取(两种模式),     connect
     */
    public static KApp connect(final String name) {
        /*
         * 无填充模式,key = value,此时 key 就是应用程序名称
         */
        return CRunning.CC_APP.pick(() -> KApp.instance(name), name);
    }

    /*
     * 反向调用,此处有可能会引起不必要的死循环
     * HET / HES 在调用过程中有可能会出现相互之间循环调用,但
     * 1)由于HES是静态调用,HET是实例化过后调用,所以此处不会轻易出现死循环
     * 2)HET调用HES时实际规划成反向调用,其目的就是让系统不会出现死循环,否则方法名容易引起误解
     */
    public static KApp connect(final String sigma, final String key) {
        /*
         * 1. 按sigma查找
         * 2. 按key查找
         * 3. 都找不到时读取当前
         */
        KApp app = null;
        if (Ut.isNotNil(sigma)) {
            // 按sigma查找
            app = CRunning.CC_APP.store(sigma);
        }
        if (Ut.isNotNil(key) && Objects.isNull(app)) {
            // 按key查找
            app = CRunning.CC_APP.store(key);
        }
        return Objects.isNull(app) ? connect() : app;
    }

    // ------------------ 直接连接应用 --------------------
    /*
     * 连接当前应用,工作流程
     * 1. 先调用 HET 的 initialize 方法(如果CC_APP为空则执行,如果不为空不执行初始化)
     * 2. 填充最终上下文环境提取当前应用,调用 values(),只有一个则返回
     */
    public static KApp connect() {
        final Set appSet = new HashSet<>(CRunning.CC_APP.store().values());
        KApp env = null;
        if (VValue.ONE == appSet.size()) {
            env = appSet.iterator().next();
        }
        return env;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy