@Override public boolean matches(CommandMessage<?> commandMessage) { return !filter.matches(commandMessage); } }
/** * Instantiate a Builder to be able to create a {@link DistributedCommandBus}. * <p> * The {@link MessageMonitor} is defaulted to a {@link NoOpMessageMonitor}. * The {@link CommandRouter} and {@link CommandBusConnector} are <b>hard requirements</b> and as such should be * provided. * * @return a Builder to be able to create a {@link DistributedCommandBus} */ public static Builder builder() { return new Builder(); }
@Override public Registration registerHandlerInterceptor( MessageHandlerInterceptor<? super CommandMessage<?>> handlerInterceptor) { return connector.registerHandlerInterceptor(handlerInterceptor); }
/** * {@inheritDoc} * <p/> * In the DistributedCommandBus, the handler is subscribed to the local segment only. */ @Override public Registration subscribe(String commandName, MessageHandler<? super CommandMessage<?>> handler) { Registration reg = connector.subscribe(commandName, handler); updateFilter(commandFilter.get().or(new CommandNameFilter(commandName))); return () -> { updateFilter(commandFilter.get().and(new DenyCommandNameFilter(commandName))); return reg.cancel(); }; }
/** * Registers the given {@code member} with given {@code loadFactor} and {@code commandFilter} if it is not * already contained in the {@link ConsistentHash}. It will return the current ConsistentHash if the addition is * a duplicate and returns a new ConsistentHash with updated memberships if it is not. * <p> * The relative loadFactor of the member determines the likelihood of being selected as a destination for a command. * * @param member the member to register * @param loadFactor the load factor of the new member * @param commandFilter filter describing which commands can be handled by the given member * @return a new {@link ConsistentHash} instance with updated memberships */ public ConsistentHash with(Member member, int loadFactor, CommandMessageFilter commandFilter) { Assert.notNull(member, () -> "Member may not be null"); ConsistentHashMember newMember = new ConsistentHashMember(member, loadFactor, commandFilter); if (members.containsKey(member.name()) && newMember.equals(members.get(member.name()))) { return this; } Map<String, ConsistentHashMember> newMembers = new TreeMap<>(members); newMembers.put(member.name(), newMember); return new ConsistentHash(newMembers, hashFunction, modCount + 1); }
/** * Deregisters the given {@code member} and returns a new {@link ConsistentHash} with updated memberships. * * @param member the member to remove from the consistent hash * @return a new {@link ConsistentHash} instance with updated memberships */ public ConsistentHash without(Member member) { Assert.notNull(member, () -> "Member may not be null"); if (!members.containsKey(member.name())) { return this; } Map<String, ConsistentHashMember> newMembers = new TreeMap<>(members); newMembers.remove(member.name()); return new ConsistentHash(newMembers, hashFunction, modCount + 1); }
/** * Stores a callback * * @param callbackId The id to store the callback with * @param commandCallbackWrapper The CommandCallbackWrapper to store * @param <E> The type of the remote endpoint identifier * @param <C> The type of the command * @param <R> The type of the result */ public <E, C, R> void store(String callbackId, CommandCallbackWrapper<E, C, R> commandCallbackWrapper) { CommandCallbackWrapper previous; if ((previous = callbacks.put(callbackId, commandCallbackWrapper)) != null) { //a previous callback with the same command ID was already found, we will cancel the callback as the command //is likely to be retried, so the previous one likely failed previous.reportResult(asCommandResultMessage(new CommandBusConnectorCommunicationException( "Command-callback cancelled, a new command with the same ID is entered into the command bus"))); } }
@Override public <T> Optional<T> getConnectionEndpoint(Class<T> protocol) { return member.getConnectionEndpoint(protocol); }
/** * Returns the hashes covered by the member. If the hash of the routing key matches with one of the returned * hashes and the member is capable of handling the command then it will be selected as a target for the * command. * * @return the hashes covered by this member */ public Set<String> hashes() { return IntStream.range(0, segmentCount) .mapToObj(i -> hash(name() + " #" + i)) .collect(Collectors.toSet()); }
@Override public boolean local() { return member.local(); }
/** * Invokes {@link CommandCallback#onResult(CommandMessage, CommandResultMessage)} with given {@code result} on * the wrapped callback. * * @param result the result of the command */ public void reportResult(CommandResultMessage<R> result) { onResult(getMessage(), result); }
@Override protected String doResolveRoutingKey(CommandMessage<?> command) { String routingKey; try { routingKey = findIdentifier(command); } catch (InvocationTargetException e) { throw new AxonConfigurationException( "An exception occurred while extracting routing information form a command", e ); } catch (IllegalAccessException e) { throw new AxonConfigurationException( "The current security context does not allow extraction of routing information from the given command.", e ); } return routingKey; }
@Override public String toString() { return member.name() + "(" + segmentCount + ")"; } }
@Override public void suspect() { member.suspect(); }
/** * Updates the load factor of this node compared to other nodes registered with the {@link CommandRouter}. * * @param loadFactor the new load factor of this node */ public void updateLoadFactor(int loadFactor) { this.loadFactor = loadFactor; commandRouter.updateMembership(loadFactor, commandFilter.get()); }
/** * Initializes a {@link DistributedCommandBus} as specified through this Builder. * * @return a {@link DistributedCommandBus} as specified through this Builder */ public DistributedCommandBus build() { return new DistributedCommandBus(this); }
/** * Instantiate a {@link DistributedCommandBus} based on the fields contained in the {@link Builder}. * <p> * Will assert that the {@link CommandRouter}, {@link CommandBusConnector} and {@link MessageMonitor} are not * {@code null}, and will throw an {@link AxonConfigurationException} if any of them is {@code null}. * * @param builder the {@link Builder} used to instantiate a {@link DistributedCommandBus} instance */ protected DistributedCommandBus(Builder builder) { builder.validate(); this.commandRouter = builder.commandRouter; this.connector = builder.connector; this.messageMonitor = builder.messageMonitor; }
@Override public String name() { return member.name(); }