Skip to content

Commit 131872c

Browse files
committed
fix: improve ticket csv serializer performance
fix: improve ticket repository performance remove not needed extra joins fix: set fetchJoinCollection to false for ticket repo fix: get always owner to avoid N+1 on ticket repository fix: improve get tickets generic pagination
1 parent 34fed2a commit 131872c

File tree

9 files changed

+343
-60
lines changed

9 files changed

+343
-60
lines changed

app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitTicketApiController.php

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
use models\exceptions\ValidationException;
2727
use models\oauth2\IResourceServerContext;
2828
use models\summit\IOrderConstants;
29+
use models\summit\ISummitAttendeeRepository;
2930
use models\summit\ISummitAttendeeTicketRepository;
3031
use models\summit\ISummitRepository;
3132
use models\summit\Summit;
@@ -71,16 +72,20 @@ public function getChildSerializer()
7172
*/
7273
private $service;
7374

75+
private $attendee_repository;
76+
7477
/**
7578
* OAuth2SummitTicketApiController constructor.
7679
* @param ISummitRepository $summit_repository
80+
* @param ISummitAttendeeRepository $attendee_repository,
7781
* @param ISummitAttendeeTicketRepository $repository
7882
* @param ISummitOrderService $service
7983
* @param IResourceServerContext $resource_server_context
8084
*/
8185
public function __construct
8286
(
8387
ISummitRepository $summit_repository,
88+
ISummitAttendeeRepository $attendee_repository,
8489
ISummitAttendeeTicketRepository $repository,
8590
ISummitOrderService $service,
8691
IResourceServerContext $resource_server_context
@@ -89,6 +94,7 @@ public function __construct
8994
parent::__construct($resource_server_context);
9095
$this->repository = $repository;
9196
$this->summit_repository = $summit_repository;
97+
$this->attendee_repository = $attendee_repository;
9298
$this->service = $service;
9399
}
94100

@@ -274,7 +280,7 @@ public function getAllBySummitCSV($summit_id)
274280
{
275281
$summit = SummitFinderStrategyFactory::build($this->summit_repository, $this->getResourceServerContext())->find($summit_id);
276282
if (is_null($summit)) return $this->error404();
277-
283+
$questions = $summit->getOrderExtraQuestionsByUsage(SummitOrderExtraQuestionTypeConstants::TicketQuestionUsage);
278284
return $this->_getAllCSV(
279285
function () {
280286
return [
@@ -446,8 +452,25 @@ function () use ($summit) {
446452
sprintf('tickets-%s-', $summit_id),
447453
[
448454
'features_types' => $summit->getBadgeFeaturesTypes(),
449-
'ticket_questions' => $summit->getOrderExtraQuestionsByUsage(SummitOrderExtraQuestionTypeConstants::TicketQuestionUsage)
450-
]
455+
'ticket_questions' => $questions
456+
],
457+
null,
458+
function($data, $serializerParams) use($questions){
459+
460+
$owners = [];
461+
foreach ($data->getItems() as $t){
462+
if ($t->hasOwner()) $owners[] = $t->getOwner()->getId();
463+
}
464+
$questionIds = [];
465+
foreach ($questions as $q) {
466+
$questionIds[] = $q->getId();
467+
}
468+
$questionIds = array_values(array_unique($questionIds));
469+
$owners = array_values(array_unique($owners));
470+
471+
$serializerParams['answers_by_owner'] = $this->attendee_repository->getExtraQuestionAnswersByOwners($owners, $questionIds);
472+
return $serializerParams;
473+
}
451474
);
452475
}
453476

@@ -932,4 +955,4 @@ public function canPrintAttendeeBadge($summit_id, $ticket_id, $view_type)
932955
);
933956
});
934957
}
935-
}
958+
}

