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

software.xdev.tci.factory.BaseTCIFactory Maven / Gradle / Ivy

The newest version!
/*
 * Copyright © 2024 XDEV Software (https://xdev.software)
 *
 * 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 software.xdev.tci.factory;

import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Supplier;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.output.Slf4jLogConsumer;

import software.xdev.tci.TCI;
import software.xdev.tci.tracing.TCITracer;


@SuppressWarnings("java:S119")
public abstract class BaseTCIFactory<
	C extends GenericContainer,
	I extends TCI>
	implements TCIFactory
{
	private final Logger logger;
	protected Set returnedAndInUse = Collections.synchronizedSet(new HashSet<>());
	protected boolean warmedUp;
	/**
	 * Describes how often new infra should be created/started - if it fails.
	 * 

* This helps with "Random" errors that occur during infra startup. For example when a port allocation fails. *

*/ protected int getNewTryCount = 2; protected BiFunction infraBuilder; protected final Supplier containerBuilder; protected final String containerBaseName; protected final String containerLoggerName; protected final TCITracer tracer = new TCITracer(); protected BaseTCIFactory( final BiFunction infraBuilder, final Supplier containerBuilder, final String containerBaseName, final String containerLoggerName) { this.infraBuilder = Objects.requireNonNull(infraBuilder); this.containerBuilder = Objects.requireNonNull(containerBuilder); this.containerBaseName = Objects.requireNonNull(containerBaseName); this.containerLoggerName = Objects.requireNonNull(containerLoggerName); this.logger = LoggerFactory.getLogger(this.getClass()); this.register(); } @Override public void warmUp() { if(!this.warmedUp) { this.warmUpSync(); } } protected synchronized void warmUpSync() { if(this.warmedUp) { return; } final long startTime = System.currentTimeMillis(); this.warmUpInternal(); this.warmedUp = true; this.tracer.timedAdd("warmUp", System.currentTimeMillis() - startTime); } protected void warmUpInternal() { // No OP } protected C buildContainer() { return this.containerBuilder.get() .withLogConsumer(getLogConsumer(this.containerLoggerName)); } protected void handleInfraStartFail(final I infra) { CompletableFuture.runAsync(() -> { final long startTime = System.currentTimeMillis(); try { infra.stop(); } catch(final Exception stopEx) { this.log().warn("Failed to cleanup infra that failed during startup", stopEx); } this.tracer.timedAdd("infraStartFailCleanup", System.currentTimeMillis() - startTime); }); } protected I registerReturned(final I infra) { this.returnedAndInUse.add(infra); infra.setOnStopped(() -> this.returnedAndInUse.remove(infra)); return infra; } @Override public void close() { // NO OP } @Override public Set getReturnedAndInUse() { return new HashSet<>(this.returnedAndInUse); } @Override public TCITracer getTracer() { return this.tracer; } public void setGetNewTryCount(final int getNewTryCount) { if(getNewTryCount <= 0) { throw new IllegalArgumentException("must be greater than 0"); } this.getNewTryCount = getNewTryCount; } protected Logger log() { return this.logger; } protected static Slf4jLogConsumer getLogConsumer(final String name) { return new Slf4jLogConsumer(LoggerFactory.getLogger(name)); } }