package com.yammer.breakerbox.azure.model;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Optional;
import com.microsoft.windowsazure.services.table.client.TableServiceEntity;
import com.yammer.breakerbox.azure.core.AzureTableName;
import com.yammer.breakerbox.azure.core.TableId;
import com.yammer.breakerbox.azure.core.TableKey;
import com.yammer.breakerbox.azure.core.TableType;
import com.yammer.breakerbox.store.DependencyId;
import com.yammer.breakerbox.store.ServiceId;
import com.yammer.tenacity.core.config.TenacityConfiguration;
import io.dropwizard.jackson.Jackson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;
/**
* Bean to represent the Dependency table.
* This is for looking up time-based configurations on a per-key basis. It is assumed that you know which
* Dependency Key you wish to use before accessing this table.
*/
public class DependencyEntity extends TableType implements TableKey {
private static final ObjectMapper OBJECTMAPPER = Jackson.newObjectMapper();
private static final Validator VALIDATOR = Validation.buildDefaultValidatorFactory().getValidator();
private static final Logger LOGGER = LoggerFactory.getLogger(ServiceEntity.class);
private String tenacityConfigurationAsString;
private String user;
private String serviceName;
private DependencyEntity(DependencyId dependencyId,
long timeStamp,
String userName,
String configuration,
ServiceId serviceId) {
super(TableId.DEPENDENCY);
this.partitionKey = dependencyId.getId();
this.rowKey = String.valueOf(timeStamp);
this.tenacityConfigurationAsString = configuration;
this.user = userName;
this.serviceName = serviceId.getId();
}
public static DependencyEntity build(DependencyId dependencyId,
String username,
TenacityConfiguration tenacityConfiguration,
ServiceId serviceId) {
return build(dependencyId, System.currentTimeMillis(), username, tenacityConfiguration, serviceId);
}
public static DependencyEntity build(DependencyId dependencyId,
long timeStamp,
String userName,
TenacityConfiguration configuration,
ServiceId serviceId) {
try {
final String configurationAsString = OBJECTMAPPER.writeValueAsString(configuration);
return new DependencyEntity(dependencyId, timeStamp, userName, configurationAsString, serviceId);
} catch (JsonProcessingException err) {
LOGGER.warn("Could not convert TenacityConfiguration to json", err);
throw new RuntimeException(err);
}
}
public Optional<TenacityConfiguration> getConfiguration() {
try {
final TenacityConfiguration dependencyConfiguration = OBJECTMAPPER.readValue(tenacityConfigurationAsString, TenacityConfiguration.class);
final Set<?> validationErrors = VALIDATOR.validate(dependencyConfiguration);
if (!validationErrors.isEmpty()) {
LOGGER.warn("Failed to validate TenacityConfiguration", validationErrors.toString());
}
return Optional.of(dependencyConfiguration);
} catch (Exception err) {
LOGGER.warn("Failed to parse TenacityConfiguration", err);
}
return Optional.absent();
}
public long getConfigurationTimestamp() {
return Long.parseLong(rowKey);
}
public static TenacityConfiguration defaultConfiguration() {
return new TenacityConfiguration();
}
public ServiceId getServiceId() {
return ServiceId.from(serviceName);
}
public DependencyId getDependencyId() {
return DependencyId.from(partitionKey);
}
@Override
public Class<? extends TableServiceEntity> getEntityClass() {
return DependencyEntity.class;
}
@Override
public AzureTableName getTable() {
return TableId.DEPENDENCY;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
DependencyEntity that = (DependencyEntity) o;
if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) return false;
if (tenacityConfigurationAsString != null ? !tenacityConfigurationAsString.equals(that.tenacityConfigurationAsString) : that.tenacityConfigurationAsString != null)
return false;
if (user != null ? !user.equals(that.user) : that.user != null) return false;
return true;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (tenacityConfigurationAsString != null ? tenacityConfigurationAsString.hashCode() : 0);
result = 31 * result + (user != null ? user.hashCode() : 0);
result = 31 * result + (serviceName != null ? serviceName.hashCode() : 0);
return result;
}
/**
* @deprecated kept for backward compatibility
* For Azure bean serialization via reflection
*/
@Deprecated
public DependencyEntity() {
super(TableId.DEPENDENCY);
}
/**
* @deprecated kept for backward compatibility
* @return
*/
@Deprecated
public String getTenacityConfigurationAsString() {
return tenacityConfigurationAsString;
}
/**
* @deprecated kept for backward compatibility
* @param tenacityConfigurationAsString
*/
@Deprecated
public void setTenacityConfigurationAsString(String tenacityConfigurationAsString) {
this.tenacityConfigurationAsString = tenacityConfigurationAsString;
}
/**
* @deprecated kept for backward compatibility
* @return
*/
@Deprecated
public String getServiceName() {
return serviceName;
}
/**
* @deprecated kept for backward compatibility
* @param serviceName
*/
@Deprecated
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
/**
* Getter for user field.
* NOTE: This method is exposed, but is also used for bean serialization. Don't remove this.
*/
public String getUser() {
return user;
}
/**
* @deprecated kept for backward compatibility
* @param user
*/
@Deprecated
public void setUser(String user) {
this.user = user;
}
}