package com.griddynamics.jagger.jaas.storage.impl; import com.griddynamics.jagger.jaas.storage.AbstractCrudDao; import com.griddynamics.jagger.jaas.storage.TestEnvironmentDao; import com.griddynamics.jagger.jaas.storage.model.LoadScenarioEntity; import com.griddynamics.jagger.jaas.storage.model.TestEnvironmentEntity; import org.hibernate.Query; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.UUID; import static java.time.ZonedDateTime.now; import static org.apache.commons.collections.CollectionUtils.isNotEmpty; import static org.hibernate.criterion.CriteriaSpecification.DISTINCT_ROOT_ENTITY; import static org.hibernate.criterion.Projections.rowCount; /** * Hibernate based transactional implementation of {@link com.griddynamics.jagger.jaas.storage.CrudDao} interface for * {@link TestEnvironmentEntity}. */ @SuppressWarnings("unchecked") @Repository public class TestEnvironmentDaoImpl extends AbstractCrudDao<TestEnvironmentEntity, String> implements TestEnvironmentDao { @Value("${environments.ttl.minutes}") private int environmentsTtlMinutes; @Override @Transactional public TestEnvironmentEntity read(String testEnvironmentId) { return (TestEnvironmentEntity) getCurrentSession().get(TestEnvironmentEntity.class, testEnvironmentId); } @Override @Transactional public List<TestEnvironmentEntity> readAll() { return getCurrentSession().createCriteria(TestEnvironmentEntity.class).setResultTransformer(DISTINCT_ROOT_ENTITY).list(); } @Override @Transactional public void create(TestEnvironmentEntity testEnvironment) { fillLoadScenarios(testEnvironment); testEnvironment.setExpirationTimestamp(getExpirationTimestamp()); if (testEnvironment.getSessionId() == null) { testEnvironment.setSessionId(UUID.randomUUID().toString()); } if (testEnvironment.getRunningLoadScenario() != null) { Optional<LoadScenarioEntity> runningLoadScenario = testEnvironment.getLoadScenarios() .stream() .filter(loadScenarioEntity -> loadScenarioEntity.equals(testEnvironment.getRunningLoadScenario())) .findFirst(); if (runningLoadScenario.isPresent()) { // to make sure it is the same object not just equals one. testEnvironment.setRunningLoadScenario(runningLoadScenario.get()); } else { // if it is not found then add it testEnvironment.getLoadScenarios().add(testEnvironment.getRunningLoadScenario()); } } getCurrentSession().save(testEnvironment); } @Override @Transactional public void reCreate(TestEnvironmentEntity testEnvironment) { delete(testEnvironment.getEnvironmentId()); create(testEnvironment); } @Override @Transactional public void create(Iterable<TestEnvironmentEntity> testEnvironments) { Objects.requireNonNull(testEnvironments); testEnvironments.forEach(env -> getCurrentSession().save(env)); } @Override @Transactional public void update(TestEnvironmentEntity testEnvironment) { getCurrentSession().update(testEnvironment); } @Override @Transactional public void createOrUpdate(TestEnvironmentEntity testEnvironment) { getCurrentSession().saveOrUpdate(testEnvironment); } @Override @Transactional public void delete(String testEnvironmentId) { TestEnvironmentEntity testEnvironmentEntity = (TestEnvironmentEntity) getCurrentSession().get(TestEnvironmentEntity.class, testEnvironmentId); delete(testEnvironmentEntity); } @Override @Transactional public void delete(TestEnvironmentEntity testEnvironment) { getCurrentSession().delete(testEnvironment); } @Override @Transactional public void delete(Iterable<TestEnvironmentEntity> testEnvs) { testEnvs.forEach(this::delete); } @Override @Transactional public long count() { return (Long) getCurrentSession().createCriteria(TestEnvironmentEntity.class).setProjection(rowCount()).uniqueResult(); } @Override @Transactional public boolean exists(String testEnvironmentId) { Query query = getCurrentSession().createQuery("select 1 from TestEnvironmentEntity t where t.environmentId = :id"); query.setString("id", testEnvironmentId); return query.uniqueResult() != null; } @Override @Transactional public boolean existsWithSessionId(String testEnvironmentId, String sessionId) { Query query = getCurrentSession() .createQuery("select 1 from TestEnvironmentEntity t where t.environmentId = :id and t.sessionId = :sessionId" ); query.setString("id", testEnvironmentId); query.setString("sessionId", sessionId); return query.uniqueResult() != null; } @Override @Transactional public List<TestEnvironmentEntity> readExpired(long timestamp) { Query query = getCurrentSession().createQuery("select t from TestEnvironmentEntity t where t.expirationTimestamp < :timestamp"); query.setLong("timestamp", timestamp); return query.list(); } @Override @Transactional public int deleteExpired(long timestamp) { List<TestEnvironmentEntity> expiredEnvs = readExpired(timestamp); delete(expiredEnvs); return expiredEnvs.size(); } private void fillLoadScenarios(TestEnvironmentEntity testEnv) { fillLoadScenarios(testEnv, testEnv); } private void fillLoadScenarios(TestEnvironmentEntity testEnvToBeFilled, TestEnvironmentEntity testEnvToSet) { if (isNotEmpty(testEnvToBeFilled.getLoadScenarios())) testEnvToBeFilled.getLoadScenarios() .stream() .filter(suite -> suite.getTestEnvironmentEntity() == null) .forEach(suite -> suite.setTestEnvironmentEntity(testEnvToSet)); if (testEnvToBeFilled.getRunningLoadScenario() != null && testEnvToBeFilled.getRunningLoadScenario().getTestEnvironmentEntity() == null) testEnvToBeFilled.getRunningLoadScenario().setTestEnvironmentEntity(testEnvToSet); } private long getExpirationTimestamp() { return now().plusMinutes(environmentsTtlMinutes).toInstant().toEpochMilli(); } }