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

com.icthh.xm.commons.scheduler.adapter.SchedulerChannelManager Maven / Gradle / Ivy

The newest version!
package com.icthh.xm.commons.scheduler.adapter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.icthh.xm.commons.config.client.api.RefreshableConfiguration;
import com.icthh.xm.commons.config.client.config.XmConfigProperties;
import com.icthh.xm.commons.config.client.repository.TenantListRepository;
import com.icthh.xm.commons.config.domain.TenantState;
import java.util.Objects;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;

import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

import static com.icthh.xm.commons.config.client.repository.TenantListRepository.TENANTS_LIST_CONFIG_KEY;
import static com.icthh.xm.commons.config.client.repository.TenantListRepository.isSuspended;

@Slf4j
public class SchedulerChannelManager implements RefreshableConfiguration {

    private static final String SCHEDULER_APP_DEFAULT = "scheduler";

    private final DynamicTopicConsumerConfiguration dynamicTopicConsumerConfiguration;
    private final ObjectMapper objectMapper;

    @Value("${spring.application.name}")
    String appName;

    @Value("${application.scheduler-config.scheduler-app-name:" + SCHEDULER_APP_DEFAULT + "}")
    private String schedulerAppName = SCHEDULER_APP_DEFAULT;

    private final Set includedTenants;

    private volatile Set tenantToStart;

    public SchedulerChannelManager(XmConfigProperties xmConfigProperties,
                                   DynamicTopicConsumerConfiguration dynamicTopicConsumerConfiguration) {
        this.includedTenants = xmConfigProperties.getIncludeTenantLowercase();
        this.dynamicTopicConsumerConfiguration = dynamicTopicConsumerConfiguration;
        this.objectMapper = new ObjectMapper();
    }

    @SneakyThrows
    boolean parseConfig(String key, String config) {

        log.info("Tenants list was updated, start to parse config");

        if (!TENANTS_LIST_CONFIG_KEY.equals(key)) {
            throw new IllegalArgumentException("Wrong config key to update " + key);
        }

        if (StringUtils.isEmpty(config)) {
            throw new IllegalArgumentException("Config file has empty content: " + key);
        }

        Set tenantKeys = TenantListRepository.parseTenantStates(config, objectMapper)
                                                          .getOrDefault(schedulerAppName, new HashSet<>());

        if (tenantKeys.isEmpty()) {
            log.warn("No one tenant configured to use scheduler. "
                     + "Add tenant state to ms-config/tenant-list.json to section $.scheduler");
        }
        if (!includedTenants.isEmpty()) {
            log.warn("Tenant list was overridden by property 'xm-config.include-tenants' to: {}", includedTenants);
        }

        var tenantToStart = tenantKeys.stream()
                                  .filter(TenantListRepository.isIncluded(includedTenants)
                                                              .and(isSuspended().negate()))
                                  .map(TenantState::getName)
                                  .collect(Collectors.toSet());

        if (Objects.equals(this.tenantToStart, tenantToStart)) {
            log.info("Tenants list was not changed old: {}, new: {}, skip update", this.tenantToStart, tenantToStart);
            return false;
        }

        this.tenantToStart = Set.copyOf(tenantToStart);
        log.info("scheduler will be turned on for tenants: {}", tenantToStart);
        return true;
    }

    @EventListener(ApplicationReadyEvent.class)
    public void startChannels() {
        if (tenantToStart == null) {
            throw new IllegalStateException("Scheduler channel manager was not initialized. Call onInit() first!");
        }
        log.info("Start channels for tenants: {}", tenantToStart);
        tenantToStart.forEach(tenantKey -> {
            dynamicTopicConsumerConfiguration.buildDynamicConsumers(tenantKey);
            dynamicTopicConsumerConfiguration.sendRefreshDynamicConsumersEvent(tenantKey);
        });
    }

    @Override
    public void onRefresh(String key, String config) {
        if (parseConfig(key, config)) {
            startChannels();
        }
    }

    @Override
    public boolean isListeningConfiguration(String updatedKey) {
        return TENANTS_LIST_CONFIG_KEY.equals(updatedKey);
    }

    @Override
    public void onInit(String key, String config) {
        parseConfig(key, config);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy