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

io.gravitee.gateway.services.sync.process.distributed.synchronizer.AbstractDistributedSynchronizer Maven / Gradle / Ivy

There is a newer version: 4.5.2
Show newest version
/*
 * Copyright © 2015 The Gravitee team (http://gravitee.io)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.gravitee.gateway.services.sync.process.distributed.synchronizer;

import io.gravitee.gateway.services.sync.process.common.deployer.Deployer;
import io.gravitee.gateway.services.sync.process.common.model.Deployable;
import io.gravitee.gateway.services.sync.process.common.model.SyncAction;
import io.gravitee.gateway.services.sync.process.distributed.DistributedSynchronizer;
import io.gravitee.gateway.services.sync.process.distributed.fetcher.DistributedEventFetcher;
import io.gravitee.repository.distributedsync.model.DistributedEvent;
import io.gravitee.repository.distributedsync.model.DistributedEventType;
import io.gravitee.repository.distributedsync.model.DistributedSyncAction;
import io.reactivex.rxjava3.core.Completable;
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.core.Maybe;
import io.reactivex.rxjava3.schedulers.Schedulers;
import java.time.Instant;
import java.util.Set;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicLong;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author Guillaume LAMIRAND (guillaume.lamirand at graviteesource.com)
 * @author GraviteeSource Team
 */
@Slf4j
@RequiredArgsConstructor
public abstract class AbstractDistributedSynchronizer> implements DistributedSynchronizer {

    protected static final Set INIT_SYNC_ACTIONS = Set.of(DistributedSyncAction.DEPLOY);
    protected static final Set INCREMENTAL_SYNC_ACTIONS = Set.of(
        DistributedSyncAction.DEPLOY,
        DistributedSyncAction.UNDEPLOY
    );
    private final DistributedEventFetcher distributedEventFetcher;
    private final ThreadPoolExecutor syncFetcherExecutor;
    private final ThreadPoolExecutor syncDeployerExecutor;

    @Override
    public Completable synchronize(final Long from, final Long to) {
        boolean initialSync = from == null || from == -1;
        AtomicLong launchTime = new AtomicLong();
        return distributedEventFetcher
            .fetchLatest(from, to, distributedEventType(), syncActions(initialSync))
            .subscribeOn(Schedulers.from(syncFetcherExecutor))
            .flatMapMaybe(this::mapTo)
            // per deployable
            .compose(upstream -> {
                Y deployer = createDeployer();
                return upstream
                    .parallel(syncDeployerExecutor.getMaximumPoolSize())
                    .runOn(Schedulers.from(syncDeployerExecutor))
                    .flatMap(deployable -> {
                        if (deployable.syncAction() == SyncAction.DEPLOY) {
                            return deploy(deployer, deployable);
                        } else if (deployable.syncAction() == SyncAction.UNDEPLOY) {
                            return undeploy(deployer, deployable);
                        } else {
                            return Flowable.empty();
                        }
                    })
                    .sequential(distributedEventFetcher.bulkItems());
            })
            .count()
            .doOnSubscribe(disposable -> launchTime.set(Instant.now().toEpochMilli()))
            .doOnSuccess(count -> {
                String logMsg = String.format(
                    "%s %s(s) synchronized in %sms",
                    count,
                    distributedEventType().name().toLowerCase(),
                    (System.currentTimeMillis() - launchTime.get())
                );
                if (initialSync) {
                    log.info(logMsg);
                } else {
                    log.debug(logMsg);
                }
            })
            .ignoreElement();
    }

    protected Set syncActions(final boolean initialSync) {
        return initialSync ? INIT_SYNC_ACTIONS : INCREMENTAL_SYNC_ACTIONS;
    }

    protected abstract DistributedEventType distributedEventType();

    protected abstract Maybe mapTo(final DistributedEvent distributedEvent);

    protected abstract Y createDeployer();

    private Flowable deploy(final Y apiDeployer, final T deployable) {
        return apiDeployer.deploy(deployable).andThen(apiDeployer.doAfterDeployment(deployable)).andThen(Flowable.just(deployable));
    }

    private Flowable undeploy(final Y apiDeployer, final T deployable) {
        return apiDeployer.undeploy(deployable).andThen(apiDeployer.doAfterUndeployment(deployable)).andThen(Flowable.just(deployable));
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy