From 086a68d86ab65e4eb20f96a99f853291c84a4331 Mon Sep 17 00:00:00 2001 From: batalin Date: Tue, 29 Oct 2019 17:35:28 +0200 Subject: [PATCH 1/3] Just for code review (BULK). This code contains error. --- .../offer/PostgresOfferRepositoryImpl.kt | 62 ++++++++++++++++++- .../bitclave/node/services/v1/OfferService.kt | 6 +- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/bitclave/node/repository/offer/PostgresOfferRepositoryImpl.kt b/src/main/kotlin/com/bitclave/node/repository/offer/PostgresOfferRepositoryImpl.kt index d06735ff..cd7a227f 100644 --- a/src/main/kotlin/com/bitclave/node/repository/offer/PostgresOfferRepositoryImpl.kt +++ b/src/main/kotlin/com/bitclave/node/repository/offer/PostgresOfferRepositoryImpl.kt @@ -21,6 +21,7 @@ import org.springframework.data.domain.SliceImpl import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Component import java.math.BigInteger +import java.text.SimpleDateFormat import java.util.HashMap import javax.persistence.EntityManager import kotlin.system.measureTimeMillis @@ -31,7 +32,8 @@ class PostgresOfferRepositoryImpl( val repository: OfferCrudRepository, val offerSearchRepository: OfferSearchCrudRepository, val entityManager: EntityManager, - val wsService: WsService + val wsService: WsService, + val em: EntityManager ) : OfferRepository { override fun saveOffer(offer: Offer): Offer { @@ -46,7 +48,61 @@ class PostgresOfferRepositoryImpl( } override fun saveAll(offers: List): List { - val result = repository.saveAll(offers).toList() + // native spring implementation + // val result = repository.saveAll(offers).toList() + // return syncElementCollections(result) + + var result: List = listOf() + val offersForInserting = offers.filter { it.id == 0L } + + val insertedOffersValues = offersForInserting.map { + val isoPattern = "yyyy-MM-dd'T'HH:mm:ss'Z'" + val updatedAt = SimpleDateFormat(isoPattern).format(it.updatedAt) + val createdAt = SimpleDateFormat(isoPattern).format(it.createdAt) + "(nextval('offer_id_seq')," + + " '${it.title}', '${it.description}', '${it.owner}', " + + "'${it.imageUrl}', '${it.worth}', '$createdAt', '$updatedAt')" + } + if (insertedOffersValues.isNotEmpty()) { + val springQueryTiming = measureTimeMillis { + // create offers + val insertOffers = "INSERT INTO offer " + + "(id, title, description, owner, image_url, worth, created_at, updated_at) VALUES \n" + val insertOffersQuery = insertOffers + insertedOffersValues.joinToString(",\n") + + "\n RETURNING id;" + val createdOfferIds: List = em.createNativeQuery(insertOffersQuery).resultList as List +// println("result: $createdOfferIds") + + // create tags + val insertTags = "INSERT INTO offer_tags (offer_id, tags, tags_key) VALUES \n" + val insertedOfferTagsValues = offersForInserting.mapIndexed { index, offer -> + offer.tags.map { "( ${createdOfferIds[index]}, '${it.value}', '${it.key}' )" } + }.flatten().joinToString(",\n") + val insertOfferTagsQuery = insertTags + insertedOfferTagsValues + em.createNativeQuery(insertOfferTagsQuery).executeUpdate() + + // compare + val insertCompare = "INSERT INTO offer_compare (offer_id, compare, compare_key) VALUES \n" + val insertedOfferCompareValues = offersForInserting.mapIndexed { index, offer -> + offer.compare.map { "( ${createdOfferIds[index]}, '${it.value}', '${it.key}' )" } + }.flatten().joinToString(",\n") + val insertOfferCompareQuery = insertCompare + insertedOfferCompareValues + em.createNativeQuery(insertOfferCompareQuery).executeUpdate() + + // rules + val insertRules = "INSERT INTO offer_rules (offer_id, rules, rules_key) VALUES \n" + val insertedOfferRulesValues = offersForInserting.mapIndexed { index, offer -> + offer.rules.map { "( ${createdOfferIds[index]}, ${it.value.ordinal}, '${it.key}' )" } + }.flatten().joinToString(",\n") + val insertOfferRulesQuery = insertRules + insertedOfferRulesValues + em.createNativeQuery(insertOfferRulesQuery).executeUpdate() + + val ids = createdOfferIds.joinToString(", ") + val query = "SELECT * FROM offer WHERE offer.id IN ($ids)" + result = em.createNativeQuery(query, Offer::class.java).resultList as List + } + println(" -- save all (native query) timing $springQueryTiming") + } return syncElementCollections(result) } @@ -68,7 +124,7 @@ class PostgresOfferRepositoryImpl( override fun deleteOffers(owner: String): Int { val deletedOffers = repository.deleteByOwner(owner) deletedOffers.forEach { - wsService.sendEvent(OfferEvent.OnDelete, it.id) +// wsService.sendEvent(OfferEvent.OnDelete, it.id) } return deletedOffers.size diff --git a/src/main/kotlin/com/bitclave/node/services/v1/OfferService.kt b/src/main/kotlin/com/bitclave/node/services/v1/OfferService.kt index 9b820632..c4a79be1 100644 --- a/src/main/kotlin/com/bitclave/node/services/v1/OfferService.kt +++ b/src/main/kotlin/com/bitclave/node/services/v1/OfferService.kt @@ -141,7 +141,7 @@ class OfferService( val saveAllTiming = measureTimeMillis { result = offerRepository.changeStrategy(strategy).saveAll(readyForSaveOffers) } -// logger.debug(" - save all timing $saveAllTiming") + Logger.debug(" - save all timing $saveAllTiming") val prices = result.mapIndexed { index, offer -> readyForSaveOffers[index].offerPrices.map { offerPrice -> @@ -154,7 +154,7 @@ class OfferService( val saveAllPricesTiming = measureTimeMillis { offerPriceRepository.changeStrategy(strategy).saveAllPrices(prices) } -// logger.debug(" - save all prices timing $saveAllPricesTiming") + Logger.debug(" - save all prices timing $saveAllPricesTiming") val offersIdsForCleanupOfferSearches = offers.filter { it.id != 0L }.map { it.id } val deleteOfferSearchTiming = measureTimeMillis { @@ -162,7 +162,7 @@ class OfferService( offerSearchService.deleteByOfferIds(offersIdsForCleanupOfferSearches, strategy) } } -// logger.debug(" - delete all offer searches by offerId timing $deleteOfferSearchTiming") + Logger.debug(" - delete all offer searches by offerId timing $deleteOfferSearchTiming") result.map { it.id } }) From f54d21dc0a9eb70c427c43bb3d26784e3b01c47a Mon Sep 17 00:00:00 2001 From: batalin Date: Wed, 30 Oct 2019 17:39:49 +0200 Subject: [PATCH 2/3] update code ready for testing --- .../dev/VerifyConsistencyController.kt | 2 +- .../offer/PostgresOfferRepositoryImpl.kt | 50 +++++++++++++------ 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/main/kotlin/com/bitclave/node/controllers/dev/VerifyConsistencyController.kt b/src/main/kotlin/com/bitclave/node/controllers/dev/VerifyConsistencyController.kt index 6efbe0e7..65bcba71 100644 --- a/src/main/kotlin/com/bitclave/node/controllers/dev/VerifyConsistencyController.kt +++ b/src/main/kotlin/com/bitclave/node/controllers/dev/VerifyConsistencyController.kt @@ -455,7 +455,7 @@ class VerifyConsistencyController( .thenCompose { offerSearchService.getOfferInteractionsByOfferIdsAndOwners( request.data!!.offerIds, - request.data!!.owners, + request.data.owners, getStrategyType(strategy) ) }.exceptionally { e -> diff --git a/src/main/kotlin/com/bitclave/node/repository/offer/PostgresOfferRepositoryImpl.kt b/src/main/kotlin/com/bitclave/node/repository/offer/PostgresOfferRepositoryImpl.kt index cd7a227f..d6871cf5 100644 --- a/src/main/kotlin/com/bitclave/node/repository/offer/PostgresOfferRepositoryImpl.kt +++ b/src/main/kotlin/com/bitclave/node/repository/offer/PostgresOfferRepositoryImpl.kt @@ -24,6 +24,7 @@ import java.math.BigInteger import java.text.SimpleDateFormat import java.util.HashMap import javax.persistence.EntityManager +import org.springframework.transaction.annotation.Transactional import kotlin.system.measureTimeMillis @Component @@ -32,8 +33,7 @@ class PostgresOfferRepositoryImpl( val repository: OfferCrudRepository, val offerSearchRepository: OfferSearchCrudRepository, val entityManager: EntityManager, - val wsService: WsService, - val em: EntityManager + val wsService: WsService ) : OfferRepository { override fun saveOffer(offer: Offer): Offer { @@ -46,21 +46,34 @@ class PostgresOfferRepositoryImpl( return result } - + @Transactional override fun saveAll(offers: List): List { // native spring implementation // val result = repository.saveAll(offers).toList() // return syncElementCollections(result) var result: List = listOf() - val offersForInserting = offers.filter { it.id == 0L } + // prepare for delete + val offerForDeletion = offers.filter { it.id != 0L } + if (offerForDeletion.isNotEmpty()) { + val ids = offerForDeletion.joinToString(", ") + var query = "DELETE FROM offer where offer.id IN ($ids)" + entityManager.createNativeQuery(query) .executeUpdate() + query = "DELETE FROM offer_tags where offer_tags.offer_id IN ($ids)" + entityManager.createNativeQuery(query).executeUpdate() + query = "DELETE FROM offer_compare where offer_compare.offer.id IN ($ids)" + entityManager.createNativeQuery(query).executeUpdate() + query = "DELETE FROM offer_rules where offer_rules.offer.id IN ($ids)" + entityManager.createNativeQuery(query).executeUpdate() + } - val insertedOffersValues = offersForInserting.map { + val insertedOffersValues = offers.map { val isoPattern = "yyyy-MM-dd'T'HH:mm:ss'Z'" val updatedAt = SimpleDateFormat(isoPattern).format(it.updatedAt) val createdAt = SimpleDateFormat(isoPattern).format(it.createdAt) - "(nextval('offer_id_seq')," + - " '${it.title}', '${it.description}', '${it.owner}', " + + val id = if (it.id == 0L) "(nextval('offer_id_seq')," else it.id.toString() + + "$id, '${it.title}', '${it.description}', '${it.owner}', " + "'${it.imageUrl}', '${it.worth}', '$createdAt', '$updatedAt')" } if (insertedOffersValues.isNotEmpty()) { @@ -70,36 +83,41 @@ class PostgresOfferRepositoryImpl( "(id, title, description, owner, image_url, worth, created_at, updated_at) VALUES \n" val insertOffersQuery = insertOffers + insertedOffersValues.joinToString(",\n") + "\n RETURNING id;" - val createdOfferIds: List = em.createNativeQuery(insertOffersQuery).resultList as List -// println("result: $createdOfferIds") + + @Suppress("UNCHECKED_CAST") + val createdOfferIds: List = entityManager + .createNativeQuery(insertOffersQuery) + .resultList as List + println("result: $createdOfferIds") // create tags val insertTags = "INSERT INTO offer_tags (offer_id, tags, tags_key) VALUES \n" - val insertedOfferTagsValues = offersForInserting.mapIndexed { index, offer -> + val insertedOfferTagsValues = offers.mapIndexed { index, offer -> offer.tags.map { "( ${createdOfferIds[index]}, '${it.value}', '${it.key}' )" } }.flatten().joinToString(",\n") val insertOfferTagsQuery = insertTags + insertedOfferTagsValues - em.createNativeQuery(insertOfferTagsQuery).executeUpdate() + entityManager.createNativeQuery(insertOfferTagsQuery).executeUpdate() // compare val insertCompare = "INSERT INTO offer_compare (offer_id, compare, compare_key) VALUES \n" - val insertedOfferCompareValues = offersForInserting.mapIndexed { index, offer -> + val insertedOfferCompareValues = offers.mapIndexed { index, offer -> offer.compare.map { "( ${createdOfferIds[index]}, '${it.value}', '${it.key}' )" } }.flatten().joinToString(",\n") val insertOfferCompareQuery = insertCompare + insertedOfferCompareValues - em.createNativeQuery(insertOfferCompareQuery).executeUpdate() + entityManager.createNativeQuery(insertOfferCompareQuery).executeUpdate() // rules val insertRules = "INSERT INTO offer_rules (offer_id, rules, rules_key) VALUES \n" - val insertedOfferRulesValues = offersForInserting.mapIndexed { index, offer -> + val insertedOfferRulesValues = offers.mapIndexed { index, offer -> offer.rules.map { "( ${createdOfferIds[index]}, ${it.value.ordinal}, '${it.key}' )" } }.flatten().joinToString(",\n") val insertOfferRulesQuery = insertRules + insertedOfferRulesValues - em.createNativeQuery(insertOfferRulesQuery).executeUpdate() + entityManager.createNativeQuery(insertOfferRulesQuery).executeUpdate() val ids = createdOfferIds.joinToString(", ") val query = "SELECT * FROM offer WHERE offer.id IN ($ids)" - result = em.createNativeQuery(query, Offer::class.java).resultList as List + @Suppress("UNCHECKED_CAST") + result = entityManager.createNativeQuery(query, Offer::class.java).resultList as List } println(" -- save all (native query) timing $springQueryTiming") } From 4988e08f8dda4cac17ca0e063fe06c69fab5271b Mon Sep 17 00:00:00 2001 From: batalin Date: Fri, 1 Nov 2019 14:16:50 +0200 Subject: [PATCH 3/3] attempt to delete for update --- .../offer/PostgresOfferRepositoryImpl.kt | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/com/bitclave/node/repository/offer/PostgresOfferRepositoryImpl.kt b/src/main/kotlin/com/bitclave/node/repository/offer/PostgresOfferRepositoryImpl.kt index d6871cf5..05fa98cd 100644 --- a/src/main/kotlin/com/bitclave/node/repository/offer/PostgresOfferRepositoryImpl.kt +++ b/src/main/kotlin/com/bitclave/node/repository/offer/PostgresOfferRepositoryImpl.kt @@ -56,14 +56,24 @@ class PostgresOfferRepositoryImpl( // prepare for delete val offerForDeletion = offers.filter { it.id != 0L } if (offerForDeletion.isNotEmpty()) { - val ids = offerForDeletion.joinToString(", ") - var query = "DELETE FROM offer where offer.id IN ($ids)" - entityManager.createNativeQuery(query) .executeUpdate() - query = "DELETE FROM offer_tags where offer_tags.offer_id IN ($ids)" + val ids = offerForDeletion.map { it.id }.joinToString(", ") + + var query = "DELETE FROM offer_tags where offer_tags.offer_id IN ($ids)" + entityManager.createNativeQuery(query).executeUpdate() + query = "DELETE FROM offer_compare where offer_compare.offer_id IN ($ids)" entityManager.createNativeQuery(query).executeUpdate() - query = "DELETE FROM offer_compare where offer_compare.offer.id IN ($ids)" + query = "DELETE FROM offer_rules where offer_rules.offer_id IN ($ids)" entityManager.createNativeQuery(query).executeUpdate() - query = "DELETE FROM offer_rules where offer_rules.offer.id IN ($ids)" + + // delete price rules + query = "SELECT id FROM offer_price WHERE offer_price.offer_id IN ($ids)" + @Suppress("UNCHECKED_CAST") + var offerPriceIdsForDeletion = entityManager.createNativeQuery(query).resultList as List + query = "SELECT id" + + // delete price + + query = "DELETE FROM offer where offer.id IN ($ids)" entityManager.createNativeQuery(query).executeUpdate() } @@ -71,7 +81,7 @@ class PostgresOfferRepositoryImpl( val isoPattern = "yyyy-MM-dd'T'HH:mm:ss'Z'" val updatedAt = SimpleDateFormat(isoPattern).format(it.updatedAt) val createdAt = SimpleDateFormat(isoPattern).format(it.createdAt) - val id = if (it.id == 0L) "(nextval('offer_id_seq')," else it.id.toString() + val id = if (it.id == 0L) "(nextval('offer_id_seq')" else it.id.toString() "$id, '${it.title}', '${it.description}', '${it.owner}', " + "'${it.imageUrl}', '${it.worth}', '$createdAt', '$updatedAt')"