Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat : handle transactions effectively #396

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,8 @@ public interface UserSchemeDetailsEntityRepository extends JpaRepository<UserSch
where u.userFolioDetailsEntity.userCasDetailsEntity.investorInfoEntity.email = :email and
u.userFolioDetailsEntity.userCasDetailsEntity.investorInfoEntity.name = :name
""")
@Transactional(readOnly = true)
List<UserSchemeDetailsEntity> findByUserEmailAndName(@Param("email") String email, @Param("name") String name);

@Transactional(readOnly = true)
Optional<SchemeNameAndISIN> findFirstByAmfi(Long amfi);

@Query(
Expand All @@ -43,6 +41,5 @@ select mf_scheme_id, count(msn.id) from public.user_scheme_details usd join mf_s
group by mf_scheme_id having count(msn.id) < 3
""",
nativeQuery = true)
@Transactional(readOnly = true)
List<Long> getHistoricalDataNotLoadedSchemeIdList();
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Loggable
@Transactional(readOnly = true)
public class CachedNavService {

private static final Logger LOGGER = LoggerFactory.getLogger(CachedNavService.class);
Expand All @@ -21,8 +23,12 @@ public CachedNavService(SchemeService schemeService) {
this.schemeService = schemeService;
}

@Cacheable(cacheNames = "getNavForDate", unless = "#result == null")
@Loggable(result = false)
@Cacheable(
value = "getNavForDate",
key =
"#root.targetClass.simpleName + ':' + #root.methodName + ':schemeCode:' + #schemeCode + ':navDate:' + #navDate",
unless = "#result == null")
public MFSchemeDTO getNavForDate(Long schemeCode, LocalDate navDate) {
LOGGER.info("Fetching Nav for AMFISchemeCode: {} for date: {} from Database", schemeCode, navDate);
return schemeService
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
public class CapitalGainsService {

private static final double MIN_OPEN_BALANCE = 0.01;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
public class FIFOUnitsService {

private static final Logger LOGGER = LoggerFactory.getLogger(FIFOUnitsService.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
public class GainEntryService {

private final Map<String, BigDecimal> CII = loadCostInflationIndexData();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestClient;
import org.springframework.web.util.UriComponentsBuilder;

@Service
@Loggable
@Transactional(readOnly = true)
public class HistoricalNavService {

private static final Logger LOGGER = LoggerFactory.getLogger(HistoricalNavService.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,31 @@
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.Assert;

@Service
@Loggable
@Transactional(readOnly = true)
public class MFSchemeNavService {

private static final Logger LOGGER = LoggerFactory.getLogger(MFSchemeNavService.class);

private final MFSchemeNavEntityRepository mfSchemeNavEntityRepository;
private final MFSchemeRepository mfSchemeRepository;
private final ResourceLoader resourceLoader;
private final TransactionTemplate transactionTemplate;

public MFSchemeNavService(
MFSchemeNavEntityRepository mfSchemeNavEntityRepository,
MFSchemeRepository mfSchemeRepository,
ResourceLoader resourceLoader) {
ResourceLoader resourceLoader,
TransactionTemplate transactionTemplate) {
this.mfSchemeNavEntityRepository = mfSchemeNavEntityRepository;
this.mfSchemeRepository = mfSchemeRepository;
this.resourceLoader = resourceLoader;
transactionTemplate.setPropagationBehaviorName("PROPAGATION_REQUIRES_NEW");
this.transactionTemplate = transactionTemplate;
}

public void loadHistoricalNavOn31Jan2018ForExistingSchemes() {
Expand All @@ -61,7 +68,9 @@ public void loadHistoricalNavOn31Jan2018ForExistingSchemes() {
return mfSchemeNavEntity;
})
.toList();
List<MFSchemeNavEntity> persistedEntities = mfSchemeNavEntityRepository.saveAll(mfSchemeNavEntities);
List<MFSchemeNavEntity> persistedEntities =
transactionTemplate.execute(status -> mfSchemeNavEntityRepository.saveAll(mfSchemeNavEntities));
Assert.notNull(persistedEntities, () -> "persistedEntities cant be null");
LOGGER.info("Persisted : {} rows", persistedEntities.size());
} catch (IOException e) {
throw new FileNotFoundException(e.getMessage());
Expand All @@ -70,12 +79,10 @@ public void loadHistoricalNavOn31Jan2018ForExistingSchemes() {
}
}

@Transactional(readOnly = true)
public boolean navLoadedFor31Jan2018ForExistingSchemes() {
return mfSchemeNavEntityRepository.countByNavDate(AppConstants.GRAND_FATHERED_DATE) >= 5908;
}

@Transactional(readOnly = true)
public boolean navLoadedForClosedOrMergedSchemes() {
return mfSchemeNavEntityRepository.countByNavDate(AppConstants.GRAND_FATHERED_DATE) >= 9000;
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/learning/mfscreener/service/NavService.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

@Service
@Loggable
@Transactional(readOnly = true)
public class NavService {

private static final Logger LOGGER = LoggerFactory.getLogger(NavService.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

@Service
@Loggable
@Transactional(readOnly = true)
public class PortfolioService {

private static final Logger LOGGER = LoggerFactory.getLogger(PortfolioService.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Loggable
@Transactional(readOnly = true)
public class PortfolioServiceHelper {

private static final Logger LOGGER = LoggerFactory.getLogger(PortfolioServiceHelper.class);
Expand Down Expand Up @@ -45,10 +47,11 @@ public <T> List<T> joinFutures(List<CompletableFuture<T>> futures) {
}

public List<PortfolioDetailsDTO> getPortfolioDetailsByPANAndAsOfDate(String panNumber, LocalDate asOfDate) {
return joinFutures(userCASDetailsService.getPortfolioDetailsByPanAndAsOfDate(panNumber, asOfDate).stream()
.map(portfolioDetails -> CompletableFuture.supplyAsync(() -> {
return userCASDetailsService.getPortfolioDetailsByPanAndAsOfDate(panNumber, asOfDate).stream()
.map(portfolioDetails -> {
MFSchemeDTO scheme;
try {
LOGGER.debug("fetching Nav for SchemeId :{}", portfolioDetails.getSchemeId());
scheme = navService.getNavByDateWithRetry(portfolioDetails.getSchemeId(), asOfDate);
} catch (NavNotFoundException navNotFoundException) {
// Will happen in case of NFO where units are allocated but not ready for subscription
Expand All @@ -67,8 +70,8 @@ public List<PortfolioDetailsDTO> getPortfolioDetailsByPANAndAsOfDate(String panN
scheme.date(),
xIRRCalculatorService.calculateXIRRBySchemeId(
portfolioDetails.getSchemeId(), portfolioDetails.getSchemeDetailId(), asOfDate));
}))
.toList());
})
.toList();
}

public long countTransactionsByUserFolioDTOList(List<UserFolioDTO> folioDTOList) {
Expand Down
22 changes: 7 additions & 15 deletions src/main/java/com/learning/mfscreener/service/SchemeService.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatusCode;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.Assert;
Expand All @@ -38,6 +39,7 @@

@Service
@Loggable
@Transactional(readOnly = true)
public class SchemeService {

private static final Logger LOGGER = LoggerFactory.getLogger(SchemeService.class);
Expand Down Expand Up @@ -68,14 +70,10 @@ public SchemeService(
this.transactionTemplate = transactionTemplate;
}

@Loggable
@Transactional
public void fetchSchemeDetails(Long schemeCode) {
processResponseEntity(schemeCode, getNavResponseResponseEntity(schemeCode));
}

@Loggable
@Transactional
public void fetchSchemeDetails(String oldSchemeCode, Long newSchemeCode) {
processResponseEntity(newSchemeCode, getNavResponseResponseEntity(Long.valueOf(oldSchemeCode)));
}
Expand All @@ -95,13 +93,12 @@ public List<FundDetailProjection> fetchSchemesByFundName(String fundName) {
}

// if panKYC is NOT OK then PAN is not set. hence manually setting it.
@Loggable
public void setPANIfNotSet(Long userCasID) {
// find pan by id
UserFolioDetailsPanProjection panProjection =
userFolioDetailsService.findFirstByUserCasIdAndPanKyc(userCasID, "OK");
int rowsUpdated = userFolioDetailsService.updatePanByCasId(panProjection.getPan(), userCasID);
LOGGER.debug("Updated {} rows with PAN", rowsUpdated);
LOGGER.debug("Updated {} rows with PAN for casID :{}", rowsUpdated, userCasID);
}

@Loggable(result = false)
Expand Down Expand Up @@ -157,7 +154,7 @@ void mergeList(NavResponse navResponse, MFSchemeEntity mfSchemeEntity, Long sche
mfSchemeEntity.addSchemeNav(newSchemeNav);
}
try {
this.mfSchemeRepository.save(mfSchemeEntity);
transactionTemplate.executeWithoutResult(status -> this.mfSchemeRepository.save(mfSchemeEntity));
} catch (ConstraintViolationException | DataIntegrityViolationException exception) {
LOGGER.error("ConstraintViolationException or DataIntegrityViolationException ", exception);
}
Expand All @@ -167,42 +164,37 @@ void mergeList(NavResponse navResponse, MFSchemeEntity mfSchemeEntity, Long sche
}
}

@Transactional(readOnly = true)
public Optional<MFSchemeEntity> findByPayOut(String isin) {
return mfSchemeRepository.findByPayOut(isin);
}

@Cacheable(value = "schemeIdByISIN")
@Transactional(readOnly = true)
public List<Long> getSchemeIdByISIN(String isin) {
return mfSchemeRepository.getSchemeIdByISIN(isin);
}

@Transactional
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Loggable(result = false, params = false)
public MFSchemeEntity saveEntity(MFSchemeEntity mfSchemeEntity) {
return mfSchemeRepository.save(mfSchemeEntity);
}

@Transactional(readOnly = true)
@Loggable(result = false)
public Optional<MFSchemeEntity> findBySchemeCode(Long schemeCode) {
return mfSchemeRepository.findBySchemeId(schemeCode);
}

@Transactional(readOnly = true)
public long count() {
return mfSchemeRepository.count();
}

@Transactional(readOnly = true)
@Loggable(result = false)
public List<Long> findAllSchemeIds() {
return mfSchemeRepository.findAllSchemeIds();
}

@Transactional
@Loggable(result = false, params = false)
@Transactional
public List<MFSchemeEntity> saveAllEntities(List<MFSchemeEntity> mfSchemeEntityList) {
return mfSchemeRepository.saveAll(mfSchemeEntityList);
}
Expand Down Expand Up @@ -243,7 +235,7 @@ public void loadHistoricalDataForClosedOrMergedSchemes() {
.toList();
List<MFSchemeEntity> persistedEntities =
transactionTemplate.execute(status -> mfSchemeRepository.saveAll(mfSchemeEntities));
Assert.notEmpty(persistedEntities, () -> "Response cant be empty");
Assert.notNull(persistedEntities, () -> "persistedEntities cant be null");
LOGGER.info("Persisted : {} rows", persistedEntities.size());
} catch (IOException e) {
throw new FileNotFoundException(e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.time.LocalDate;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Loggable
Expand All @@ -20,7 +21,7 @@ public UserCASDetailsService(UserCASDetailsEntityRepository userCASDetailsEntity
this.userCASDetailsEntityRepository = userCASDetailsEntityRepository;
}

@Transactional
@Transactional(propagation = Propagation.REQUIRES_NEW)
public UserCASDetailsEntity saveEntity(UserCASDetailsEntity casDetailsEntity) {
return userCASDetailsEntityRepository.save(casDetailsEntity);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.time.LocalDate;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
Expand All @@ -33,7 +34,7 @@ public UserFolioDetailsPanProjection findFirstByUserCasIdAndPanKyc(Long userCasI
return userFolioDetailsEntityRepository.findFirstByUserCasDetailsEntity_IdAndPanKyc(userCasID, ok);
}

@Transactional
@Transactional(propagation = Propagation.REQUIRES_NEW)
public int updatePanByCasId(String pan, Long userCasID) {
return userFolioDetailsEntityRepository.updatePanByCasId(pan, userCasID);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Loggable
@Transactional(readOnly = true)
public class XIRRCalculatorService {

private static final Logger LOGGER = LoggerFactory.getLogger(XIRRCalculatorService.class);
Expand Down
Loading
Loading