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

io.activej.launchers.crdt.CrdtNodeLogicModule Maven / Gradle / Ivy

/*
 * Copyright (C) 2020 ActiveJ LLC.
 *
 * 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.activej.launchers.crdt;

import io.activej.config.Config;
import io.activej.config.converter.ConfigConverters;
import io.activej.crdt.CrdtServer;
import io.activej.crdt.CrdtStorageClient;
import io.activej.crdt.storage.CrdtStorage;
import io.activej.crdt.storage.cluster.CrdtPartitions;
import io.activej.crdt.storage.cluster.CrdtRepartitionController;
import io.activej.crdt.storage.cluster.CrdtStorageCluster;
import io.activej.crdt.storage.cluster.DiscoveryService;
import io.activej.crdt.storage.local.CrdtStorageFs;
import io.activej.crdt.storage.local.CrdtStorageMap;
import io.activej.eventloop.Eventloop;
import io.activej.fs.ActiveFs;
import io.activej.inject.Key;
import io.activej.inject.annotation.Provides;
import io.activej.inject.annotation.QualifierAnnotation;
import io.activej.inject.module.AbstractModule;
import io.activej.types.Types;
import org.jetbrains.annotations.NotNull;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import static io.activej.common.Checks.checkState;
import static io.activej.config.converter.ConfigConverters.ofInteger;
import static io.activej.launchers.crdt.Initializers.ofFsCrdtClient;
import static io.activej.launchers.initializers.Initializers.ofAbstractServer;
import static io.activej.launchers.initializers.Initializers.ofEventloop;

public abstract class CrdtNodeLogicModule, S> extends AbstractModule {
	@Override
	protected void configure() {
		Type genericSuperclass = getClass().getGenericSuperclass();
		Type[] typeArguments = ((ParameterizedType) genericSuperclass).getActualTypeArguments();

		@NotNull Type supertype = Types.parameterizedType(CrdtStorage.class, typeArguments);

		bind((Key) Key.ofType(supertype, InMemory.class))
				.to(Key.ofType(Types.parameterizedType(CrdtStorageMap.class, typeArguments)));
		bind((Key) Key.ofType(supertype, Persistent.class))
				.to(Key.ofType(Types.parameterizedType(CrdtStorageFs.class, typeArguments)));

		Type[] clusterStorageTypes = Arrays.copyOf(typeArguments, 3);
		clusterStorageTypes[2] = String.class;

		bind((Key) Key.ofType(supertype, Cluster.class))
				.to(Key.ofType(Types.parameterizedType(CrdtStorageCluster.class, clusterStorageTypes)));
	}

	@Provides
	CrdtStorageMap runtimeCrdtClient(Eventloop eventloop, CrdtDescriptor descriptor) {
		return CrdtStorageMap.create(eventloop, descriptor.getCrdtFunction());
	}

	@Provides
	CrdtStorageFs fsCrdtClient(Eventloop eventloop, Config config, ActiveFs activeFs, CrdtDescriptor descriptor) {
		return CrdtStorageFs.create(eventloop, activeFs, descriptor.getSerializer(), descriptor.getCrdtFunction())
				.withInitializer(ofFsCrdtClient(config));
	}

	@Provides
	DiscoveryService discoveryService(CrdtStorageMap localClient, CrdtDescriptor descriptor, Config config) {
		config = config.getChild("crdt.cluster");

		Eventloop eventloop = localClient.getEventloop();

		Map> partitions = new HashMap<>();
		partitions.put(config.get("localPartitionId"), localClient);

		Map partitionsConfigmap = config.getChild("partitions").getChildren();
		checkState(!partitionsConfigmap.isEmpty(), "Cluster could not operate without partitions, config had none");

		for (Map.Entry entry : partitionsConfigmap.entrySet()) {
			InetSocketAddress address = ConfigConverters.ofInetSocketAddress().get(entry.getValue());
			partitions.put(entry.getKey(), CrdtStorageClient.create(eventloop, address, descriptor.getSerializer()));
		}

		return DiscoveryService.constant(partitions);
	}

	@Provides
	CrdtPartitions partitions(Eventloop eventloop, DiscoveryService discoveryService) {
		return CrdtPartitions.create(eventloop, discoveryService);
	}

	@Provides
	CrdtStorageCluster clusterCrdtClient(CrdtPartitions partitions, CrdtDescriptor descriptor, Config config) {
		return CrdtStorageCluster.create(
						partitions,
						descriptor.getCrdtFunction())
				.withReplicationCount(config.get(ofInteger(), "crdt.cluster.replicationCount", 1));
	}

	@Provides
	CrdtRepartitionController crdtRepartitionController(CrdtStorageCluster clusterClient, Config config) {
		return CrdtRepartitionController.create(clusterClient, config.get("crdt.cluster.localPartitionId"));
	}

	@Provides
	CrdtServer crdtServer(Eventloop eventloop, CrdtStorageMap client, CrdtDescriptor descriptor, Config config) {
		return CrdtServer.create(eventloop, client, descriptor.getSerializer())
				.withInitializer(ofAbstractServer(config.getChild("crdt.server")));
	}

	@Provides
	@Cluster
	CrdtServer clusterServer(Eventloop eventloop, CrdtStorageCluster client, CrdtDescriptor descriptor, Config config) {
		return CrdtServer.create(eventloop, client, descriptor.getSerializer())
				.withInitializer(ofAbstractServer(config.getChild("crdt.cluster.server")));
	}

	@Provides
	Eventloop eventloop(Config config) {
		return Eventloop.create()
				.withInitializer(ofEventloop(config));
	}

	@Retention(RetentionPolicy.RUNTIME)
	@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
	@QualifierAnnotation
	public @interface InMemory {}

	@Retention(RetentionPolicy.RUNTIME)
	@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
	@QualifierAnnotation
	public @interface Persistent {}

	@Retention(RetentionPolicy.RUNTIME)
	@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
	@QualifierAnnotation
	public @interface Cluster {}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy