use of org.apache.beam.repackaged.core.org.apache.commons.lang3.tuple.Pair in project pravega by pravega.
the class StreamTransactionMetadataTasks method createTxnBody.
/**
* Creates txn on the specified stream.
*
* Post-condition:
* 1. If txn creation succeeds, then
* (a) txn node is created in the store,
* (b) txn segments are successfully created on respective segment stores,
* (c) txn is present in the host-txn index of current host,
* (d) txn's timeout is being tracked in timeout service.
*
* 2. If process fails after creating txn node, but before responding to the client, then since txn is
* present in the host-txn index, some other controller process shall abort the txn after maxLeaseValue
*
* 3. If timeout service tracks timeout of specified txn,
* then txn is also present in the host-txn index of current process.
*
* Invariant:
* The following invariants are maintained throughout the execution of createTxn, pingTxn and sealTxn methods.
* 1. If timeout service tracks timeout of a txn, then txn is also present in the host-txn index of current process.
* 2. If txn znode is updated, then txn is also present in the host-txn index of current process.
*
* @param scope scope name.
* @param stream stream name.
* @param lease txn lease.
* @param scaleGracePeriod amount of time for which txn may remain open after scale operation is initiated.
* @param ctx context.
* @return identifier of the created txn.
*/
CompletableFuture<Pair<VersionedTransactionData, List<Segment>>> createTxnBody(final String scope, final String stream, final long lease, final long scaleGracePeriod, final OperationContext ctx) {
// Step 1. Validate parameters.
CompletableFuture<Void> validate = validate(lease, scaleGracePeriod);
long maxExecutionPeriod = Math.min(MAX_EXECUTION_TIME_MULTIPLIER * lease, Duration.ofDays(1).toMillis());
UUID txnId = UUID.randomUUID();
TxnResource resource = new TxnResource(scope, stream, txnId);
// Step 2. Add txn to host-transaction index.
CompletableFuture<Void> addIndex = validate.thenComposeAsync(ignore -> streamMetadataStore.addTxnToIndex(hostId, resource, 0), executor).whenComplete((v, e) -> {
if (e != null) {
log.debug("Txn={}, failed adding txn to host-txn index of host={}", txnId, hostId);
} else {
log.debug("Txn={}, added txn to host-txn index of host={}", txnId, hostId);
}
});
// Step 3. Create txn node in the store.
CompletableFuture<VersionedTransactionData> txnFuture = addIndex.thenComposeAsync(ignore -> streamMetadataStore.createTransaction(scope, stream, txnId, lease, maxExecutionPeriod, scaleGracePeriod, ctx, executor), executor).whenComplete((v, e) -> {
if (e != null) {
log.debug("Txn={}, failed creating txn in store", txnId);
} else {
log.debug("Txn={}, created in store", txnId);
}
});
// Step 4. Notify segment stores about new txn.
CompletableFuture<List<Segment>> segmentsFuture = txnFuture.thenComposeAsync(txnData -> streamMetadataStore.getActiveSegments(scope, stream, txnData.getEpoch(), ctx, executor), executor);
CompletableFuture<Void> notify = segmentsFuture.thenComposeAsync(activeSegments -> notifyTxnCreation(scope, stream, activeSegments, txnId), executor).whenComplete((v, e) -> log.debug("Txn={}, notified segments stores", txnId));
// Step 5. Start tracking txn in timeout service
return notify.whenCompleteAsync((result, ex) -> {
int version = 0;
long executionExpiryTime = System.currentTimeMillis() + maxExecutionPeriod;
if (!txnFuture.isCompletedExceptionally()) {
version = txnFuture.join().getVersion();
executionExpiryTime = txnFuture.join().getMaxExecutionExpiryTime();
}
timeoutService.addTxn(scope, stream, txnId, version, lease, executionExpiryTime, scaleGracePeriod);
log.debug("Txn={}, added to timeout service on host={}", txnId, hostId);
}, executor).thenApplyAsync(v -> new ImmutablePair<>(txnFuture.join(), segmentsFuture.join()), executor);
}
use of org.apache.beam.repackaged.core.org.apache.commons.lang3.tuple.Pair in project alf.io by alfio-event.
the class WaitingQueueManager method preReserveTickets.
private void preReserveTickets(Event event, int ticketsNeeded, int eventId, int alreadyReserved) {
final int toBeGenerated = Math.abs(alreadyReserved - ticketsNeeded);
EventStatisticView eventStatisticView = eventRepository.findStatisticsFor(eventId);
Map<Integer, TicketCategoryStatisticView> ticketCategoriesStats = ticketCategoryRepository.findStatisticsForEventIdByCategoryId(eventId);
List<Pair<Integer, TicketCategoryStatisticView>> collectedTickets = ticketCategoryRepository.findAllTicketCategories(eventId).stream().filter(tc -> !tc.isAccessRestricted()).sorted(Comparator.comparing(t -> t.getExpiration(event.getZoneId()))).map(tc -> Pair.of(determineAvailableSeats(ticketCategoriesStats.get(tc.getId()), eventStatisticView), ticketCategoriesStats.get(tc.getId()))).collect(new PreReservedTicketDistributor(toBeGenerated));
MapSqlParameterSource[] candidates = collectedTickets.stream().flatMap(p -> selectTicketsForPreReservation(eventId, p).stream()).map(id -> new MapSqlParameterSource().addValue("id", id)).toArray(MapSqlParameterSource[]::new);
jdbc.batchUpdate(ticketRepository.preReserveTicket(), candidates);
}
use of org.apache.beam.repackaged.core.org.apache.commons.lang3.tuple.Pair in project alf.io by alfio-event.
the class ReservationFlowIntegrationTest method checkReservationComplete.
private TicketDecorator checkReservationComplete(String eventName, String reservationIdentifier) {
Model confirmationPageModel = new BindingAwareModelMap();
String confirmationPageSuccess = reservationController.showConfirmationPage(eventName, reservationIdentifier, false, false, confirmationPageModel, Locale.ENGLISH, new MockHttpServletRequest());
assertEquals("/event/reservation-page-complete", confirmationPageSuccess);
@SuppressWarnings("unchecked") List<Pair<?, List<TicketDecorator>>> tickets = (List<Pair<?, List<TicketDecorator>>>) confirmationPageModel.asMap().get("ticketsByCategory");
assertEquals(1, tickets.size());
assertEquals(1, tickets.get(0).getRight().size());
return tickets.get(0).getRight().get(0);
}
use of org.apache.beam.repackaged.core.org.apache.commons.lang3.tuple.Pair in project alf.io by alfio-event.
the class TicketReservationManager method totalReservationCostWithVAT.
private static TotalPrice totalReservationCostWithVAT(PromoCodeDiscount promoCodeDiscount, Event event, PriceContainer.VatStatus reservationVatStatus, List<Ticket> tickets, Stream<Pair<AdditionalService, List<AdditionalServiceItem>>> additionalServiceItems) {
List<TicketPriceContainer> ticketPrices = tickets.stream().map(t -> TicketPriceContainer.from(t, reservationVatStatus, event, promoCodeDiscount)).collect(toList());
BigDecimal totalVAT = ticketPrices.stream().map(TicketPriceContainer::getVAT).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal totalDiscount = ticketPrices.stream().map(TicketPriceContainer::getAppliedDiscount).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal totalNET = ticketPrices.stream().map(TicketPriceContainer::getFinalPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
int discountedTickets = (int) ticketPrices.stream().filter(t -> t.getAppliedDiscount().compareTo(BigDecimal.ZERO) > 0).count();
int discountAppliedCount = discountedTickets <= 1 || promoCodeDiscount.getDiscountType() == DiscountType.FIXED_AMOUNT ? discountedTickets : 1;
List<AdditionalServiceItemPriceContainer> asPrices = additionalServiceItems.flatMap(generateASIPriceContainers(event, null)).collect(toList());
BigDecimal asTotalVAT = asPrices.stream().map(AdditionalServiceItemPriceContainer::getVAT).reduce(BigDecimal.ZERO, BigDecimal::add);
// FIXME discount is not applied to donations, as it wouldn't make sense. Must be implemented for #111
BigDecimal asTotalNET = asPrices.stream().map(AdditionalServiceItemPriceContainer::getFinalPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
return new TotalPrice(unitToCents(totalNET.add(asTotalNET)), unitToCents(totalVAT.add(asTotalVAT)), -(MonetaryUtil.unitToCents(totalDiscount)), discountAppliedCount);
}
use of org.apache.beam.repackaged.core.org.apache.commons.lang3.tuple.Pair in project alf.io by alfio-event.
the class TicketReservationManager method sendAssignmentReminder.
private void sendAssignmentReminder(Pair<Event, List<String>> p) {
try {
requiresNewTransactionTemplate.execute(status -> {
Event event = p.getLeft();
ZoneId eventZoneId = event.getZoneId();
int quietPeriod = configurationManager.getIntConfigValue(Configuration.from(event.getOrganizationId(), event.getId(), ConfigurationKeys.ASSIGNMENT_REMINDER_INTERVAL), 3);
p.getRight().stream().map(id -> findByIdForNotification(id, eventZoneId, quietPeriod)).filter(Optional::isPresent).map(Optional::get).forEach(reservation -> {
Map<String, Object> model = prepareModelForReservationEmail(event, reservation);
ticketReservationRepository.updateLatestReminderTimestamp(reservation.getId(), ZonedDateTime.now(eventZoneId));
Locale locale = findReservationLanguage(reservation.getId());
notificationManager.sendSimpleEmail(event, reservation.getEmail(), messageSource.getMessage("reminder.ticket-not-assigned.subject", new Object[] { event.getDisplayName() }, locale), () -> templateManager.renderTemplate(event, TemplateResource.REMINDER_TICKETS_ASSIGNMENT_EMAIL, model, locale));
});
return null;
});
} catch (Exception ex) {
log.warn("cannot send reminder message", ex);
}
}
Aggregations