Skip to content

Commit

Permalink
DST-17586 Fix database transaction issues (#795)
Browse files Browse the repository at this point in the history
* DST-17586 : Transactional changes Pt1

* DST-17586 : Transactional changes Pt2

* DST-17586 : Failing tests fix

* DST-17586 : Code cleanup
  • Loading branch information
robertmccormackbconline authored Aug 2, 2024
1 parent 5fa3636 commit b65f932
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@

import uk.co.bconline.ndelius.model.entity.ProbationAreaUserEntity;

import java.util.List;

public interface ProbationAreaUserRepository extends JpaRepository<ProbationAreaUserEntity, Long> {
List<ProbationAreaUserEntity> findProbationAreaUserEntitiesByUserId(Long id);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@

import uk.co.bconline.ndelius.model.entity.StaffTeamEntity;

import java.util.List;

public interface StaffTeamRepository extends JpaRepository<StaffTeamEntity, Long> {
List<StaffTeamEntity> findStaffTeamEntitiesByStaffId(long staffId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@
import uk.co.bconline.ndelius.model.entity.StaffEntity;
import uk.co.bconline.ndelius.model.entity.UserEntity;
import uk.co.bconline.ndelius.model.entity.export.UserExportEntity;
import uk.co.bconline.ndelius.repository.db.*;
import uk.co.bconline.ndelius.repository.db.ChangeNoteRepository;
import uk.co.bconline.ndelius.repository.db.ProbationAreaUserRepository;
import uk.co.bconline.ndelius.repository.db.SearchResultRepository;
import uk.co.bconline.ndelius.repository.db.StaffRepository;
import uk.co.bconline.ndelius.repository.db.StaffTeamRepository;
import uk.co.bconline.ndelius.repository.db.UserEntityRepository;
import uk.co.bconline.ndelius.service.UserEntityService;
import uk.co.bconline.ndelius.transformer.SearchResultTransformer;
import uk.co.bconline.ndelius.util.SearchUtils;
Expand All @@ -25,14 +30,18 @@
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;

import static java.time.LocalDate.now;
import static java.time.temporal.ChronoUnit.DAYS;
import static java.time.temporal.ChronoUnit.MILLIS;
import static java.util.Collections.singleton;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.*;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.groupingByConcurrent;
import static java.util.stream.Collectors.reducing;
import static java.util.stream.Collectors.toList;
import static org.springframework.util.CollectionUtils.isEmpty;
import static uk.co.bconline.ndelius.util.AuthUtils.myUsername;

Expand Down Expand Up @@ -150,29 +159,43 @@ public UserEntity save(UserEntity user) {
// Staff/Teams
ofNullable(user.getStaff()).ifPresent(staff -> {
log.debug("Retrieving existing staff");
ofNullable(staff.getId()).flatMap(staffRepository::findById).ifPresent(existingStaff -> {
ofNullable(staff.getId()).flatMap(staffRepository::findById).ifPresentOrElse(existingStaff -> {
log.debug("Unlinking any other users with the same staff code");
unlinkOtherUsersFromStaff(user, existingStaff);
log.debug("Deleting team links");
staffTeamRepository.deleteAll(existingStaff.getTeamLinks());
val allTeamEntities = staffTeamRepository.findStaffTeamEntitiesByStaffId(existingStaff.getId());
staffTeamRepository.deleteAll(allTeamEntities);
log.debug("Saving team links");
staffTeamRepository.saveAll(staff.getTeamLinks());
log.debug("Saving staff");
staffRepository.save(staff);
},
() -> {
log.debug("Saving staff");
staffRepository.save(staff);
log.debug("Saving team links");
staffTeamRepository.saveAll(staff.getTeamLinks());
});
log.debug("Saving staff");
staffRepository.save(staff);
log.debug("Saving team links");
staffTeamRepository.saveAll(staff.getTeamLinks());
});

// User/Datasets
log.debug("Retrieving existing user");
ofNullable(user.getId()).flatMap(repository::findById).ifPresent(existingUser -> {
val savedUser = ofNullable(user.getId()).flatMap(repository::findById).map(existingUser -> {
handlePreviousStaffRecord(user.getStaff(), existingUser.getStaff());
log.debug("Deleting datasets");
probationAreaUserRepository.deleteAll(existingUser.getProbationAreaLinks());
val allDataSets = probationAreaUserRepository.findProbationAreaUserEntitiesByUserId(user.getId());
probationAreaUserRepository.deleteAll(allDataSets);
log.debug("Saving new datasets");
probationAreaUserRepository.saveAll(user.getProbationAreaLinks());
log.debug("Saving user");
return repository.save(user);
}).orElseGet( () -> {
log.debug("Saving user");
val userEntity = repository.save(user);
log.debug("Saving new datasets");
probationAreaUserRepository.saveAll(user.getProbationAreaLinks());
return userEntity;
});
log.debug("Saving user");
val savedUser = repository.save(user);
log.debug("Saving new datasets");
probationAreaUserRepository.saveAll(user.getProbationAreaLinks());
log.debug("Updating user history");
changeNoteRepository.saveAll(user.getHistory());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,37 +184,31 @@ public Optional<User> getUserByStaffCode(String staffCode) {

@Override
public void addUser(User user) {
val dbFuture = runAsync(() -> userEntityService.save(transformer.mapToUserEntity(user, new UserEntity())), taskExecutor);
val ldapFuture = runAsync(() -> userEntryService.save(transformer.mapToUserEntry(user, new UserEntry())), taskExecutor);

try {
allOf(dbFuture, ldapFuture).join();
} catch (CancellationException | CompletionException e) {
userEntityService.save(transformer.mapToUserEntity(user, new UserEntity()));
userEntryService.save(transformer.mapToUserEntry(user, new UserEntry()));
} catch (Exception e) {
throw new AppException(String.format("Unable to create user (%s)", getMostSpecificCause(e).getMessage()), e);
}
}

@Override
public void updateUser(User user) {
val existingHomeArea = userEntryService.getUserHomeArea(user.getExistingUsername());
val dbFuture = runAsync(() -> {

try {
log.debug("Fetching existing DB value");
val existingUser = userEntityService.getUser(user.getExistingUsername()).orElse(new UserEntity());
val existingDBUser = userEntityService.getUser(user.getExistingUsername()).orElse(new UserEntity());
log.debug("Transforming into DB user");
val updatedUser = transformer.mapToUserEntity(user, existingUser, existingHomeArea);
userEntityService.save(updatedUser);
}, taskExecutor);
val ldapFuture = runAsync(() -> {
val updatedDBUser = transformer.mapToUserEntity(user, existingDBUser, existingHomeArea);
userEntityService.save(updatedDBUser);

log.debug("Fetching existing LDAP value");
val existingUser = userEntryService.getUser(user.getExistingUsername()).orElse(new UserEntry());
val existingLDAPUser = userEntryService.getUser(user.getExistingUsername()).orElse(new UserEntry());
log.debug("Transforming into LDAP user");
val updatedUser = transformer.mapToUserEntry(user, existingUser);
userEntryService.save(user.getExistingUsername(), updatedUser);
}, taskExecutor);

try {
allOf(dbFuture, ldapFuture).join();
} catch (CancellationException | CompletionException e) {
val updatedLDAPUser = transformer.mapToUserEntry(user, existingLDAPUser);
userEntryService.save(user.getExistingUsername(), updatedLDAPUser);
} catch (Exception e) {
throw new AppException(String.format("Unable to update user (%s)", getMostSpecificCause(e).getMessage()), e);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,6 @@ public UserEntity mapToUserEntity(User user, UserEntity existingUser, String exi
entity.getProbationAreaLinks().addAll(Stream
.concat(user.getDatasets().stream(),
ofNullable(user.getEstablishments()).map(List::stream).orElseGet(Stream::empty))
.parallel()
.map(dataset -> datasetService.getDatasetId(dataset.getCode()).orElse(null))
.filter(Objects::nonNull)
.map(ProbationAreaEntity::new)
Expand Down Expand Up @@ -296,7 +295,7 @@ public StaffEntity mapToStaffEntity(User user, StaffEntity existingStaff, String
.updatedById(myUserId)
.build();
entity.getTeamLinks().clear();
entity.getTeamLinks().addAll(ofNullable(user.getTeams()).map(list -> list.parallelStream()
entity.getTeamLinks().addAll(ofNullable(user.getTeams()).map(list -> list.stream()
.map(team -> teamService.getTeamId(team.getCode()).orElse(null))
.filter(Objects::nonNull)
.map(id -> StaffTeamEntity.builder()
Expand Down

0 comments on commit b65f932

Please sign in to comment.