Skip to content

Commit

Permalink
#677 - changed timestamp spread approach. fixed defects in repository…
Browse files Browse the repository at this point in the history
… queries. fixed failure in address checking.
  • Loading branch information
petmongrels committed Feb 21, 2024
1 parent 684a7a0 commit f36369a
Show file tree
Hide file tree
Showing 18 changed files with 44 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ default void setChangedForSync(Individual individual) {
}

@Modifying
@Query(value = "update checklist_item e set is_voided = true, last_modified_date_time = (current_timestamp + e.id * (interval '1 millisecond')/1000), last_modified_by_id = :lastModifiedById " +
"from individual i, program_enrolment pe, checklist c" +
" where i.id = pe.individual_id and c.id = e.checklist_id and i.id = pe.individual_id and i.address_id = :addressId and e.is_voided = false", nativeQuery = true)
@Query(value = "update checklist_item e set is_voided = true, last_modified_date_time = (current_timestamp + random() * 5000 * (interval '1 millisecond')), last_modified_by_id = :lastModifiedById " +
"from individual i, program_enrolment enrolment, checklist c" +
" where i.id = enrolment.individual_id and enrolment.id = c.program_enrolment_id and c.id = e.checklist_id and i.address_id = :addressId and e.is_voided = false", nativeQuery = true)
void voidSubjectItemsAt(Long addressId, Long lastModifiedById);
default void voidSubjectItemsAt(AddressLevel address) {
this.voidSubjectItemsAt(address.getId(), UserContextHolder.getUserId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ default void setChangedForSync(Individual individual) {
}

@Modifying
@Query(value = "update checklist e set is_voided = true, last_modified_date_time = (current_timestamp + e.id * (interval '1 millisecond')/1000), last_modified_by_id = :lastModifiedById " +
"from individual i, program_enrolment pe" +
" where i.id = pe.individual_id and i.address_id = :addressId and i.id = pe.individual_id and e.is_voided = false", nativeQuery = true)
@Query(value = "update checklist e set is_voided = true, last_modified_date_time = (current_timestamp + random() * 5000 * (interval '1 millisecond')), last_modified_by_id = :lastModifiedById " +
"from individual i, program_enrolment enrolment" +
" where i.id = enrolment.individual_id and i.address_id = :addressId and enrolment.id = e.program_enrolment_id and e.is_voided = false", nativeQuery = true)
void voidSubjectItemsAt(Long addressId, Long lastModifiedById);
default void voidSubjectItemsAt(AddressLevel address) {
this.voidSubjectItemsAt(address.getId(), UserContextHolder.getUserId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ default boolean isEntityChanged(SyncParameters syncParameters){
}

@Modifying
@Query(value = "update comment e set is_voided = true, last_modified_date_time = (current_timestamp + e.id * (interval '1 millisecond')/1000), last_modified_by_id = :lastModifiedById " +
@Query(value = "update comment e set is_voided = true, last_modified_date_time = (current_timestamp + random() * 5000 * (interval '1 millisecond')), last_modified_by_id = :lastModifiedById " +
"from individual i" +
" where i.address_id = :addressId and i.id = e.subject_id and e.is_voided = false", nativeQuery = true)
void voidSubjectItemsAt(Long addressId, Long lastModifiedById);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package org.avni.server.dao;

import org.avni.server.domain.AddressLevel;
import org.avni.server.domain.Comment;
import org.avni.server.domain.CommentThread;
import org.avni.server.domain.Individual;
import org.avni.server.framework.security.UserContextHolder;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.stereotype.Repository;

Expand All @@ -13,7 +17,7 @@

@Repository
@RepositoryRestResource(collectionResourceRel = "commentThread", path = "commentThread", exported = false)
public interface CommentThreadRepository extends TransactionalDataRepository<CommentThread>, FindByLastModifiedDateTime<CommentThread>, OperatingIndividualScopeAwareRepository<CommentThread> {
public interface CommentThreadRepository extends TransactionalDataRepository<CommentThread>, FindByLastModifiedDateTime<CommentThread>, OperatingIndividualScopeAwareRepository<CommentThread>, SubjectTreeItemRepository {

default Specification<CommentThread> syncStrategySpecification(SyncParameters syncParameters) {
return (Root<CommentThread> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
Expand All @@ -34,4 +38,13 @@ default boolean isEntityChanged(SyncParameters syncParameters){
}

List<CommentThread> findDistinctByIsVoidedFalseAndCommentsIsVoidedFalseAndComments_SubjectOrderByOpenDateTimeDescIdDesc(Individual subject);

@Modifying
@Query(value = "update comment_thread e set is_voided = true, last_modified_date_time = (current_timestamp + random() * 5000 * (interval '1 millisecond')), last_modified_by_id = :lastModifiedById " +
"from individual i, comment c" +
" where c.subject_id = i.id and i.address_id = :addressId and e.id = c.comment_thread_id and e.is_voided = false", nativeQuery = true)
void voidSubjectItemsAt(Long addressId, Long lastModifiedById);
default void voidSubjectItemsAt(AddressLevel address) {
this.voidSubjectItemsAt(address.getId(), UserContextHolder.getUserId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ default void updateConceptSyncAttributesForSubjectType(Long subjectTypeId, Strin
}

@Modifying
@Query(value = "update encounter e set is_voided = true, last_modified_date_time = (current_timestamp + e.id * (interval '1 millisecond')/1000), last_modified_by_id = :lastModifiedById " +
@Query(value = "update encounter e set is_voided = true, last_modified_date_time = (current_timestamp + random() * 5000 * (interval '1 millisecond')), last_modified_by_id = :lastModifiedById " +
"from individual i" +
" where i.address_id = :addressId and i.id = e.individual_id and e.is_voided = false", nativeQuery = true)
void voidSubjectItemsAt(Long addressId, Long lastModifiedById);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ default EntityApprovalStatus saveEAS(EntityApprovalStatus entityToSave) {
}

@Modifying
@Query(value = "update entity_approval_status e set is_voided = true, last_modified_date_time = (current_timestamp + e.id * (interval '1 millisecond')/1000), last_modified_by_id = :lastModifiedById " +
@Query(value = "update entity_approval_status e set is_voided = true, last_modified_date_time = (current_timestamp + random() * 5000 * (interval '1 millisecond')), last_modified_by_id = :lastModifiedById " +
"from individual i" +
" where i.address_id = :addressId and i.id = e.individual_id and e.is_voided = false", nativeQuery = true)
void voidSubjectsAt(Long addressId, Long lastModifiedById);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ default void updateConceptSyncAttributesForSubjectType(Long subjectTypeId, Strin
}

@Modifying
@Query(value = "update group_subject e set is_voided = true, last_modified_date_time = (current_timestamp + e.id * (interval '1 millisecond')/1000), last_modified_by_id = :lastModifiedById " +
@Query(value = "update group_subject e set is_voided = true, last_modified_date_time = (current_timestamp + random() * 5000 * (interval '1 millisecond')), last_modified_by_id = :lastModifiedById " +
"from individual i" +
" where i.address_id = :addressId and (i.id = e.group_subject_id or i.id = e.member_subject_id) and e.is_voided = false", nativeQuery = true)
void voidSubjectItemsAt(Long addressId, Long lastModifiedById);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ default Individual getSubject(String uuid, String legacyId) {
}

@Modifying
@Query(value = "update individual i set is_voided = true, last_modified_date_time = (current_timestamp + i.id * (interval '1 millisecond')/1000), last_modified_by_id = :lastModifiedById where i.address_id = :addressId and i.is_voided = false", nativeQuery = true)
@Query(value = "update individual i set is_voided = true, last_modified_date_time = (current_timestamp + random() * 5000 * (interval '1 millisecond')), last_modified_by_id = :lastModifiedById where i.address_id = :addressId and i.is_voided = false", nativeQuery = true)
void voidSubjectItemsAt(Long addressId, Long lastModifiedById);
default void voidSubjectItemsAt(AddressLevel address) {
this.voidSubjectItemsAt(address.getId(), UserContextHolder.getUserId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,9 @@ public SearchParams(Date lastModifiedDateTime, Date now, Map<Concept, String> co
}

@Modifying
@Query(value = "update program_encounter e set is_voided = true, last_modified_date_time = (current_timestamp + e.id * (interval '1 millisecond')/1000), last_modified_by_id = :lastModifiedById " +
"from individual i, program_enrolment pe" +
" where i.id = pe.individual_id and i.address_id = :addressId and i.id = pe.individual_id and e.is_voided = false", nativeQuery = true)
@Query(value = "update program_encounter e set is_voided = true, last_modified_date_time = (current_timestamp + random() * 5000 * (interval '1 millisecond')), last_modified_by_id = :lastModifiedById " +
"from individual i, program_enrolment enrolment" +
" where i.id = enrolment.individual_id and i.address_id = :addressId and enrolment.id = e.program_enrolment_id and e.is_voided = false", nativeQuery = true)
void voidSubjectItemsAt(Long addressId, Long lastModifiedById);
default void voidSubjectItemsAt(AddressLevel address) {
this.voidSubjectItemsAt(address.getId(), UserContextHolder.getUserId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ default void updateConceptSyncAttributesForSubjectType(Long subjectTypeId, Strin
}

@Modifying
@Query(value = "update program_enrolment e set is_voided = true, last_modified_date_time = (current_timestamp + e.id * (interval '1 millisecond')/1000), last_modified_by_id = :lastModifiedById " +
@Query(value = "update program_enrolment e set is_voided = true, last_modified_date_time = (current_timestamp + random() * 5000 * (interval '1 millisecond')), last_modified_by_id = :lastModifiedById " +
"from individual i" +
" where i.address_id = :addressId and i.id = e.individual_id and e.is_voided = false", nativeQuery = true)
void voidSubjectItemsAt(Long addressId, Long lastModifiedById);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ default boolean isEntityChanged(SyncParameters syncParameters) {
}

@Modifying
@Query(value = "update subject_migration e set is_voided = true, last_modified_date_time = (current_timestamp + e.id * (interval '1 millisecond')/1000), last_modified_by_id = :lastModifiedById " +
@Query(value = "update subject_migration e set is_voided = true, last_modified_date_time = (current_timestamp + random() * 5000 * (interval '1 millisecond')), last_modified_by_id = :lastModifiedById " +
"from individual i" +
" where i.address_id = :addressId and i.id = e.individual_id and e.is_voided = false", nativeQuery = true)
void voidSubjectItemsAt(Long addressId, Long lastModifiedById);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,10 @@ default User getUser(String userId) {

@Query(value = "select (count(p.id) > 0) as exists from group_privilege\n" +
" join privilege p on group_privilege.privilege_id = p.id\n" +
" join groups on group_privilege.group_id = groups.id\n" +
" join user_group ug on groups.id = ug.group_id\n" +
" join groups on group_privilege.group_id = groups.id and groups.is_voided = false\n" +
" join user_group ug on groups.id = ug.group_id and ug.is_voided = false\n" +
" join users on ug.user_id = users.id\n" +
"where p.type = :type and users.id = :userId and group_privilege.allow", nativeQuery = true)
"where p.type = :type and users.id = :userId and group_privilege.allow and group_privilege.is_voided = false", nativeQuery = true)
boolean hasPrivilege(String type, long userId);

@Query(value = "select bool_or(groups.has_all_privileges) from users\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ default void setChangedForSync(Individual individual) {
}

@Modifying
@Query(value = "update individual_relationship e set is_voided = true, last_modified_date_time = (current_timestamp + e.id * (interval '1 millisecond')/1000), last_modified_by_id = :lastModifiedById " +
@Query(value = "update individual_relationship e set is_voided = true, last_modified_date_time = (current_timestamp + random() * 5000 * (interval '1 millisecond')), last_modified_by_id = :lastModifiedById " +
" from individual i" +
" where i.address_id = :addressId and (i.id = e.individual_a_id or i.id = e.individual_b_id) and e.is_voided = false", nativeQuery = true)
void voidSubjectItemsAt(Long addressId, Long lastModifiedById);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ default boolean isEntityChanged(SyncParameters syncParameters) {
}

@Modifying
@Query(value = "update subject_program_eligibility e set is_voided = true, last_modified_date_time = (current_timestamp + e.id * (interval '1 millisecond')/1000), last_modified_by_id = :lastModifiedById " +
@Query(value = "update subject_program_eligibility e set is_voided = true, last_modified_date_time = (current_timestamp + random() * 5000 * (interval '1 millisecond')), last_modified_by_id = :lastModifiedById " +
"from individual i" +
" where i.address_id = :addressId and i.id = e.subject_id and e.is_voided = false", nativeQuery = true)
void voidSubjectItemsAt(Long addressId, Long lastModifiedById);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import org.avni.server.web.request.*;
import org.avni.server.web.request.api.RequestUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -57,9 +59,10 @@ public class IndividualService implements ScopeAwareService<Individual> {
private final AccessControlService accessControlService;

private final List<SubjectTreeItemRepository> subjectTreeItemRepositories;
private static final Logger logger = LoggerFactory.getLogger(IndividualService.class);

@Autowired
public IndividualService(IndividualRepository individualRepository, ObservationService observationService, GroupSubjectRepository groupSubjectRepository, ConceptRepository conceptRepository, GroupRoleRepository groupRoleRepository, SubjectTypeRepository subjectTypeRepository, EncounterRepository encounterRepository, ProgramEncounterRepository programEncounterRepository, AddressLevelService addressLevelService, ConceptService conceptService, AccessControlService accessControlService, ProgramEnrolmentRepository programEnrolmentRepository, ChecklistRepository checklistRepository, ChecklistItemRepository checklistItemRepository, SubjectMigrationRepository subjectMigrationRepository, IndividualRelationshipRepository individualRelationshipRepository, CommentRepository commentRepository, EntityApprovalStatusRepository entityApprovalStatusRepository, SubjectProgramEligibilityRepository subjectProgramEligibilityRepository) {
public IndividualService(IndividualRepository individualRepository, ObservationService observationService, GroupSubjectRepository groupSubjectRepository, ConceptRepository conceptRepository, GroupRoleRepository groupRoleRepository, SubjectTypeRepository subjectTypeRepository, EncounterRepository encounterRepository, ProgramEncounterRepository programEncounterRepository, AddressLevelService addressLevelService, ConceptService conceptService, AccessControlService accessControlService, ProgramEnrolmentRepository programEnrolmentRepository, ChecklistRepository checklistRepository, ChecklistItemRepository checklistItemRepository, SubjectMigrationRepository subjectMigrationRepository, IndividualRelationshipRepository individualRelationshipRepository, CommentRepository commentRepository, EntityApprovalStatusRepository entityApprovalStatusRepository, SubjectProgramEligibilityRepository subjectProgramEligibilityRepository, CommentThreadRepository commentThreadRepository) {
this.individualRepository = individualRepository;
this.observationService = observationService;
this.groupSubjectRepository = groupSubjectRepository;
Expand All @@ -74,7 +77,7 @@ public IndividualService(IndividualRepository individualRepository, ObservationS
this.accessControlService = accessControlService;
this.objectMapper = ObjectMapperSingleton.getObjectMapper();

subjectTreeItemRepositories = Arrays.asList(individualRepository, encounterRepository, programEnrolmentRepository, programEncounterRepository, checklistItemRepository, checklistRepository, entityApprovalStatusRepository, subjectProgramEligibilityRepository, subjectMigrationRepository, individualRelationshipRepository, commentRepository, groupSubjectRepository);
subjectTreeItemRepositories = Arrays.asList(individualRepository, encounterRepository, programEnrolmentRepository, programEncounterRepository, checklistItemRepository, checklistRepository, entityApprovalStatusRepository, subjectProgramEligibilityRepository, subjectMigrationRepository, individualRelationshipRepository, commentRepository, groupSubjectRepository, commentThreadRepository);
}

public Individual findByUuid(String uuid) {
Expand Down Expand Up @@ -467,6 +470,7 @@ public Optional<Individual> findByPhoneNumber(String phoneNumber) {
@Transactional
public void voidSubjectsTree(AddressLevel address) {
subjectTreeItemRepositories.forEach(subjectTreeItemRepository -> {
logger.info(String.format("Voiding subject tree item for address {%d, %s}", address.getId(), address.getTitle()));
subjectTreeItemRepository.voidSubjectItemsAt(address);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ public DeleteSubjectsResponse deleteSubjectTree(@RequestBody DeleteSubjectCriter
accessControlService.checkPrivilege(PrivilegeType.MultiTxEntityTypeUpdate);
DeleteSubjectsResponse deleteSubjectsResponse = new DeleteSubjectsResponse();
for (Long addressId : deleteSubjectCriteria.getAddressIds()) {
AddressLevel addressLevel = locationRepository.findById(addressId).orElseGet(null);
AddressLevel addressLevel = locationRepository.findEntity(addressId);
if (addressLevel == null)
deleteSubjectsResponse.addNotFoundAddress(addressId);
else {
Expand Down
2 changes: 1 addition & 1 deletion avni-server-api/src/main/resources/api/external-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1140,7 +1140,7 @@ paths:
delete:
tags:
- Subject, Subject Migration, Program Encounter, Program Enrolment, Encounter, Group Subject
summary: Void Subjects and its descendants that match the criteria provided. It currently supports taking id of locations. All subject and descendants belonging to that location will get voided.
summary: Void Subjects and its descendants that match the criteria provided. It currently supports taking id of locations. All subject and descendants belonging to that location will get voided. This API should not be used to update more than 10,000 records of each entity type.
parameters:
- name: auth-token
in: header
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class IndividualServiceTest {
public void setUp() throws Exception {
initMocks(this);
individualService = new IndividualService(individualRepository,
null, null, null, null, null, encounterRepository, programEncounterRepository, null, null, null, programEnrolmentRepository, null, null, null, null, null, null, null);
null, null, null, null, null, encounterRepository, programEncounterRepository, null, null, null, programEnrolmentRepository, null, null, null, null, null, null, null, null);
}

@Test
Expand Down

0 comments on commit f36369a

Please sign in to comment.