app/Http/Controllers/Apis/Protected/Summit/Traits/ParametrizedGetAll.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ public function _getAllCSV
178178
callable $getColumns,
179179
string $file_prefix = 'file-',
180180
array $serializerParams = [],
181-
callable $queryCallable = null
181+
callable $queryCallable = null,
182+
callable $preProcessSerializerParams = null,
182183
)
183184
{
184185

@@ -192,7 +193,8 @@ public function _getAllCSV
192193
$getColumns,
193194
$file_prefix,
194195
$serializerParams,
195-
$queryCallable
196+
$queryCallable,
197+
$preProcessSerializerParams
196198
) {
197199

198200
$values = Request::all();
@@ -247,6 +249,9 @@ public function _getAllCSV
247249

248250
$serializerParams['filter'] = $filter;
249251

252+
if(!is_null($preProcessSerializerParams))
253+
$serializerParams = call_user_func($preProcessSerializerParams, $data, $serializerParams);
254+
250255
$list = $data->toArray
251256
(
252257
SerializerUtils::getExpand(),

app/ModelSerializers/Summit/Registration/SummitAttendeeSerializer.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ public function serialize($expand = null, array $fields = [], array $relations =
8484
$serializer_type = $params['serializer_type'];
8585
$summit = $attendee->getSummit();
8686

87-
$attendee->updateStatus();
8887
$beginVotingDate = $params['begin_attendee_voting_period_date'] ?? null;
8988
$endVotingDate = $params['end_attendee_voting_period_date'] ?? null;
9089
$track_group_id = $params['presentation_votes_track_group_id'] ?? null;
@@ -347,4 +346,4 @@ public function serialize($expand = null, array $fields = [], array $relations =
347346
});
348347

349348
}
350-
}
349+
}

