Skip to content

Commit

Permalink
Merge pull request #28 from telekom/feature/golaris-support
Browse files Browse the repository at this point in the history
Changes for 4.2.0
  • Loading branch information
Th3Shadowbroker authored Aug 12, 2024
2 parents 0bdd32b + 95e1d0c commit e29c015
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public Optional<T> getByKey(String key) throws JsonCacheException {
var value = map.get(key);
if (value != null) {
try {
log.debug("Raw JSON value for key {}: {}", key, value.getValue());
var mappedValue = mapper.readValue(value.getValue(), mapClass);
return of(mappedValue);
} catch (JsonProcessingException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,35 @@

package de.telekom.eni.pandora.horizon.model.common;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.io.Serial;
import java.io.Serializable;

@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public abstract class Cacheable implements Serializable, Comparable<Cacheable> {

@Serial
private static final long serialVersionUID = 1L;
protected String key;
@Serial
private static final long serialVersionUID = 1L;
protected String key;

protected String getType() {
return this.getClass().getSimpleName();
}
protected String getType() {
return this.getClass().getSimpleName();
}

protected Cacheable(String key) {
this.key = key;
}
protected Cacheable(String key) {
this.key = key;
}

@Override
public int compareTo(Cacheable cacheable) {
var otherKey = cacheable.getKey();
var thisKey = getKey();
return otherKey.compareTo(thisKey);
}
@Override
public int compareTo(Cacheable cacheable) {
var otherKey = cacheable.getKey();
var thisKey = getKey();
return otherKey.compareTo(thisKey);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,55 @@

package de.telekom.eni.pandora.horizon.model.meta;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import de.telekom.eni.pandora.horizon.model.common.Cacheable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.io.Serial;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;

@Getter
@Setter
public class CircuitBreakerMessage extends Cacheable {
@Serial
private static final long serialVersionUID = 600L;
@JsonIgnoreProperties(ignoreUnknown = true)
public class CircuitBreakerMessage {

private String subscriptionId;
private String subscriberId;
private String subscriptionId;

private CircuitBreakerStatus status;
private String eventType;

private String environment;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'hh:mm:ssX", timezone = "UTC")
private Date lastModified;

private String callbackUrl; // TODO: Think if we really need the callbackUrl
private String originMessageId;

private Date timestamp;
private CircuitBreakerStatus status;

/**
* Can be null
*/
private CircuitBreakerHealthCheck lastHealthCheck;
private String assignedPodId;
private String environment;

public CircuitBreakerMessage(String subscriptionId, CircuitBreakerStatus circuitBreakerStatus, String callbackUrl, String environment) {
super(subscriptionId);
this.subscriptionId = subscriptionId;
this.subscriberId = ""; // TODO: Set in DUDE and put in constructor
this.status = circuitBreakerStatus;
this.environment = environment;
this.callbackUrl = callbackUrl;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'hh:mm:ssX", timezone = "UTC")
private Date lastOpened;

this.timestamp = Date.from(Instant.now());
this.lastHealthCheck = null;
this.assignedPodId = "";
}
private int loopCounter;

@Override
protected String getType() {
return "circuit-breaker";
}
public CircuitBreakerMessage() {
super();
}

@Override
public int compareTo(Cacheable cachable) {
if(cachable instanceof CircuitBreakerMessage circuitBreakerMessage) {
// -1 -> move to left (beginning), 0 -> keep, 1 -> move to right (end)
// sorted by timestamp millis, smallest first -> oldest timestamp first
return getTimestamp().compareTo(circuitBreakerMessage.getTimestamp());
}
public CircuitBreakerMessage(String subscriptionId, String eventType, Date lastModified, String originMessageId, CircuitBreakerStatus status, String environment, Date lastOpened, int loopCounter) {
this.subscriptionId = subscriptionId;
this.eventType = eventType;
this.lastModified = lastModified != null ? Date.from(lastModified.toInstant().truncatedTo(ChronoUnit.SECONDS)) : null;
this.originMessageId = originMessageId;
this.status = status;
this.environment = environment;
this.lastOpened = lastOpened != null ? Date.from(lastOpened.toInstant().truncatedTo(ChronoUnit.SECONDS)) : null;
this.loopCounter = loopCounter;
}

return super.compareTo(cachable);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,15 @@

import lombok.Getter;

@Getter
public enum CircuitBreakerStatus {

OPEN("OPEN"),
CHECKING("CHECKING"),
REPUBLISHING("REPUBLISHING");
OPEN("OPEN"),
CLOSED("CLOSED");

@Getter
private final String value;
private final String value;

CircuitBreakerStatus(String value) {
this.value = value;
}
CircuitBreakerStatus(String value) {
this.value = value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@

import de.telekom.eni.pandora.horizon.autoconfigure.cache.CacheAutoConfiguration;
import de.telekom.eni.pandora.horizon.cache.util.Query;
import de.telekom.eni.pandora.horizon.model.meta.CircuitBreakerMessage;
import de.telekom.eni.pandora.horizon.model.meta.CircuitBreakerStatus;
import de.telekom.eni.pandora.horizon.utils.CacheServiceDummy;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
Expand All @@ -25,7 +24,7 @@ class CacheServiceTest {
@Autowired
private CacheService cacheService;

private static CircuitBreakerMessage dummy;
private static CacheServiceDummy dummy;

@BeforeAll
static void setup() {
Expand All @@ -45,17 +44,19 @@ void create() {
@DisplayName("Get from cache")
@Order(2)
void get() {
Optional<CircuitBreakerMessage> subscription = cacheService.get(dummy.getSubscriptionId());
assertTrue(subscription.isPresent());
assertEquals(dummy.getSubscriptionId(), subscription.get().getSubscriptionId());
System.out.println(cacheService.getValues().toString());

Optional<CacheServiceDummy> retrievedDummy = cacheService.get(dummy.getKey());
assertTrue(retrievedDummy.isPresent());
assertEquals(dummy.getKey(), retrievedDummy.get().getKey());
}

@Test
@DisplayName("Update cache")
@Order(3)
void update() {
assertDoesNotThrow(() -> {
dummy.setCallbackUrl("https://example.com/callback-2");
dummy.setValue("fizzbuzz");
cacheService.update(dummy);
});
}
Expand All @@ -64,31 +65,31 @@ void update() {
@DisplayName("Verify cache update")
@Order(4)
void verify() {
Optional<CircuitBreakerMessage> subscription = cacheService.get(dummy.getSubscriptionId());
Optional<CacheServiceDummy> subscription = cacheService.get(dummy.getKey());
assertTrue(subscription.isPresent());
assertEquals(dummy.getCallbackUrl(), subscription.get().getCallbackUrl());
assertEquals(dummy.getKey(), subscription.get().getKey());
}

@Test
@DisplayName("Perform SQL query")
@Order(5)
void executeQuery() {
var query = Query.builder(CircuitBreakerMessage.class).addMatchers("subscriptionId", dummy.getSubscriptionId()).build();
var expectedQuery = format("subscriptionId = %s", dummy.getSubscriptionId());
var query = Query.builder(CacheServiceDummy.class).addMatchers("value", dummy.getValue()).build();
var expectedQuery = format("value = %s", dummy.getValue());
assertEquals(expectedQuery, query.toString());

List<CircuitBreakerMessage> result = cacheService.getWithQuery(query);
List<CacheServiceDummy> result = cacheService.getWithQuery(query);
assertFalse(result.isEmpty());
assertEquals(dummy.getSubscriptionId(), result.get(0).getSubscriptionId());
assertEquals(dummy.getKey(), result.getFirst().getKey());
}

@Test
@DisplayName("Remove chache entry")
@Order(6)
void remove() {
cacheService.remove(dummy.getSubscriptionId());
cacheService.remove(dummy.getKey());

Optional<CircuitBreakerMessage> subscription = cacheService.get(dummy.getSubscriptionId());
Optional<CacheServiceDummy> subscription = cacheService.get(dummy.getKey());
assertFalse(subscription.isPresent());
}

Expand All @@ -107,7 +108,8 @@ void clear() {
assertTrue(list.isEmpty());
}

static CircuitBreakerMessage createDummy() {
return new CircuitBreakerMessage("subscription-id", CircuitBreakerStatus.OPEN, "callback-url", "environment");
static CacheServiceDummy createDummy() {
return new CacheServiceDummy("foo", "bar");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2024 Deutsche Telekom IT GmbH
//
// SPDX-License-Identifier: Apache-2.0

package de.telekom.eni.pandora.horizon.utils;

import de.telekom.eni.pandora.horizon.model.common.Cacheable;
import lombok.Getter;
import lombok.Setter;

import java.io.Serial;

@Getter
@Setter
public class CacheServiceDummy extends Cacheable {

@Serial
private static final long serialVersionUID = 1000L;

public String value;

public CacheServiceDummy(String key, String value) {
super(key);
this.value = value;
}

@Override
public String getType() {
return "cache-service";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.HazelcastJsonValue;
import com.hazelcast.map.IMap;
import de.telekom.eni.pandora.horizon.cache.service.JsonCacheService;
import de.telekom.eni.pandora.horizon.cache.listener.SubscriptionResourceEventBroadcaster;
import de.telekom.eni.pandora.horizon.cache.service.JsonCacheService;
import de.telekom.eni.pandora.horizon.kubernetes.resource.SubscriptionResource;
import de.telekom.eni.pandora.horizon.model.meta.CircuitBreakerMessage;
import de.telekom.jsonfilter.operator.Operator;
import de.telekom.jsonfilter.serde.OperatorDeserializer;
import de.telekom.jsonfilter.serde.OperatorSerializer;
Expand All @@ -26,6 +28,10 @@ public class JsonCacheAutoconfiguration {

private static final String SUBSCRIPTION_RESOURCE_V1 = "subscriptions.subscriber.horizon.telekom.de.v1";

private static final String CIRCUITBREAKER_MAP = "circuit-breakers";

private static final ObjectMapper DEFAULT_MAPPER = new ObjectMapper();

@Bean
public JsonCacheService<SubscriptionResource> subscriptionCache(HazelcastInstance hazelcastInstance, ApplicationEventPublisher applicationEventPublisher) {
var module = new SimpleModule();
Expand All @@ -40,4 +46,14 @@ public JsonCacheService<SubscriptionResource> subscriptionCache(HazelcastInstanc
return new JsonCacheService<>(SubscriptionResource.class, map, mapper);
}

@Bean
public JsonCacheService<CircuitBreakerMessage> circuitBreakerCache(HazelcastInstance hazelcastInstance) {
IMap<String, HazelcastJsonValue> map = hazelcastInstance.getMap(CIRCUITBREAKER_MAP);

var mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());

return new JsonCacheService<>(CircuitBreakerMessage.class, map, mapper);
}

}

0 comments on commit e29c015

Please sign in to comment.