package com.hubspot.blazar.data.service; import java.sql.SQLIntegrityConstraintViolationException; import java.util.Set; import javax.transaction.Transactional; import javax.ws.rs.NotFoundException; import org.skife.jdbi.v2.exceptions.UnableToExecuteStatementException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.inject.Inject; import com.hubspot.blazar.base.GitInfo; import com.hubspot.blazar.data.dao.BranchDao; public class BranchService { private static final Logger LOG = LoggerFactory.getLogger(BranchService.class); private final BranchDao branchDao; @Inject public BranchService(BranchDao branchDao) { this.branchDao = branchDao; } public Set<GitInfo> getAll() { return branchDao.getAll(); } public Set<GitInfo> getAllActive() { return branchDao.getAllActive(); } public Optional<GitInfo> get(int id) { return branchDao.get(id); } public Set<GitInfo> getByRepository(int repositoryId) { return branchDao.getByRepository(repositoryId); } public Optional<GitInfo> getByRepositoryAndBranch(int repositoryId, String branch) { return branchDao.getByRepositoryAndBranch(repositoryId, branch); } public void checkBranchExists(int branchId) { Optional<GitInfo> maybeBranch = get(branchId); if (!maybeBranch.isPresent()) { throw new NotFoundException(String.format("Could not find branch with id %d", branchId)); } } @Transactional public GitInfo upsert(GitInfo gitInfo) { Optional<GitInfo> existing = getByRepositoryAndBranch(gitInfo.getRepositoryId(), gitInfo.getBranch()); if (existing.isPresent()) { gitInfo = gitInfo.withId(existing.get().getId().get()); if (!existing.get().equals(gitInfo)) { int updated = branchDao.update(gitInfo); Preconditions.checkState(updated == 1, "Expected to update 1 row but updated %s", updated); handleConflictingBranches(gitInfo); } return gitInfo; } else { try { int id = branchDao.insert(gitInfo); handleConflictingBranches(gitInfo); return gitInfo.withId(id); } catch (UnableToExecuteStatementException e) { if (e.getCause() instanceof SQLIntegrityConstraintViolationException) { Optional<GitInfo> maybeBranch = getByRepositoryAndBranch(gitInfo.getRepositoryId(), gitInfo.getBranch()); if (!maybeBranch.isPresent()) { throw new RuntimeException(String.format("Unable to upsert gitInfo %s", gitInfo)); } return maybeBranch.get(); } else { throw e; } } } } private void handleConflictingBranches(GitInfo gitInfo) { for (GitInfo conflicting : branchDao.getConflictingBranches(gitInfo)) { LOG.warn("Found {} which conflicts with updated {} marking the former as inactive", conflicting, gitInfo); deactivate(conflicting); } } public void deactivate(GitInfo gitInfo) { branchDao.deactivate(gitInfo); } }