app/ModelSerializers/Summit/Registration/SummitAttendeeTicketCSVSerializer.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ public function serialize($expand = null, array $fields = [], array $relations =
8080
$ticket_owner = $ticket->getOwner();
8181

8282
if (isset($params['ticket_questions'])) {
83+
$answersByOwner = $params['answers_by_owner'] ?? null;
8384
foreach ($params['ticket_questions'] as $question) {
8485
if (!$question instanceof SummitOrderExtraQuestionType) continue;
8586

@@ -88,7 +89,7 @@ public function serialize($expand = null, array $fields = [], array $relations =
8889
$values[$question_label] = '';
8990

9091
if (!is_null($ticket_owner)) {
91-
$value = $ticket_owner->getExtraQuestionAnswerValueByQuestion($question);
92+
$value = $answersByOwner[$ticket_owner->getId()][$question->getId()] ?? null;
9293
if(is_null($value)) continue;
9394

9495
$cacheKey = $question->getId() . '|' . $value;
@@ -140,4 +141,4 @@ public function serialize($expand = null, array $fields = [], array $relations =
140141

141142
return $values;
142143
}
143-
}
144+
}

app/Models/Foundation/Summit/Registration/Attendees/SummitAttendee.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,6 @@ private function warmExtraQuestionAnswersCache():void{
749749

750750
$map = [];
751751
foreach ($rows as $row) {
752-
// QuestionID es int; Value es string (para multiselect puede ser CSV/JSON según tu modelo)
753752
$map[(int)$row['QuestionID']] = $row['Value'];
754753
}
755754
$this->extraQuestionAnswersCache = $map;

app/Models/Foundation/Summit/Repositories/ISummitAttendeeRepository.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,11 @@ public function deleteAllBySummit(int $summit_id):bool;
9696
*/
9797
public function getBySummitAndFirstNameAndLastNameAndManager(Summit $summit, string $first_name, string $last_name, SummitAttendee $manager):?SummitAttendee;
9898

99+
100+
/**
101+
* @param array $owners
102+
* @param array $questions
103+
* @return array
104+
*/
105+
public function getExtraQuestionAnswersByOwners(array $owners, array $questions):array;
99106
}

app/Repositories/DoctrineRepository.php

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Doctrine\ORM\EntityManagerInterface;
1818
use Doctrine\ORM\EntityRepository;
1919
use Doctrine\ORM\LazyCriteriaCollection;
20+
use Doctrine\ORM\Mapping\ClassMetadata;
2021
use Doctrine\ORM\NativeQuery;
2122
use Doctrine\ORM\Query;
2223
use Doctrine\ORM\Query\ResultSetMappingBuilder;
@@ -39,6 +40,12 @@
3940
*/
4041
abstract class DoctrineRepository extends EntityRepository implements IBaseRepository
4142
{
43+
protected $fetchJoinCollection = true;
44+
45+
public function __construct(EntityManagerInterface $em, ClassMetadata $class)
46+
{
47+
parent::__construct($em, $class);
48+
}
4249

4350
/**
4451
* @var string
@@ -189,7 +196,7 @@ protected function getParametrizedAllByPage
189196
Log::debug(sprintf("DoctrineRepository::getParametrizedAllByPage DQL %s", $query->getDQL()));
190197
$start = time();
191198

192-
$paginator = new Paginator($query, $fetchJoinCollection = true);
199+
$paginator = new Paginator($query, $this->fetchJoinCollection);
193200
$total = $paginator->count();
194201
$end = time();
195202
$delta = $end - $start;
@@ -283,7 +290,7 @@ public function getAllByPage(PagingInfo $paging_info, Filter $filter = null, Ord
283290
->setFirstResult($paging_info->getOffset())
284291
->setMaxResults($paging_info->getPerPage());
285292

286-
$paginator = new Paginator($query, $fetchJoinCollection = true);
293+
$paginator = new Paginator($query, $this->fetchJoinCollection);
287294
$total = $paginator->count();
288295
$data = [];
289296

@@ -300,6 +307,35 @@ public function getAllByPage(PagingInfo $paging_info, Filter $filter = null, Ord
300307
);
301308
}
302309

310+
/**
311+
* @param Filter|null $filter
312+
* @param Order|null $order
313+
* @return int
314+
*/
315+
public function getFastCount(Filter $filter = null, Order $order = null){
316+
$query = $this->getEntityManager()
317+
->createQueryBuilder()
318+
->select('COUNT(DISTINCT e.id)')
319+
->from($this->getBaseEntity(), "e")
320+
->distinct(false);
321+
322+
$query = $this->applyExtraJoins($query, $filter, $order);
323+
324+
$query = $this->applyExtraSelects($query, $filter, $order);
325+
326+
if(!is_null($filter)){
327+
$filter->apply2Query($query, $this->getFilterMappings($filter));
328+
}
329+
330+
$query = $this->applyExtraFilters($query);
331+
332+
if(!is_null($order)){
333+
$order->apply2Query($query, $this->getOrderMappings($filter));
334+
}
335+
336+
return (int) $query->getQuery()->getSingleScalarResult();
337+
}
338+
303339
/**
304340
* @param PagingInfo $paging_info
305341
* @param Filter|null $filter
@@ -518,7 +554,7 @@ protected function getAllAbstractByPage
518554
->setFirstResult($paging_info->getOffset())
519555
->setMaxResults($paging_info->getPerPage());
520556

521-
$paginator = new Paginator($query, $fetchJoinCollection = true);
557+
$paginator = new Paginator($query, $this->fetchJoinCollection);
522558
$total = $paginator->count();
523559
$data = array();
524560

@@ -534,4 +570,4 @@ protected function getAllAbstractByPage
534570
$data
535571
);
536572
}
537-
}
573+
}

app/Repositories/Summit/DoctrineSummitAttendeeRepository.php

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ protected function getOrderMappings()
285285
'member_id' => 'm.id',
286286
'status' => 'e.status',
287287
'email' => <<<SQL
288-
COALESCE(LOWER(m.email), LOWER(e.email))
288+
COALESCE(LOWER(m.email), LOWER(e.email))
289289
SQL,
290290
'presentation_votes_count' => 'COUNT(pv.id)',
291291
'summit_hall_checked_in_date' => 'e.summit_hall_checked_in_date',
@@ -556,4 +556,41 @@ public function getBySummitAndFirstNameAndLastNameAndManager(Summit $summit, str
556556
return $query->getQuery()->getOneOrNullResult();
557557
}
558558

559-
}
559+
/**
560+
* @param array $owners
561+
* @param array $questions
562+
* @return array
563+
* @throws \Doctrine\DBAL\Exception
564+
*/
565+
public function getExtraQuestionAnswersByOwners(array $owners, array $questions): array
566+
{
567+
$sql = <<<SQL
568+
SELECT SOEQA.SummitAttendeeID AS owner_id, EQA.QuestionID AS question_id, EQA.Value AS value
569+
FROM SummitOrderExtraQuestionAnswer SOEQA
570+
JOIN ExtraQuestionAnswer EQA ON EQA.ID = SOEQA.ID
571+
WHERE SOEQA.SummitAttendeeID IN (:owner_ids)
572+
AND EQA.QuestionID IN (:question_ids)
573+
SQL;
574+
575+
$stmt = $this->getEntityManager()->getConnection()->executeQuery
576+
(
577+
$sql,
578+
[
579+
'owner_ids' => $owners,
580+
'question_ids' => $questions
581+
],
582+
[
583+
'owner_ids' => \Doctrine\DBAL\ArrayParameterType::INTEGER,
584+
'question_ids' => \Doctrine\DBAL\ArrayParameterType::INTEGER
585+
]
586+
);
587+
588+
$answersByOwner = [];
589+
foreach ($stmt->fetchAllAssociative() as $r) {
590+
$answersByOwner[(int)$r['owner_id']][(int)$r['question_id']] = (string)$r['value'];
591+
}
592+
593+
return $answersByOwner;
594+
595+
}
596+
}

0 commit comments

Comments
 (0)