Skip to content

Commit

Permalink
PR comments
Browse files Browse the repository at this point in the history
  • Loading branch information
schananas committed Jul 23, 2024
1 parent 9e7b710 commit 331b032
Show file tree
Hide file tree
Showing 11 changed files with 210 additions and 97 deletions.
2 changes: 1 addition & 1 deletion multitenancy-spring-boot-3-integrationtests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
<packaging>jar</packaging>

<properties>
<axon.version>4.10.0-SNAPSHOT</axon.version>
<axon.version>4.10.0</axon.version>
<testcoontainers.version>1.20.0</testcoontainers.version>

<jar-plugin.version>3.4.2</jar-plugin.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
Expand All @@ -69,7 +70,7 @@
@AutoConfiguration
@ConditionalOnClass(AxonServerConfiguration.class)
@ConditionalOnProperty(value = {"axon.axonserver.enabled", "axon.multi-tenancy.enabled"}, matchIfMissing = true)
@AutoConfigureBefore(AxonServerAutoConfiguration.class)
@AutoConfigureAfter(AxonServerAutoConfiguration.class)
@ComponentScan(excludeFilters = {
@ComponentScan.Filter(
type = FilterType.REGEX,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
/*
* Copyright (c) 2010-2024. Axon Framework
*
* 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 org.axonframework.extensions.multitenancy.autoconfig;

import org.axonframework.axonserver.connector.event.axon.PersistentStreamMessageSource;
import org.axonframework.axonserver.connector.event.axon.PersistentStreamMessageSourceFactory;
import org.axonframework.common.StringUtils;
import org.axonframework.extensions.multitenancy.components.TenantProvider;
import org.axonframework.extensions.multitenancy.components.eventstore.MultiTenantPersistentStreamMessageSource;
import org.axonframework.extensions.multitenancy.components.eventstore.TenantPersistentStreamMessageSourceFactory;
import org.axonframework.springboot.autoconfig.AxonServerAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
Expand All @@ -16,7 +33,7 @@
* This configuration is enabled when Axon Server and multi-tenancy are both enabled.
*
* @author Stefan Dragisic
* @since 4.10
* @since 4.10.0
*/
@AutoConfiguration
@ConditionalOnProperty(value = {"axon.axonserver.enabled", "axon.multi-tenancy.enabled"}, matchIfMissing = true)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.axonframework.extensions.multitenancy.components.deadletterqueue.MultiTenantDeadLetterQueueFactory;
import org.axonframework.extensions.multitenancy.components.eventstore.MultiTenantEventStore;
import org.axonframework.extensions.multitenancy.components.eventstore.TenantEventSegmentFactory;
import org.axonframework.extensions.multitenancy.components.eventstore.TenantPersistentStreamMessageSourceFactory;
import org.axonframework.extensions.multitenancy.components.queryhandeling.MultiTenantQueryBus;
import org.axonframework.extensions.multitenancy.components.queryhandeling.MultiTenantQueryUpdateEmitter;
import org.axonframework.extensions.multitenancy.components.queryhandeling.TenantQuerySegmentFactory;
Expand All @@ -37,8 +38,6 @@
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

import java.util.concurrent.ScheduledExecutorService;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

Expand Down
4 changes: 4 additions & 0 deletions multitenancy/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,9 @@
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.axonframework</groupId>
<artifactId>axon-server-connector</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -1,25 +1,36 @@
/*
* Copyright (c) 2010-2024. Axon Framework
*
* 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 org.axonframework.extensions.multitenancy.components;

import java.util.Map;

/**
* Interface for multi-tenant message sources that can provide tenant segments.
*
* @param <T> The type of the tenant segment
*/
import org.axonframework.eventhandling.EventMessage;
import org.axonframework.messaging.SubscribableMessageSource;

/**
* Interface for multi-tenant message sources that can provide tenant segments.
*
* @author Stefan Dragisic
* @param <T> The type of the tenant segment, which must extend MessageSource
* @since 4.10.0
*/
public interface MultiTenantSubscribableMessageSource<T extends SubscribableMessageSource<EventMessage<?>>> {

/**
* Returns a map of tenant segments, where the key is the TenantDescriptor
* and the value is the corresponding tenant segment of type T, which extends MessageSource.
* and the value is the corresponding tenant segment of type T, which extends {@link SubscribableMessageSource}.
*
* @return A map of TenantDescriptor to tenant segments
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright (c) 2010-2024. Axon Framework
*
* 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 org.axonframework.extensions.multitenancy.components.eventstore;


import io.axoniq.axonserver.connector.event.PersistentStreamProperties;
import org.axonframework.axonserver.connector.event.axon.PersistentStreamMessageSource;
import org.axonframework.config.Configuration;
import org.axonframework.extensions.multitenancy.components.MultiTenantAwareComponent;
import org.axonframework.extensions.multitenancy.components.MultiTenantSubscribableMessageSource;
import org.axonframework.extensions.multitenancy.components.TenantDescriptor;
import org.axonframework.common.Registration;

import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;

/**
* A multi-tenant persistent stream message source that extends PersistentStreamMessageSource
* and implements MultiTenantAwareComponent and MultiTenantSubscribableMessageSource interfaces.
* <p>
* This class provides functionality to manage message sources for multiple tenants,
* allowing registration and management of tenant-specific persistent stream message sources.
* It maintains a concurrent map of tenant descriptors to their corresponding message sources.
* </p>
* <p>
* The class supports operations such as registering new tenants, starting tenants,
* and retrieving all tenant segments. It uses a factory to create tenant-specific
* message sources, ensuring proper initialization and configuration for each tenant.
* </p>
* @author Stefan Dragisic
* @since 4.10.0
*/
public class MultiTenantPersistentStreamMessageSource extends PersistentStreamMessageSource
implements MultiTenantAwareComponent, MultiTenantSubscribableMessageSource<PersistentStreamMessageSource> {

private final String name;
private final Configuration configuration;
private final TenantPersistentStreamMessageSourceFactory tenantPersistentStreamMessageSourceFactory;
private final Map<TenantDescriptor, PersistentStreamMessageSource> tenantSegments = new ConcurrentHashMap<>();
private final PersistentStreamProperties persistentStreamProperties;
private final ScheduledExecutorService scheduler;
private final int batchSize;
private final String context;

/**
* Constructs a new MultiTenantPersistentStreamMessageSource.
*
* @param name The name of the message source.
* @param persistentStreamProperties Properties for the persistent stream.
* @param scheduler The scheduled executor service for managing tasks.
* @param batchSize The size of each batch of messages to process.
* @param context The context in which this message source operates.
* @param configuration The configuration settings for the message source.
* @param tenantPersistentStreamMessageSourceFactory The factory for creating tenant-specific message sources.
*/
public MultiTenantPersistentStreamMessageSource(String name, PersistentStreamProperties
persistentStreamProperties, ScheduledExecutorService scheduler, int batchSize, String context, Configuration configuration,
TenantPersistentStreamMessageSourceFactory tenantPersistentStreamMessageSourceFactory) {

super(name, configuration, persistentStreamProperties, scheduler, batchSize, context);
this.tenantPersistentStreamMessageSourceFactory = tenantPersistentStreamMessageSourceFactory;
this.name = name;
this.configuration = configuration;
this.persistentStreamProperties = persistentStreamProperties;
this.scheduler = scheduler;
this.batchSize = batchSize;
this.context = context;
}

/**
* Registers a new tenant with the message source.
*
* @param tenantDescriptor The descriptor of the tenant to register.
* @return A Registration object that can be used to unregister the tenant.
*/
@Override
public Registration registerTenant(TenantDescriptor tenantDescriptor) {
PersistentStreamMessageSource tenantSegment = tenantPersistentStreamMessageSourceFactory.build(name,
persistentStreamProperties, scheduler, batchSize, context, configuration, tenantDescriptor);
tenantSegments.putIfAbsent(tenantDescriptor, tenantSegment);

return () -> {
PersistentStreamMessageSource removed = tenantSegments.remove(tenantDescriptor);
return removed != null;
};
}

/**
* Registers and starts a new tenant with the message source.
* In this implementation, it's equivalent to just registering the tenant.
* This component doesn't require any additional steps to start a tenant.
*
* @param tenantDescriptor The descriptor of the tenant to register and start.
* @return A Registration object that can be used to unregister the tenant.
*/
@Override
public Registration registerAndStartTenant(TenantDescriptor tenantDescriptor) {
return registerTenant(tenantDescriptor);
}

/**
* Returns a map of all registered tenant segments.
*
* @return An unmodifiable map where keys are TenantDescriptors and values are PersistentStreamMessageSources.
*/
@Override
public Map<TenantDescriptor, PersistentStreamMessageSource> tenantSegments() {
return Collections.unmodifiableMap(tenantSegments);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
package org.axonframework.extensions.multitenancy.autoconfig;
/*
* Copyright (c) 2010-2024. Axon Framework
*
* 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 org.axonframework.extensions.multitenancy.components.eventstore;

import io.axoniq.axonserver.connector.event.PersistentStreamProperties;
import org.axonframework.axonserver.connector.AxonServerConfiguration;
Expand All @@ -16,7 +31,7 @@
*
* This interface is used to create a {@link PersistentStreamMessageSource} for a given tenant,
* @author Stefan Dragisic
* @since 4.10
* @since 4.10.0
*/
@FunctionalInterface
public interface TenantPersistentStreamMessageSourceFactory {
Expand Down
Loading

0 comments on commit 331b032

Please sign in to comment.