io.hekate.messaging.internal.DefaultMessagingChannel Maven / Gradle / Ivy
/*
* Copyright 2022 The Hekate Project
*
* The Hekate Project licenses this file to you 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.hekate.messaging.internal;
import io.hekate.cluster.ClusterFilter;
import io.hekate.cluster.ClusterView;
import io.hekate.cluster.internal.TopologyContextCache;
import io.hekate.core.internal.util.ArgAssert;
import io.hekate.messaging.MessagingChannel;
import io.hekate.messaging.MessagingChannelId;
import io.hekate.messaging.loadbalance.LoadBalancer;
import io.hekate.messaging.operation.Aggregate;
import io.hekate.messaging.operation.Broadcast;
import io.hekate.messaging.operation.Request;
import io.hekate.messaging.operation.Send;
import io.hekate.messaging.operation.Subscribe;
import io.hekate.partition.PartitionMapper;
import io.hekate.partition.RendezvousHashMapper;
import io.hekate.util.format.ToString;
import io.hekate.util.format.ToStringIgnore;
import java.util.concurrent.Executor;
/**
* Default implementation of {@link MessagingChannel} interface.
*
* @param Message type.
*/
class DefaultMessagingChannel implements MessagingChannel, MessageOperationOpts {
/** Messaging gateway. */
private final MessagingGateway gateway;
/** Cluster view of this channel. */
@ToStringIgnore
private final ClusterView cluster;
/** Partition mapper (see {@link #withPartitions(PartitionMapper)}). */
private final PartitionMapper partitions;
/** Load balancer (see {@link #withLoadBalancer(LoadBalancer)}. */
private final LoadBalancer balancer;
/** Cache for load balancer. */
@ToStringIgnore
private TopologyContextCache balancerCache;
/**
* Constructs a new instance.
*
* @param gateway Messaging gateway.
* @param cluster Cluster view of this channel.
* @param partitions Partition mapper.
* @param balancer Load balancer.
*/
public DefaultMessagingChannel(
MessagingGateway gateway,
ClusterView cluster,
PartitionMapper partitions,
LoadBalancer balancer
) {
this.gateway = gateway;
this.cluster = cluster;
this.partitions = partitions;
this.balancer = balancer;
}
@Override
public Send newSend(T message) {
SendOperationBuilder builder = new SendOperationBuilder<>(message, context(), this);
gateway.baseRetryPolicy().configure(builder);
return builder;
}
@Override
public Request newRequest(T request) {
RequestOperationBuilder builder = new RequestOperationBuilder<>(request, context(), this);
gateway.baseRetryPolicy().configure(builder);
return builder;
}
@Override
public Subscribe newSubscribe(T request) {
SubscribeOperationBuilder builder = new SubscribeOperationBuilder<>(request, context(), this);
gateway.baseRetryPolicy().configure(builder);
return builder;
}
@Override
public Broadcast newBroadcast(T request) {
BroadcastOperationBuilder builder = new BroadcastOperationBuilder<>(request, context(), this);
gateway.baseRetryPolicy().configure(builder);
return builder;
}
@Override
public Aggregate newAggregate(T request) {
AggregateOperationBuilder builder = new AggregateOperationBuilder<>(request, context(), this);
gateway.baseRetryPolicy().configure(builder);
return builder;
}
@Override
public MessagingChannelId id() {
return gateway.channelId();
}
@Override
public String name() {
return gateway.name();
}
@Override
public Class baseType() {
return gateway.baseType();
}
@Override
public PartitionMapper partitions() {
return partitions;
}
@Override
public TopologyContextCache balancerCache() {
// No synchronization here.
// It is ok if different threads will construct and access different cache instances in parallel.
if (balancerCache == null) {
balancerCache = new TopologyContextCache();
}
return balancerCache;
}
@Override
public DefaultMessagingChannel withPartitions(int partitions, int backupNodes) {
if (partitions().partitions() == partitions && partitions().backupNodes() == backupNodes) {
return this;
}
RendezvousHashMapper mapper = RendezvousHashMapper.of(cluster, partitions, backupNodes);
return new DefaultMessagingChannel<>(
gateway,
cluster,
mapper,
balancer
);
}
@Override
public MessagingChannel withPartitions(PartitionMapper mapper) {
ArgAssert.notNull(mapper, "Mapper");
return new DefaultMessagingChannel<>(
gateway,
cluster,
mapper,
balancer
);
}
@Override
public DefaultMessagingChannel withLoadBalancer(LoadBalancer balancer) {
ArgAssert.notNull(balancer, "Load balancer");
return new DefaultMessagingChannel<>(
gateway,
cluster,
partitions,
balancer
);
}
@Override
public Executor executor() {
return gateway.executor();
}
@Override
public DefaultMessagingChannel filterAll(ClusterFilter filter) {
ArgAssert.notNull(filter, "Filter");
ClusterView newCluster = cluster.filterAll(filter);
PartitionMapper newPartitions = partitions.copy(newCluster);
return new DefaultMessagingChannel<>(
gateway,
newCluster,
newPartitions,
balancer
);
}
@Override
public ClusterView cluster() {
return cluster;
}
@Override
public DefaultMessagingChannel withCluster(ClusterView cluster) {
ArgAssert.notNull(cluster, "Cluster");
ClusterView newCluster = cluster.filter(MessagingMetaData.hasReceiver(gateway.name()));
PartitionMapper newPartitions = partitions.copy(newCluster);
return new DefaultMessagingChannel<>(
gateway,
newCluster,
newPartitions,
balancer
);
}
@Override
public int nioThreads() {
return gateway.nioThreads();
}
@Override
public int workerThreads() {
return gateway.workerThreads();
}
@Override
public LoadBalancer balancer() {
return balancer;
}
// Package level for testing purposes.
MessagingGatewayContext context() {
return gateway.requireContext();
}
@Override
public String toString() {
return ToString.format(MessagingChannel.class, this);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy