Skip to content

Commit

Permalink
rework storage entirely. Fixes #118 (#119)
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Graff committed Nov 3, 2017
1 parent f47dcb4 commit ac902ae
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.netflix.kayenta.memory.storage.MemoryStorageService;
import com.netflix.kayenta.security.AccountCredentials;
import com.netflix.kayenta.security.AccountCredentialsRepository;
import com.netflix.kayenta.storage.ObjectType;
import com.netflix.kayenta.storage.StorageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
Expand All @@ -32,6 +33,8 @@
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Configuration
@EnableConfigurationProperties
Expand All @@ -53,7 +56,6 @@ StorageService storageService(MemoryConfigurationProperties memoryConfigurationP

for (MemoryManagedAccount memoryManagedAccount : memoryConfigurationProperties.getAccounts()) {
String name = memoryManagedAccount.getName();
String namespace = memoryManagedAccount.getNamespace();
List<AccountCredentials.Type> supportedTypes = memoryManagedAccount.getSupportedTypes();

log.info("Registering Memory account {} with supported types {}.", name, supportedTypes);
Expand All @@ -62,13 +64,18 @@ StorageService storageService(MemoryConfigurationProperties memoryConfigurationP
MemoryNamedAccountCredentials.MemoryNamedAccountCredentialsBuilder memoryNamedAccountCredentialsBuilder =
MemoryNamedAccountCredentials.builder()
.name(name)
.namespace(namespace)
.credentials(memoryAccountCredentials);

if (!CollectionUtils.isEmpty(supportedTypes)) {
memoryNamedAccountCredentialsBuilder.supportedTypes(supportedTypes);
}

// Set up the data maps for this in-memory storage account
Map<ObjectType, Map<String, Object>> objectStorage = new ConcurrentHashMap<>();
memoryNamedAccountCredentialsBuilder.objects(objectStorage);
Map<ObjectType, Map<String, Map<String, Object>>> metadataStorage = new ConcurrentHashMap<>();
memoryNamedAccountCredentialsBuilder.metadata(metadataStorage);

MemoryNamedAccountCredentials memoryNamedAccountCredentials = memoryNamedAccountCredentialsBuilder.build();
accountCredentialsRepository.save(name, memoryNamedAccountCredentials);
memoryStorageServiceBuilder.accountName(name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,5 @@ public class MemoryManagedAccount {
@NotNull
private String name;

private String namespace;

private List<AccountCredentials.Type> supportedTypes;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
package com.netflix.kayenta.memory.security;

import com.netflix.kayenta.security.AccountCredentials;
import com.netflix.kayenta.storage.ObjectType;
import lombok.Builder;
import lombok.Data;
import lombok.Singular;

import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;

@Builder
@Data
Expand All @@ -39,7 +41,10 @@ public class MemoryNamedAccountCredentials implements AccountCredentials<MemoryA
private MemoryAccountCredentials credentials;

@NotNull
private String namespace;
private Map<ObjectType, Map<String, Object>> objects;

@NotNull
private Map<ObjectType, Map<String, Map<String, Object>>> metadata;

@Override
public String getType() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import lombok.Builder;
import lombok.Getter;
import lombok.Singular;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import javax.validation.constraints.NotNull;
Expand All @@ -37,14 +36,7 @@
import java.util.concurrent.ConcurrentHashMap;

@Builder
@Slf4j
public class MemoryStorageService implements StorageService {

public static class MemoryStorageServiceBuilder {
private Map<String, Object> entries = new ConcurrentHashMap<>();
private Map<String, Map<String, Object>> entryMetadata = new ConcurrentHashMap<>();
}

@NotNull
@Singular
@Getter
Expand All @@ -53,31 +45,35 @@ public static class MemoryStorageServiceBuilder {
@Autowired
AccountCredentialsRepository accountCredentialsRepository;

private Map<String, Object> entries;
private Map<String, Map<String, Object>> entryMetadata;

@Override
public boolean servicesAccount(String accountName) {
return accountNames.contains(accountName);
}

private MemoryNamedAccountCredentials getCredentials(String accountName, ObjectType objectType) {
MemoryNamedAccountCredentials credentials = (MemoryNamedAccountCredentials)accountCredentialsRepository
.getOne(accountName)
.orElseThrow(() -> new IllegalArgumentException("Unable to resolve account " + accountName + "."));
credentials.getObjects().putIfAbsent(objectType, new ConcurrentHashMap<>());
credentials.getMetadata().putIfAbsent(objectType, new ConcurrentHashMap<>());
return credentials;
}

@Override
public <T> T loadObject(String accountName, ObjectType objectType, String objectKey) throws IllegalArgumentException {
String key = makeKey(accountName, objectType, objectKey);
log.info("Getting object type {}, key {}", objectType.toString(), key);
Object entry = entries.get(key);
MemoryNamedAccountCredentials credentials = getCredentials(accountName, objectType);
Object entry = credentials.getObjects().get(objectType).get(objectKey);

if (entry == null) {
throw new IllegalArgumentException("No such object named " + key);
throw new IllegalArgumentException("No such object named " + objectKey);
}

return (T)entry;
}

@Override
public <T> void storeObject(String accountName, ObjectType objectType, String objectKey, T obj, String filename, boolean isAnUpdate) {
String key = makeKey(accountName, objectType, objectKey);
log.info("Writing key {}", key);
MemoryNamedAccountCredentials credentials = getCredentials(accountName, objectType);

long currentTimestamp = System.currentTimeMillis();
Map<String, Object> objectMetadataMap = new HashMap<>();
Expand All @@ -94,8 +90,8 @@ public <T> void storeObject(String accountName, ObjectType objectType, String ob
objectMetadataMap.put("applications", canaryConfig.getApplications());
}

entries.put(key, obj);
entryMetadata.put(key, objectMetadataMap);
credentials.getObjects().get(objectType).put(objectKey, obj);
credentials.getMetadata().get(objectType).put(objectKey, objectMetadataMap);
}

private void checkForDuplicateCanaryConfig(String accountName, ObjectType objectType, CanaryConfig canaryConfig, String canaryConfigId) {
Expand All @@ -116,51 +112,40 @@ private void checkForDuplicateCanaryConfig(String accountName, ObjectType object

@Override
public void deleteObject(String accountName, ObjectType objectType, String objectKey) {
String key = makeKey(accountName, objectType, objectKey);
log.info("Deleting key {}", key);
Object oldValue = entries.remove(key);
entryMetadata.remove(key);
MemoryNamedAccountCredentials credentials = getCredentials(accountName, objectType);

Object oldValue = credentials.getObjects().get(objectType).remove(objectKey);
credentials.getMetadata().get(objectType).remove(objectKey);

if (oldValue == null) {
log.error("Object named {} does not exist", key);
throw new IllegalArgumentException("Does not exist");
}
}

@Override
public List<Map<String, Object>> listObjectKeys(String accountName, ObjectType objectType, List<String> applications, boolean skipIndex) {
MemoryNamedAccountCredentials credentials = getCredentials(accountName, objectType);

boolean filterOnApplications = applications != null && applications.size() > 0;
List<Map<String, Object>> result = new ArrayList<>();

for (Map.Entry<String, Object> entry : entries.entrySet()) {
for (Map.Entry<String, Object> entry : credentials.getObjects().get(objectType).entrySet()) {
String entryKey = entry.getKey();
if (objectType == ObjectType.CANARY_CONFIG) {
if (filterOnApplications) {
CanaryConfig canaryConfig = (CanaryConfig)entry.getValue();

if (CanaryConfigIndex.haveCommonElements(applications, canaryConfig.getApplications())) {
result.add(entryMetadata.get(entry.getKey()));
result.add(credentials.getMetadata().get(objectType).get(entryKey));
}
} else {
result.add(entryMetadata.get(entry.getKey()));
result.add(credentials.getMetadata().get(objectType).get(entryKey));
}
} else {
result.add(entryMetadata.get(entry.getKey()));
result.add(credentials.getMetadata().get(objectType).get(entryKey));
}
}

return result;
}

private String makePrefix(String accountName, ObjectType objectType) {
MemoryNamedAccountCredentials credentials = (MemoryNamedAccountCredentials) accountCredentialsRepository
.getOne(accountName)
.orElseThrow(() -> new IllegalArgumentException("Unable to resolve account " + accountName + "."));
String namespace = credentials.getNamespace();
String typename = objectType.toString();
return namespace + ":" + typename + ":";
}

private String makeKey(String accountName, ObjectType objectType, String objectKey) {
return makePrefix(accountName, objectType) + objectKey;
}
}

0 comments on commit ac902ae

Please sign in to comment.