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

refactor: move code from manager to repository (remove template queries) #582

Merged
merged 6 commits into from
Jan 17, 2019
Merged
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
14 changes: 4 additions & 10 deletions src/main/java/alfio/manager/AdminReservationManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
import org.springframework.context.MessageSource;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
Expand Down Expand Up @@ -88,7 +87,6 @@ public class AdminReservationManager {
private final TicketReservationManager ticketReservationManager;
private final TicketCategoryRepository ticketCategoryRepository;
private final TicketRepository ticketRepository;
private final NamedParameterJdbcTemplate jdbc;
private final SpecialPriceRepository specialPriceRepository;
private final TicketReservationRepository ticketReservationRepository;
private final EventRepository eventRepository;
Expand Down Expand Up @@ -552,7 +550,7 @@ private Result<TicketCategory> checkExistingCategory(TicketsInfo ti, Event event

private void createMissingTickets(Event event, int tickets) {
final MapSqlParameterSource[] params = generateEmptyTickets(event, Date.from(ZonedDateTime.now(event.getZoneId()).toInstant()), tickets, Ticket.TicketStatus.FREE).toArray(MapSqlParameterSource[]::new);
jdbc.batchUpdate(ticketRepository.bulkTicketInitialization(), params);
ticketRepository.bulkTicketInitialization(params);
}

@Transactional
Expand Down Expand Up @@ -696,15 +694,11 @@ private void removeTicketsFromReservation(TicketReservation reservation, Event e

ticketRepository.resetCategoryIdForUnboundedCategoriesWithTicketIds(ticketIds);
ticketFieldRepository.deleteAllValuesForTicketIds(ticketIds);
MapSqlParameterSource[] args = ticketIds.stream().map(id -> new MapSqlParameterSource("ticketId", id)
.addValue("reservationId", reservationId)
.addValue("eventId", event.getId())
.addValue("newUuid", UUID.randomUUID().toString())
).toArray(MapSqlParameterSource[]::new);

List<String> reservationIds = ticketRepository.findReservationIds(ticketIds);
List<String> ticketUUIDs = ticketRepository.findUUIDs(ticketIds);
int[] results = jdbc.batchUpdate(ticketRepository.batchReleaseTickets(), args);
Validate.isTrue(Arrays.stream(results).sum() == args.length, "Failed to update tickets");
int[] results = ticketRepository.batchReleaseTickets(reservationId, ticketIds, event);
Validate.isTrue(Arrays.stream(results).sum() == ticketIds.size(), "Failed to update tickets");
if(!removeReservation) {
if(forceInvoiceReceiptUpdate) {
auditingRepository.insert(reservationId, userId, event.getId(), FORCED_UPDATE_INVOICE, date, RESERVATION, reservationId);
Expand Down
25 changes: 7 additions & 18 deletions src/main/java/alfio/manager/AdminReservationRequestManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,13 @@
import alfio.repository.AdminReservationRequestRepository;
import alfio.repository.EventRepository;
import alfio.repository.user.UserRepository;
import alfio.util.Json;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
Expand All @@ -47,7 +45,6 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static alfio.util.OptionalWrapper.optionally;
import static java.util.Collections.singletonList;
import static java.util.Optional.ofNullable;

Expand All @@ -59,7 +56,6 @@ public class AdminReservationRequestManager {

private final AdminReservationManager adminReservationManager;
private final EventManager eventManager;
private final NamedParameterJdbcTemplate jdbc;
private final UserRepository userRepository;
private final AdminReservationRequestRepository adminReservationRequestRepository;
private final EventRepository eventRepository;
Expand Down Expand Up @@ -90,6 +86,7 @@ public Result<String> scheduleReservations(String eventName,
.orElseGet(() -> Result.error(ErrorCode.ReservationError.UPDATE_FAILED));
}

//TODO: rewrite, and add test!
public Pair<Integer, Integer> processPendingReservations() {
Map<Boolean, List<MapSqlParameterSource>> result = adminReservationRequestRepository.findPendingForUpdate(1000)
.stream()
Expand All @@ -98,13 +95,13 @@ public Pair<Integer, Integer> processPendingReservations() {

Result<Triple<TicketReservation, List<Ticket>, Event>> reservationResult = Result.fromNullable(eventRepository.findOptionalById((int) request.getEventId()).orElse(null), ErrorCode.EventError.NOT_FOUND)
.flatMap(e -> Result.fromNullable(userRepository.findOptionalById((int) request.getUserId()).map(u -> Pair.of(e, u)).orElse(null), ErrorCode.EventError.ACCESS_DENIED))
.flatMap(p -> processReservation(request, p));
.flatMap(p -> processReservation(request, p.getLeft(), p.getRight()));
return buildParameterSource(id, reservationResult);
}).collect(Collectors.partitioningBy(ps -> AdminReservationRequest.Status.SUCCESS.name().equals(ps.getValue("status"))));

result.values().forEach(list -> {
try {
jdbc.batchUpdate(adminReservationRequestRepository.updateStatus(), list.toArray(new MapSqlParameterSource[0]));
adminReservationRequestRepository.updateStatus(list);
} catch(Exception e) {
log.fatal("cannot update the status of "+list.size()+" reservations", e);
}
Expand All @@ -114,14 +111,14 @@ public Pair<Integer, Integer> processPendingReservations() {

}

private Result<Triple<TicketReservation, List<Ticket>, Event>> processReservation(AdminReservationRequest request, Pair<Event, User> p) {
private Result<Triple<TicketReservation, List<Ticket>, Event>> processReservation(AdminReservationRequest request, Event event, User user) {
DefaultTransactionDefinition definition = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_NESTED);
TransactionTemplate template = new TransactionTemplate(transactionManager, definition);
return template.execute(status -> {
var savepoint = status.createSavepoint();
try {
String eventName = p.getLeft().getShortName();
String username = p.getRight().getUsername();
String eventName = event.getShortName();
String username = user.getUsername();
Result<Triple<TicketReservation, List<Ticket>, Event>> result = adminReservationManager.createReservation(request.getBody(), eventName, username)
.flatMap(r -> adminReservationManager.confirmReservation(eventName, r.getLeft().getId(), username));
if(!result.isSuccess()) {
Expand All @@ -147,15 +144,7 @@ private Result<String> insertRequest(AdminReservationModification body, EventAnd
try {
String requestId = UUID.randomUUID().toString();
long userId = userRepository.findIdByUserName(username).orElseThrow(IllegalArgumentException::new);
MapSqlParameterSource[] requests = spread(body, singleReservation)
.map(res -> new MapSqlParameterSource("userId", userId)
.addValue("requestId", requestId)
.addValue("requestType", AdminReservationRequest.RequestType.IMPORT.name())
.addValue("status", AdminReservationRequest.Status.PENDING.name())
.addValue("eventId", event.getId())
.addValue("body", Json.toJson(res)))
.toArray(MapSqlParameterSource[]::new);
jdbc.batchUpdate(adminReservationRequestRepository.insertRequest(), requests);
adminReservationRequestRepository.insertRequest(requestId, userId, event, spread(body, singleReservation));
return Result.success(requestId);
} catch (Exception e) {
log.error("can't insert reservation request", e);
Expand Down
36 changes: 9 additions & 27 deletions src/main/java/alfio/manager/EventManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
Expand Down Expand Up @@ -91,7 +90,6 @@ public class EventManager {
private final TicketRepository ticketRepository;
private final SpecialPriceRepository specialPriceRepository;
private final PromoCodeDiscountRepository promoCodeRepository;
private final NamedParameterJdbcTemplate jdbc;
private final ConfigurationManager configurationManager;
private final TicketFieldRepository ticketFieldRepository;
private final EventDeleterRepository eventDeleterRepository;
Expand Down Expand Up @@ -339,7 +337,7 @@ public void updateEventPrices(EventAndOrganizationId original, EventModification
Event modified = eventRepository.findById(eventId);
if(seatsDifference > 0) {
final MapSqlParameterSource[] params = generateEmptyTickets(modified, Date.from(ZonedDateTime.now(modified.getZoneId()).toInstant()), seatsDifference, TicketStatus.RELEASED).toArray(MapSqlParameterSource[]::new);
jdbc.batchUpdate(ticketRepository.bulkTicketInitialization(), params);
ticketRepository.bulkTicketInitialization(params);
} else {
List<Integer> ids = ticketRepository.selectNotAllocatedTicketsForUpdate(eventId, Math.abs(seatsDifference), singletonList(TicketStatus.FREE.name()));
Validate.isTrue(ids.size() == Math.abs(seatsDifference), "cannot lock enough tickets for deletion.");
Expand Down Expand Up @@ -552,8 +550,7 @@ private void createCategoriesForEvent(EventModification em, Event event) {

if (tc.isTokenGenerationRequested()) {
final TicketCategory ticketCategory = ticketCategoryRepository.getByIdAndActive(category.getKey(), event.getId());
final MapSqlParameterSource[] args = prepareTokenBulkInsertParameters(ticketCategory, ticketCategory.getMaxTickets());
jdbc.batchUpdate(specialPriceRepository.bulkInsert(), args);
specialPriceRepository.bulkInsert(ticketCategory, ticketCategory.getMaxTickets());
}
});
}
Expand All @@ -571,7 +568,7 @@ private Integer insertCategory(TicketCategoryModification tc, Event event) {
TicketCategory ticketCategory = ticketCategoryRepository.getByIdAndActive(category.getKey(), eventId);
if(tc.isBounded()) {
List<Integer> lockedTickets = ticketRepository.selectNotAllocatedTicketsForUpdate(eventId, ticketCategory.getMaxTickets(), asList(TicketStatus.FREE.name(), TicketStatus.RELEASED.name()));
jdbc.batchUpdate(ticketRepository.bulkTicketUpdate(), lockedTickets.stream().map(id -> new MapSqlParameterSource("id", id).addValue("categoryId", ticketCategory.getId()).addValue("srcPriceCts", ticketCategory.getSrcPriceCts())).toArray(MapSqlParameterSource[]::new));
ticketRepository.bulkTicketUpdate(lockedTickets, ticketCategory);
if(tc.isTokenGenerationRequested()) {
insertTokens(ticketCategory);
ticketRepository.revertToFree(eventId, ticketCategory.getId(), lockedTickets);
Expand All @@ -589,8 +586,7 @@ private void insertTokens(TicketCategory ticketCategory) {
}

private void insertTokens(TicketCategory ticketCategory, int requiredTokens) {
final MapSqlParameterSource[] args = prepareTokenBulkInsertParameters(ticketCategory, requiredTokens);
jdbc.batchUpdate(specialPriceRepository.bulkInsert(), args);
specialPriceRepository.bulkInsert(ticketCategory, requiredTokens);
}

private void insertOrUpdateTicketCategoryDescription(int tcId, TicketCategoryModification tc, Event event) {
Expand Down Expand Up @@ -672,14 +668,13 @@ void handlePriceChange(EventAndOrganizationId event, TicketCategory original, Ti
void handleTokenModification(TicketCategory original, TicketCategory updated, int addedTickets) {
if(original.isAccessRestricted() ^ updated.isAccessRestricted()) {
if(updated.isAccessRestricted()) {
final MapSqlParameterSource[] args = prepareTokenBulkInsertParameters(updated, updated.getMaxTickets());
jdbc.batchUpdate(specialPriceRepository.bulkInsert(), args);
specialPriceRepository.bulkInsert(updated, updated.getMaxTickets());
} else {
specialPriceRepository.cancelExpiredTokens(updated.getId());
}
} else if(updated.isAccessRestricted() && addedTickets != 0) {
if(addedTickets > 0) {
jdbc.batchUpdate(specialPriceRepository.bulkInsert(), prepareTokenBulkInsertParameters(updated, addedTickets));
specialPriceRepository.bulkInsert(updated, addedTickets);
} else {
int absDifference = Math.abs(addedTickets);
final List<Integer> ids = specialPriceRepository.lockNotSentTokens(updated.getId(), absDifference);
Expand All @@ -702,9 +697,7 @@ void handleTicketNumberModification(Event event, TicketCategory original, Ticket
//the updated category contains more tickets than the older one
List<Integer> lockedTickets = ticketRepository.selectNotAllocatedTicketsForUpdate(event.getId(), addedTickets, asList(TicketStatus.FREE.name(), TicketStatus.RELEASED.name()));
Validate.isTrue(addedTickets == lockedTickets.size(), "Cannot add %d tickets. There are only %d free tickets.", addedTickets, lockedTickets.size());
jdbc.batchUpdate(ticketRepository.bulkTicketUpdate(), lockedTickets.stream()
.map(id -> new MapSqlParameterSource("id", id).addValue("categoryId", updated.getId()).addValue("srcPriceCts", updated.getSrcPriceCts()))
.toArray(MapSqlParameterSource[]::new));
ticketRepository.bulkTicketUpdate(lockedTickets, updated);
if(updated.isAccessRestricted()) {
//since the updated category is not public, the tickets shouldn't be distributed to waiting people.
ticketRepository.revertToFree(event.getId(), updated.getId(), lockedTickets);
Expand All @@ -721,25 +714,14 @@ void handleTicketNumberModification(Event event, TicketCategory original, Ticket
}
ticketRepository.invalidateTickets(ids);
final MapSqlParameterSource[] params = generateEmptyTickets(event, Date.from(ZonedDateTime.now(event.getZoneId()).toInstant()), absDifference, TicketStatus.RELEASED).toArray(MapSqlParameterSource[]::new);
jdbc.batchUpdate(ticketRepository.bulkTicketInitialization(), params);
ticketRepository.bulkTicketInitialization(params);
}
}

private MapSqlParameterSource[] prepareTokenBulkInsertParameters(TicketCategory tc, int limit) {
return generateStreamForTicketCreation(limit)
.peek(ps -> {
ps.addValue("code", UUID.randomUUID().toString());
ps.addValue("priceInCents", tc.getSrcPriceCts());
ps.addValue("ticketCategoryId", tc.getId());
ps.addValue("status", SpecialPrice.Status.WAITING.name());
})
.toArray(MapSqlParameterSource[]::new);
}

private void createAllTicketsForEvent(Event event, EventModification em) {
Validate.notNull(em.getAvailableSeats());
final MapSqlParameterSource[] params = prepareTicketsBulkInsertParameters(ZonedDateTime.now(event.getZoneId()), event, em.getAvailableSeats(), TicketStatus.FREE);
jdbc.batchUpdate(ticketRepository.bulkTicketInitialization(), params);
ticketRepository.bulkTicketInitialization(params);
}

private int insertEvent(EventModification em) {
Expand Down
Loading