Commit 959134f6 authored by Kishore Battula's avatar Kishore Battula
Browse files

Merge branch 'users/komakkar/eventGridAbstraction' into 'master'

EG Topic Abstraction

See merge request !59
parents 86bac7f2 51d57f7b
Pipeline #19312 failed with stages
in 7 minutes and 42 seconds
......@@ -20,7 +20,7 @@
<groupId>org.opengroup.osdu</groupId>
<artifactId>core-lib-azure</artifactId>
<packaging>jar</packaging>
<version>0.0.49</version>
<version>0.0.50</version>
<name>core-lib-azure</name>
<properties>
......@@ -234,11 +234,6 @@
<version>${mockito-junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
......@@ -248,6 +243,11 @@
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-eventgrid</artifactId>
<version>1.2.0</version>
</dependency>
</dependencies>
<repositories>
......
// Copyright © Microsoft Corporation
//
// 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.opengroup.osdu.azure.cache;
import com.microsoft.azure.eventgrid.EventGridClient;
import org.opengroup.osdu.core.common.cache.VmCache;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
/**
* Implementation of ICache for TopicClient.
*/
@Component
@Lazy
public class EventGridTopicClientCache extends VmCache<String, EventGridClient> {
/**
* Default cache constructor.
*/
public EventGridTopicClientCache() {
super(60 * 60, 1000);
}
/**
* @param key cache key
* @return true if found in cache
*/
public boolean containsKey(final String key) {
return this.get(key) != null;
}
}
// Copyright © Microsoft Corporation
//
// 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.opengroup.osdu.azure.eventgrid;
import com.microsoft.azure.eventgrid.EventGridClient;
import com.microsoft.azure.eventgrid.TopicCredentials;
import com.microsoft.azure.eventgrid.implementation.EventGridClientImpl;
import org.opengroup.osdu.azure.cache.EventGridTopicClientCache;
import org.opengroup.osdu.azure.partition.PartitionInfoAzure;
import org.opengroup.osdu.azure.partition.PartitionServiceClient;
import org.opengroup.osdu.common.Validators;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Implementation for IEventGridTopicClientFactory.
*/
@Component
public class EventGridTopicClientFactoryImpl implements IEventGridTopicClientFactory {
@Autowired
private PartitionServiceClient partitionService;
@Autowired
private EventGridTopicClientCache clientCache;
/**
* @param dataPartitionId Data partition id
* @param topicName Topic Name
* @return EventGridClient
*/
@Override
public EventGridClient getClient(final String dataPartitionId, final TopicName topicName) {
Validators.checkNotNullAndNotEmpty(dataPartitionId, "dataPartitionId");
Validators.checkNotNull(topicName, "topicName");
String cacheKey = String.format("%s-%s", dataPartitionId, topicName);
if (this.clientCache.containsKey(cacheKey)) {
return this.clientCache.get(cacheKey);
}
PartitionInfoAzure pi = this.partitionService.getPartition(dataPartitionId);
TopicCredentials topicCredentials = null;
if (topicName == TopicName.RECORDS_CHANGED) {
topicCredentials = new TopicCredentials(pi.getEventGridRecordsTopicAccessKey());
}
EventGridClient eventGridClient = new EventGridClientImpl(topicCredentials);
this.clientCache.put(cacheKey, eventGridClient);
return eventGridClient;
}
}
// Copyright © Microsoft Corporation
//
// 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.opengroup.osdu.azure.eventgrid;
import com.microsoft.azure.eventgrid.EventGridClient;
import com.microsoft.azure.eventgrid.models.EventGridEvent;
import org.opengroup.osdu.azure.partition.PartitionInfoAzure;
import org.opengroup.osdu.azure.partition.PartitionServiceClient;
import org.opengroup.osdu.core.common.logging.ILogger;
import org.opengroup.osdu.core.common.model.http.AppException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
/**
* A simpler interface to interact with Azure Event Grid Topic.
* Usage examples:
* <pre>
* {@code
* @Autowired
* private EventGridTopicStore eventGridTopicStore;
*
* String publishToEventGridTopic()
* {
* List<EventGridEvent> eventsList = new ArrayList<>();
* eventsList.add(new EventGridEvent(
* UUID.randomUUID().toString(),
* "subject",
* "data",
* "event type",
* DateTime.now(),
* "0.1"
* ));
*
* eventGridTopicStore.publishToEventGridTopic("dataPartitionId", "topicName", eventList);
* }
* }
* </pre>
*/
@Component
public class EventGridTopicStore {
@Autowired
private IEventGridTopicClientFactory eventGridTopicClientFactory;
@Autowired
private ILogger logger;
@Autowired
private PartitionServiceClient partitionService;
/**
* @param dataPartitionId Data partition id
* @param topicName Topic name
* @param eventsList List of Event Grid Events
*/
public void publishToEventGridTopic(final String dataPartitionId, final TopicName topicName, final List<EventGridEvent> eventsList) {
PartitionInfoAzure pi = this.partitionService.getPartition(dataPartitionId);
String endpoint = "";
if (topicName == TopicName.RECORDS_CHANGED) {
try {
endpoint = String.format("https://%s/", new URI(pi.getEventGridRecordsTopicEndpoint()).getHost());
} catch (URISyntaxException e) {
throw new AppException(500, "Invalid Event Grid endpoint URI", "PartitionInfo for eventgrid-recordstopic " + pi.getEventGridRecordsTopicEndpoint(), e);
}
}
EventGridClient eventGridClient = eventGridTopicClientFactory.getClient(dataPartitionId, topicName);
eventGridClient.publishEvents(endpoint, eventsList);
}
}
// Copyright © Microsoft Corporation
//
// 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.opengroup.osdu.azure.eventgrid;
import com.microsoft.azure.eventgrid.EventGridClient;
/**
* Interface for Event Grid Topic client factory to return appropriate
* blobServiceClient based on the data partition id, and topic name.
*/
public interface IEventGridTopicClientFactory {
/**
* @param dataPartitionId Data partition id
* @param topicName Topic name
* @return EventGridClient
*/
EventGridClient getClient(String dataPartitionId, TopicName topicName);
}
// Copyright © Microsoft Corporation
//
// 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.opengroup.osdu.azure.eventgrid;
/**
* Topic Name Enum.
* The Topic Stores and client are controlled by the same.
*/
public enum TopicName {
RECORDS_CHANGED
}
// Copyright © Microsoft Corporation
//
// 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.opengroup.osdu.azure.eventgrid;
import com.microsoft.azure.eventgrid.EventGridClient;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.opengroup.osdu.azure.cache.EventGridTopicClientCache;
import org.opengroup.osdu.azure.partition.PartitionInfoAzure;
import org.opengroup.osdu.azure.partition.PartitionServiceClient;
import org.opengroup.osdu.core.common.partition.Property;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class EventGridTopicClientFactoryImplTest {
private static final String VALID_TOPIC_NAME = "RecordsChanged";
private static final String VALID_DATA_PARTIION_ID = "validDataPartitionId";
@Mock
private PartitionServiceClient partitionService;
@InjectMocks
private EventGridTopicClientFactoryImpl sut;
@Mock
private EventGridTopicClientCache clientCache;
@Test
public void should_throwException_given_nullDataPartitionId() {
NullPointerException nullPointerException = Assertions.assertThrows(NullPointerException.class,
() -> this.sut.getClient(null, TopicName.RECORDS_CHANGED));
assertEquals("dataPartitionId cannot be null!", nullPointerException.getMessage());
}
@Test
public void should_throwException_given_emptyDataPartitionId() {
IllegalArgumentException illegalArgumentException = Assertions.assertThrows(IllegalArgumentException.class,
() -> this.sut.getClient("", TopicName.RECORDS_CHANGED));
assertEquals("dataPartitionId cannot be empty!", illegalArgumentException.getMessage());
}
@Test
public void should_throwException_given_nullTopicName() {
NullPointerException nullPointerException = Assertions.assertThrows(NullPointerException.class,
() -> this.sut.getClient(VALID_DATA_PARTIION_ID, null));
assertEquals("topicName cannot be null!", nullPointerException.getMessage());
}
@Test
public void should_return_validClient_given_validPartitionId() {
// Setup
when(this.partitionService.getPartition(VALID_DATA_PARTIION_ID)).thenReturn(
PartitionInfoAzure.builder()
.idConfig(Property.builder().value(VALID_DATA_PARTIION_ID).build())
.eventGridRecordsTopicAccessKeyConfig(Property.builder().value(VALID_TOPIC_NAME).build()).build());
when(this.clientCache.containsKey(any())).thenReturn(false);
// Act
EventGridClient eventGridClient = this.sut.getClient(VALID_DATA_PARTIION_ID, TopicName.RECORDS_CHANGED);
// Assert
assertNotNull(eventGridClient);
verify(this.clientCache, times(1)).put(any(), any());
}
}
\ No newline at end of file
// Copyright © Microsoft Corporation
//
// 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.opengroup.osdu.azure.eventgrid;
import com.microsoft.azure.eventgrid.EventGridClient;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.opengroup.osdu.azure.partition.PartitionInfoAzure;
import org.opengroup.osdu.azure.partition.PartitionServiceClient;
import org.opengroup.osdu.core.common.logging.ILogger;
import org.opengroup.osdu.core.common.model.http.AppException;
import org.opengroup.osdu.core.common.partition.Property;
import java.util.ArrayList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.initMocks;
@ExtendWith(MockitoExtension.class)
class EventGridTopicStoreTest {
@Mock
EventGridTopicClientFactoryImpl eventGridTopicClientFactory;
@Mock
EventGridClient eventGridClient;
@Mock
private ILogger logger;
@Mock
private PartitionServiceClient partitionService;
@InjectMocks
EventGridTopicStore sut;
private static final String VALID_DATA_PARTIION_ID = "validDataPartitionId";
private static final String INVALID_URI = "://invalidUri";
@BeforeEach
void setUp() {
initMocks(this);
}
@Test
public void should_throwException_given_invalidURI() {
when(this.partitionService.getPartition(VALID_DATA_PARTIION_ID)).thenReturn(
PartitionInfoAzure.builder()
.idConfig(Property.builder().value(VALID_DATA_PARTIION_ID).build())
.eventGridRecordsTopicEndpointConfig(Property.builder().value(INVALID_URI).build()).build());
AppException appException = Assertions.assertThrows(AppException.class,
() -> this.sut.publishToEventGridTopic(VALID_DATA_PARTIION_ID, TopicName.RECORDS_CHANGED, new ArrayList<>()));
assertEquals("PartitionInfo for eventgrid-recordstopic ://invalidUri", appException.getError().getMessage());
verify(this.eventGridClient, times(0)).publishEvents(any(), any());
}
@Test
public void should_should_invoke_publishEvents() {
when(this.partitionService.getPartition(VALID_DATA_PARTIION_ID)).thenReturn(
PartitionInfoAzure.builder()
.idConfig(Property.builder().value(VALID_DATA_PARTIION_ID).build())
.eventGridRecordsTopicEndpointConfig(Property.builder().value("validURL").build()).build());
when(this.eventGridTopicClientFactory.getClient(VALID_DATA_PARTIION_ID, TopicName.RECORDS_CHANGED)).thenReturn(this.eventGridClient);
this.sut.publishToEventGridTopic(VALID_DATA_PARTIION_ID, TopicName.RECORDS_CHANGED, new ArrayList<>());
verify(this.eventGridClient, times(1)).publishEvents(any(), any());
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment