SlideShare a Scribd company logo
1 of 111
Download to read offline
How to optimize background processes
when Sylius meets Black
fi
re
Photo by Laura Ockel on Unsplash
Introduction
01
Photo by Mikhail Vasilyev on Unsplash
Photo by Ryan Quintal on Unsplash
Feature overview
sylius.com
4
Product variants


Always have Y Channel Pricings,


Where Y equals amount of Channels in shop
Product


May have from 1 to N variants
Channel Pricing


Contains end pricing for customer
Sylius pricing model
sylius.com
Discounting rules set
5
Main con
fi
guration


Dates


Channels


Enabled


Priority


Exclusiveness
Processing scope


Variants


Products


Taxonomy
Resulting actions


Fixed discount


Percentage discount
sylius.com
6
1 - 10
To process updates of


Products through UI interface
Minimal processable scope


As a business rule
10k - 100k
Default behaviour should


Be consider for these values
Typical Sylius project


Based on the clients we are working the most
Over 1kk
Feature should be possible


To be used with this scope
Maximal processable scope


From the projects we know
Dataset size
Photo by Brendan Church on Unsplash
Initial dilema
sylius.com
8
Take all eligible catalog promotions


This step can be outsourced to DB
Fetch variants for given promotion


To ensure that only correct ones applies
Apply promotion for given variants


Go to the next promotion


Execute second step
Catalog Promotion
Processing order
Take all product variants


This step can be outsourced to DB
Take all eligible catalog promotions


This step can be outsourced to DB
Apply promotion for given variant


Product Variant
Performance test setup
Photo by Loubna Aggoun on Unsplash
sylius.com
?
Dataset


7000 Product Variants


3 Catalog Promotions covering all of products at least once


2 Channels
Execution on single catalog promotion update


Triggering CatalogPromotionUpdated event
Environment


Production environment


No debug option


Removal of cache and cache warmup before each execution
<
E
10
sylius.com
11
Command Batching
Doctrine


Fetching only codes to avoid hydration


Flushing & transaction out-of-the-box


Clearance of entity manager
Symfony Messenger


No need for custom command


Flushing & transaction out-of-the-box


Sync & async switch is piece of cake
Photo by Shane Aldendorff on Unsplash
Let’s improve!
02
Photo by Bastien Plu on Unsplash
First round - bug
sylius.com
23
public function assignLocale(
TranslatableInterface $translatableEntity
): void {
$fallbackLocale = $this
->translationLocaleProvider
->getDefaultLocaleCode()
;
try {
$currentLocale = $this->localeContext->getLocaleCode();
} catch (LocaleNotFoundException) {
$currentLocale = $fallbackLocale;
}
$translatableEntity->setCurrentLocale($currentLocale);
$translatableEntity->setFallbackLocale($fallbackLocale);
}
sylius.com
24
public function assignLocale(
TranslatableInterface $translatableEntity
): void {
$fallbackLocale = $this
->translationLocaleProvider
->getDefaultLocaleCode()
;
try {
$currentLocale = $this->localeContext->getLocaleCode();
} catch (LocaleNotFoundException) {
$currentLocale = $fallbackLocale;
}
$translatableEntity->setCurrentLocale($currentLocale);
$translatableEntity->setFallbackLocale($fallbackLocale);
}
sylius.com
25
public function assignLocale(
TranslatableInterface $translatableEntity
): void {
$fallbackLocale = $this
->translationLocaleProvider
->getDefaultLocaleCode()
;
try {
$currentLocale = $this->localeContext->getLocaleCode();
} catch (LocaleNotFoundException) {
$currentLocale = $fallbackLocale;
}
$translatableEntity->setCurrentLocale($currentLocale);
$translatableEntity->setFallbackLocale($fallbackLocale);
}
sylius.com
26
public function assignLocale(
TranslatableInterface $translatableEntity
): void {
$fallbackLocale = $this
->translationLocaleProvider
->getDefaultLocaleCode()
;
try {
$currentLocale = $this->localeContext->getLocaleCode();
} catch (LocaleNotFoundException) {
$currentLocale = $fallbackLocale;
}
$translatableEntity->setCurrentLocale($currentLocale);
$translatableEntity->setFallbackLocale($fallbackLocale);
}
sylius.com
27
public function assignLocale(
TranslatableInterface $translatableEntity
): void {
$fallbackLocale = $this
->translationLocaleProvider
->getDefaultLocaleCode()
;
try {
$currentLocale = $this->localeContext->getLocaleCode();
} catch (LocaleNotFoundException) {
$currentLocale = $fallbackLocale;
}
$translatableEntity->setCurrentLocale($currentLocale);
$translatableEntity->setFallbackLocale($fallbackLocale);
}
sylius.com
28
if ($this->commandBasedChecker->isExecutedFromCLI()) {
$translatableEntity->setCurrentLocale($fallbackLocale);
return;
}
try {
$currentLocale = $this->localeContext->getLocaleCode();
} catch (LocaleNotFoundException) {
$currentLocale = $fallbackLocale;
}
sylius.com
34
Conclusion?
Photo by Pietro Mattia on Unsplash
Second round - N+1
sylius.com
41
public function findByCodes(array $codes): array
{
return $this->createQueryBuilder('o')
->andWhere('o.code IN (:codes)')
->setParameter('codes', $codes)
->getQuery()
->getResult()
;
}
sylius.com
42
public function findByCodes(array $codes): array
{
return $this->createQueryBuilder('o')
->addSelect('product')
->addSelect('channelPricings')
->addSelect('appliedPromotions')
->addSelect('productTaxon')
->addSelect('taxon')
->leftJoin('o.channelPricings', 'channelPricings')
->leftJoin('channelPricings.appliedPromotions', 'appliedPromotions')
->leftJoin('o.product', 'product')
->leftJoin('product.productTaxons', 'productTaxon')
->leftJoin('productTaxon.taxon', 'taxon')
->andWhere('o.code IN (:codes)')
->setParameter('codes', $codes)
->getQuery()
->getResult()
;
}
sylius.com
43
public function findByCodes(array $codes): array
{
return $this->createQueryBuilder('o')
->addSelect('product')
->addSelect('channelPricings')
->addSelect('appliedPromotions')
->addSelect('productTaxon')
->addSelect('taxon')
->leftJoin('o.channelPricings', 'channelPricings')
->leftJoin('channelPricings.appliedPromotions', 'appliedPromotions')
->leftJoin('o.product', 'product')
->leftJoin('product.productTaxons', 'productTaxon')
->leftJoin('productTaxon.taxon', 'taxon')
->andWhere('o.code IN (:codes)')
->setParameter('codes', $codes)
->getQuery()
->getResult()
;
}
sylius.com
50
Conclusion?
Photo by Ralfs Blumbergs on Unsplash
Third round - EM Clear
sylius.com
52
Up to this moment


All operations were executed synchronously
sylius.com
54
After implementation of EntityManagerClearer and
switching to async processing
sylius.com
56
Conclusion?
Photo by Bastien Plu on Unsplash
Summary
Photo by Glen Rushton on Unsplash
Final round - native query
sylius.com
64
private function clearChannelPricing(
ChannelPricingInterface $channelPricing
): void {
if ($channelPricing->getAppliedPromotions()->isEmpty()) {
return;
}
if ($channelPricing->getOriginalPrice() !== null) {
$channelPricing->setPrice($channelPricing->getOriginalPrice());
}
$channelPricing->clearAppliedPromotions();
}
sylius.com
65
private function clearChannelPricing(
ChannelPricingInterface $channelPricing
): void {
if ($channelPricing->getAppliedPromotions()->isEmpty()) {
return;
}
if ($channelPricing->getOriginalPrice() !== null) {
$channelPricing->setPrice($channelPricing->getOriginalPrice());
}
$channelPricing->clearAppliedPromotions();
}
sylius.com
66
private function clearChannelPricing(
ChannelPricingInterface $channelPricing
): void {
if ($channelPricing->getAppliedPromotions()->isEmpty()) {
return;
}
if ($channelPricing->getOriginalPrice() !== null) {
$channelPricing->setPrice($channelPricing->getOriginalPrice());
}
$channelPricing->clearAppliedPromotions();
}
sylius.com
67
private function clearChannelPricing(
ChannelPricingInterface $channelPricing
): void {
if ($channelPricing->getAppliedPromotions()->isEmpty()) {
return;
}
if ($channelPricing->getOriginalPrice() !== null) {
$channelPricing->setPrice($channelPricing->getOriginalPrice());
}
$channelPricing->clearAppliedPromotions();
}
sylius.com
68
public function __invoke(
ApplyCatalogPromotionsOnVariants $updateVariants
): void {
$catalogPromotions = $this->catalogPromotionsProvider->provide();
$variants = $this->productVariantRepository->findByCodes(
$updateVariants->variantsCodes
);
foreach ($variants as $variant) {
$this->clearer->clearVariant($variant);
foreach ($catalogPromotions as $promotion) {
$this->catalogPromotionApplicator->applyOnVariant(
$variant,
$promotion
);
}
}
}
sylius.com
69
public function __invoke(
ApplyCatalogPromotionsOnVariants $updateVariants
): void {
$catalogPromotions = $this->catalogPromotionsProvider->provide();
$variants = $this->productVariantRepository->findByCodes(
$updateVariants->variantsCodes
);
foreach ($variants as $variant) {
$this->clearer->clearVariant($variant);
foreach ($catalogPromotions as $promotion) {
$this->catalogPromotionApplicator->applyOnVariant(
$variant,
$promotion
);
}
}
}
sylius.com
70
public function __invoke(
ApplyCatalogPromotionsOnVariants $updateVariants
): void {
$catalogPromotions = $this->catalogPromotionsProvider->provide();
$variants = $this->productVariantRepository->findByCodes(
$updateVariants->variantsCodes
);
foreach ($variants as $variant) {
$this->clearer->clearVariant($variant);
foreach ($catalogPromotions as $promotion) {
$this->catalogPromotionApplicator->applyOnVariant(
$variant,
$promotion
);
}
}
}
sylius.com
71
public function __invoke(
ApplyCatalogPromotionsOnVariants $updateVariants
): void {
$catalogPromotions = $this->catalogPromotionsProvider->provide();
$variants = $this->productVariantRepository->findByCodes(
$updateVariants->variantsCodes
);
foreach ($variants as $variant) {
$this->clearer->clearVariant($variant);
foreach ($catalogPromotions as $promotion) {
$this->catalogPromotionApplicator->applyOnVariant(
$variant,
$promotion
);
}
}
}
sylius.com
72
public function __invoke(
ApplyCatalogPromotionsOnVariants $updateVariants
): void {
$catalogPromotions = $this->catalogPromotionsProvider->provide();
$variants = $this->productVariantRepository->findByCodes(
$updateVariants->variantsCodes
);
foreach ($variants as $variant) {
$this->clearer->clearVariant($variant);
foreach ($catalogPromotions as $promotion) {
$this->catalogPromotionApplicator->applyOnVariant(
$variant,
$promotion
);
}
}
}
sylius.com
73
public function __invoke(
ApplyCatalogPromotionsOnVariants $updateVariants
): void {
$catalogPromotions = $this->catalogPromotionsProvider->provide();
$variants = $this->productVariantRepository->findByCodes(
$updateVariants->variantsCodes
);
foreach ($variants as $variant) {
$this->clearer->clearVariant($variant);
foreach ($catalogPromotions as $promotion) {
$this->catalogPromotionApplicator->applyOnVariant(
$variant,
$promotion
);
}
}
}
sylius.com
74
public function __invoke(
ApplyCatalogPromotionsOnVariants $updateVariants
): void {
$catalogPromotions = $this->catalogPromotionsProvider->provide();
$variants = $this->productVariantRepository->findByCodes(
$updateVariants->variantsCodes
);
foreach ($variants as $variant) {
$this->clearer->clearVariant($variant);
foreach ($catalogPromotions as $promotion) {
$this->catalogPromotionApplicator->applyOnVariant(
$variant,
$promotion
);
}
}
}
sylius.com
75
foreach ($variants as $variant) {
$this->clearer->clearVariant($variant);
}
$codes = array_column($updateVariants->variantsCodes, 'code');
$connection = $this->entityManager->getConnection();
$connection->executeQuery('
DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp
JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
WHERE spv.code IN (?)’,
[$codes],
[Connection::PARAM_STR_ARRAY]
);
foreach ($variants as $variant) {
// Apply Catalog promotion
}
sylius.com
76
foreach ($variants as $variant) {
$this->clearer->clearVariant($variant);
}
$codes = array_column($updateVariants->variantsCodes, 'code');
$connection = $this->entityManager->getConnection();
$connection->executeQuery('
DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp
JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
WHERE spv.code IN (?)’,
[$codes],
[Connection::PARAM_STR_ARRAY]
);
foreach ($variants as $variant) {
// Apply Catalog promotion
}
sylius.com
77
foreach ($variants as $variant) {
$this->clearer->clearVariant($variant);
}
$codes = array_column($updateVariants->variantsCodes, 'code');
$connection = $this->entityManager->getConnection();
$connection->executeQuery('
DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp
JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
WHERE spv.code IN (?)’,
[$codes],
[Connection::PARAM_STR_ARRAY]
);
foreach ($variants as $variant) {
// Apply Catalog promotion
}
sylius.com
78
foreach ($variants as $variant) {
$this->clearer->clearVariant($variant);
}
$codes = array_column($updateVariants->variantsCodes, 'code');
$connection = $this->entityManager->getConnection();
$connection->executeQuery('
DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp
JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
WHERE spv.code IN (?)’,
[$codes],
[Connection::PARAM_STR_ARRAY]
);
foreach ($variants as $variant) {
// Apply Catalog promotion
}
sylius.com
79
foreach ($variants as $variant) {
$this->clearer->clearVariant($variant);
}
$codes = array_column($updateVariants->variantsCodes, 'code');
$connection = $this->entityManager->getConnection();
$connection->executeQuery('
DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp
JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
WHERE spv.code IN (?)’,
[$codes],
[Connection::PARAM_STR_ARRAY]
);
foreach ($variants as $variant) {
// Apply Catalog promotion
}
sylius.com
80
foreach ($variants as $variant) {
$this->clearer->clearVariant($variant);
}
$codes = array_column($updateVariants->variantsCodes, 'code');
$connection = $this->entityManager->getConnection();
$connection->executeQuery('
DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp
JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
WHERE spv.code IN (?)’,
[$codes],
[Connection::PARAM_STR_ARRAY]
);
foreach ($variants as $variant) {
// Apply Catalog promotion
}
sylius.com
81
foreach ($variants as $variant) {
$this->clearer->clearVariant($variant);
}
$codes = array_column($updateVariants->variantsCodes, 'code');
$connection = $this->entityManager->getConnection();
$connection->executeQuery('
DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp
JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
WHERE spv.code IN (?)’,
[$codes],
[Connection::PARAM_STR_ARRAY]
);
foreach ($variants as $variant) {
// Apply Catalog promotion
}
sylius.com
82
foreach ($variants as $variant) {
$this->clearer->clearVariant($variant);
}
$codes = array_column($updateVariants->variantsCodes, 'code');
$connection = $this->entityManager->getConnection();
$connection->executeQuery('
DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp
JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
WHERE spv.code IN (?)’,
[$codes],
[Connection::PARAM_STR_ARRAY]
);
foreach ($variants as $variant) {
// Apply Catalog promotion
}
sylius.com
83
foreach ($variants as $variant) {
$this->clearer->clearVariant($variant);
}
$codes = array_column($updateVariants->variantsCodes, 'code');
$connection = $this->entityManager->getConnection();
$connection->executeQuery('
DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp
JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
WHERE spv.code IN (?)’,
[$codes],
[Connection::PARAM_STR_ARRAY]
);
foreach ($variants as $variant) {
// Apply Catalog promotion
}
sylius.com
88
It didn’t work according to acceptance tests!
sylius.com
92
public function __invoke(
ClearCatalogPromotionsOnVariants $clearCatalogPromotionsOnVariants
): void {
$codes = array_column($clearCatalogPromotionsOnVariants->variantsCodes, ‘code');
$connection = $this->entityManager->getConnection();
$connection->executeQuery('
UPDATE sylius_channel_pricing scp
INNER JOIN sylius_channel_pricing_catalog_promotions scpcp ON
scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
SET scp.price=scp.original_price
WHERE spv.code IN (?);', [$codes], [Connection::PARAM_STR_ARRAY]);
$connection->executeQuery('
DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp
JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
WHERE spv.code IN (?)', [$codes], [Connection::PARAM_STR_ARRAY]);
}
sylius.com
93
public function __invoke(
ClearCatalogPromotionsOnVariants $clearCatalogPromotionsOnVariants
): void {
$codes = array_column($clearCatalogPromotionsOnVariants->variantsCodes, ‘code');
$connection = $this->entityManager->getConnection();
$connection->executeQuery('
UPDATE sylius_channel_pricing scp
INNER JOIN sylius_channel_pricing_catalog_promotions scpcp ON
scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
SET scp.price=scp.original_price
WHERE spv.code IN (?);', [$codes], [Connection::PARAM_STR_ARRAY]);
$connection->executeQuery('
DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp
JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
WHERE spv.code IN (?)', [$codes], [Connection::PARAM_STR_ARRAY]);
}
sylius.com
94
public function __invoke(
ClearCatalogPromotionsOnVariants $clearCatalogPromotionsOnVariants
): void {
$codes = array_column($clearCatalogPromotionsOnVariants->variantsCodes, ‘code');
$connection = $this->entityManager->getConnection();
$connection->executeQuery('
UPDATE sylius_channel_pricing scp
INNER JOIN sylius_channel_pricing_catalog_promotions scpcp ON
scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
SET scp.price=scp.original_price
WHERE spv.code IN (?);', [$codes], [Connection::PARAM_STR_ARRAY]);
$connection->executeQuery('
DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp
JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
WHERE spv.code IN (?)', [$codes], [Connection::PARAM_STR_ARRAY]);
}
sylius.com
95
public function __invoke(
ClearCatalogPromotionsOnVariants $clearCatalogPromotionsOnVariants
): void {
$codes = array_column($clearCatalogPromotionsOnVariants->variantsCodes, ‘code');
$connection = $this->entityManager->getConnection();
$connection->executeQuery('
UPDATE sylius_channel_pricing scp
INNER JOIN sylius_channel_pricing_catalog_promotions scpcp ON
scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
SET scp.price=scp.original_price
WHERE spv.code IN (?);', [$codes], [Connection::PARAM_STR_ARRAY]);
$connection->executeQuery('
DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp
JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
WHERE spv.code IN (?)', [$codes], [Connection::PARAM_STR_ARRAY]);
}
sylius.com
96
public function __invoke(
ClearCatalogPromotionsOnVariants $clearCatalogPromotionsOnVariants
): void {
$codes = array_column($clearCatalogPromotionsOnVariants->variantsCodes, ‘code');
$connection = $this->entityManager->getConnection();
$connection->executeQuery('
UPDATE sylius_channel_pricing scp
INNER JOIN sylius_channel_pricing_catalog_promotions scpcp ON
scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
SET scp.price=scp.original_price
WHERE spv.code IN (?);', [$codes], [Connection::PARAM_STR_ARRAY]);
$connection->executeQuery('
DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp
JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id
JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id
WHERE spv.code IN (?)', [$codes], [Connection::PARAM_STR_ARRAY]);
}
sylius.com
?
101
What if we change


the catalog promotion


con
fi
guration?
sylius.com
106
Conclusion?
Photo by Mikhail Vasilyev on Unsplash
03
Takeaways
sylius.com
109
Check the highest class in your callgraph


And look for bugs
Remember to clear Entity Manager when batch processing


Unless you are executing asynchronously messages with Symfony Messenger
Load all data required to perform operation


But not more
Pure DQL may bring bene
fi
ts


But is hard to do it properly for complicated objects or mix it with ORM
sylius.com
110
SyliusCon
This autumn - at 27th of October


In a Sylius hometown: Łódź
sylius.com
111
Thank you!
Photo by Maksym Harbar on Unsplash

More Related Content

What's hot

Advanced JavaScript
Advanced JavaScriptAdvanced JavaScript
Advanced JavaScriptNascenia IT
 
Removing performance bottlenecks with Kafka Monitoring and topic configuration
Removing performance bottlenecks with Kafka Monitoring and topic configurationRemoving performance bottlenecks with Kafka Monitoring and topic configuration
Removing performance bottlenecks with Kafka Monitoring and topic configurationKnoldus Inc.
 
10 minute command line apps with zio cli
10 minute command line apps with zio cli10 minute command line apps with zio cli
10 minute command line apps with zio cliAiswarya Prakasan
 
Attribute-Based Access Control in Symfony
Attribute-Based Access Control in SymfonyAttribute-Based Access Control in Symfony
Attribute-Based Access Control in SymfonyAdam Elsodaney
 
Introduction to RxJS
Introduction to RxJSIntroduction to RxJS
Introduction to RxJSBrainhub
 
JavaScript: Variables and Functions
JavaScript: Variables and FunctionsJavaScript: Variables and Functions
JavaScript: Variables and FunctionsJussi Pohjolainen
 
Java concurrency - Thread pools
Java concurrency - Thread poolsJava concurrency - Thread pools
Java concurrency - Thread poolsmaksym220889
 
salesforce triggers interview questions and answers
salesforce triggers interview questions and answerssalesforce triggers interview questions and answers
salesforce triggers interview questions and answersbhanuadmob
 
Oracle Forms to APEX conversion tool
Oracle Forms to APEX conversion toolOracle Forms to APEX conversion tool
Oracle Forms to APEX conversion toolScott Wesley
 
Nicky Bloor - BaRMIe - Poking Java's Back Door - 44CON 2017
Nicky Bloor - BaRMIe - Poking Java's Back Door - 44CON 2017Nicky Bloor - BaRMIe - Poking Java's Back Door - 44CON 2017
Nicky Bloor - BaRMIe - Poking Java's Back Door - 44CON 2017Nicky Bloor
 
Kim Hammar - Feature Store: the missing data layer in ML pipelines? - HopsML ...
Kim Hammar - Feature Store: the missing data layer in ML pipelines? - HopsML ...Kim Hammar - Feature Store: the missing data layer in ML pipelines? - HopsML ...
Kim Hammar - Feature Store: the missing data layer in ML pipelines? - HopsML ...Kim Hammar
 
The-Hacker-Playbook-Practical-Guide-To-Penetration-Testing-2014.pdf
The-Hacker-Playbook-Practical-Guide-To-Penetration-Testing-2014.pdfThe-Hacker-Playbook-Practical-Guide-To-Penetration-Testing-2014.pdf
The-Hacker-Playbook-Practical-Guide-To-Penetration-Testing-2014.pdfprasunkagrawal
 
Spring security oauth2
Spring security oauth2Spring security oauth2
Spring security oauth2axykim00
 
Advanced task management with Celery
Advanced task management with CeleryAdvanced task management with Celery
Advanced task management with CeleryMahendra M
 

What's hot (20)

Complete-NGINX-Cookbook-2019.pdf
Complete-NGINX-Cookbook-2019.pdfComplete-NGINX-Cookbook-2019.pdf
Complete-NGINX-Cookbook-2019.pdf
 
Advanced JavaScript
Advanced JavaScriptAdvanced JavaScript
Advanced JavaScript
 
C++ Interview Questions
C++ Interview QuestionsC++ Interview Questions
C++ Interview Questions
 
Removing performance bottlenecks with Kafka Monitoring and topic configuration
Removing performance bottlenecks with Kafka Monitoring and topic configurationRemoving performance bottlenecks with Kafka Monitoring and topic configuration
Removing performance bottlenecks with Kafka Monitoring and topic configuration
 
10 minute command line apps with zio cli
10 minute command line apps with zio cli10 minute command line apps with zio cli
10 minute command line apps with zio cli
 
Attribute-Based Access Control in Symfony
Attribute-Based Access Control in SymfonyAttribute-Based Access Control in Symfony
Attribute-Based Access Control in Symfony
 
Introduction to RxJS
Introduction to RxJSIntroduction to RxJS
Introduction to RxJS
 
JavaScript: Variables and Functions
JavaScript: Variables and FunctionsJavaScript: Variables and Functions
JavaScript: Variables and Functions
 
Java concurrency - Thread pools
Java concurrency - Thread poolsJava concurrency - Thread pools
Java concurrency - Thread pools
 
jQuery Essentials
jQuery EssentialsjQuery Essentials
jQuery Essentials
 
salesforce triggers interview questions and answers
salesforce triggers interview questions and answerssalesforce triggers interview questions and answers
salesforce triggers interview questions and answers
 
InnoDB Locking Explained with Stick Figures
InnoDB Locking Explained with Stick FiguresInnoDB Locking Explained with Stick Figures
InnoDB Locking Explained with Stick Figures
 
Oracle Forms to APEX conversion tool
Oracle Forms to APEX conversion toolOracle Forms to APEX conversion tool
Oracle Forms to APEX conversion tool
 
Nicky Bloor - BaRMIe - Poking Java's Back Door - 44CON 2017
Nicky Bloor - BaRMIe - Poking Java's Back Door - 44CON 2017Nicky Bloor - BaRMIe - Poking Java's Back Door - 44CON 2017
Nicky Bloor - BaRMIe - Poking Java's Back Door - 44CON 2017
 
Php sessions & cookies
Php sessions & cookiesPhp sessions & cookies
Php sessions & cookies
 
Kim Hammar - Feature Store: the missing data layer in ML pipelines? - HopsML ...
Kim Hammar - Feature Store: the missing data layer in ML pipelines? - HopsML ...Kim Hammar - Feature Store: the missing data layer in ML pipelines? - HopsML ...
Kim Hammar - Feature Store: the missing data layer in ML pipelines? - HopsML ...
 
Angular
AngularAngular
Angular
 
The-Hacker-Playbook-Practical-Guide-To-Penetration-Testing-2014.pdf
The-Hacker-Playbook-Practical-Guide-To-Penetration-Testing-2014.pdfThe-Hacker-Playbook-Practical-Guide-To-Penetration-Testing-2014.pdf
The-Hacker-Playbook-Practical-Guide-To-Penetration-Testing-2014.pdf
 
Spring security oauth2
Spring security oauth2Spring security oauth2
Spring security oauth2
 
Advanced task management with Celery
Advanced task management with CeleryAdvanced task management with Celery
Advanced task management with Celery
 

Similar to How to optimize background processes - when Sylius meets Blackfire

How to optimize background processes.pdf
How to optimize background processes.pdfHow to optimize background processes.pdf
How to optimize background processes.pdfŁukasz Chruściel
 
Building a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesBuilding a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesCiaranMcNulty
 
Repensando o Desenvolvimento Web com Ruby on Rails
Repensando o Desenvolvimento Web com Ruby on RailsRepensando o Desenvolvimento Web com Ruby on Rails
Repensando o Desenvolvimento Web com Ruby on RailsDante Regis
 
Asp netmvc e03
Asp netmvc e03Asp netmvc e03
Asp netmvc e03Yu GUAN
 
The Ring programming language version 1.5.2 book - Part 7 of 181
The Ring programming language version 1.5.2 book - Part 7 of 181The Ring programming language version 1.5.2 book - Part 7 of 181
The Ring programming language version 1.5.2 book - Part 7 of 181Mahmoud Samir Fayed
 
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...Databricks
 
Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Konstantin Kudryashov
 
The Ring programming language version 1.5.1 book - Part 12 of 180
The Ring programming language version 1.5.1 book - Part 12 of 180The Ring programming language version 1.5.1 book - Part 12 of 180
The Ring programming language version 1.5.1 book - Part 12 of 180Mahmoud Samir Fayed
 
Art and Science Come Together When Mastering Relevance Ranking - Tom Burgmans...
Art and Science Come Together When Mastering Relevance Ranking - Tom Burgmans...Art and Science Come Together When Mastering Relevance Ranking - Tom Burgmans...
Art and Science Come Together When Mastering Relevance Ranking - Tom Burgmans...Lucidworks
 
Machine Learning Model Bakeoff
Machine Learning Model BakeoffMachine Learning Model Bakeoff
Machine Learning Model Bakeoffmrphilroth
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every dayVadym Khondar
 
Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Mahmoud Hamed Mahmoud
 
Php Unit With Zend Framework Zendcon09
Php Unit With Zend Framework   Zendcon09Php Unit With Zend Framework   Zendcon09
Php Unit With Zend Framework Zendcon09Michelangelo van Dam
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applicationschartjes
 
Symfony 4 Workshop - Limenius
Symfony 4 Workshop - LimeniusSymfony 4 Workshop - Limenius
Symfony 4 Workshop - LimeniusIgnacio Martín
 
An Introduction to Property Based Testing
An Introduction to Property Based TestingAn Introduction to Property Based Testing
An Introduction to Property Based TestingC4Media
 

Similar to How to optimize background processes - when Sylius meets Blackfire (20)

How to optimize background processes.pdf
How to optimize background processes.pdfHow to optimize background processes.pdf
How to optimize background processes.pdf
 
Building a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesBuilding a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing Strategies
 
Repensando o Desenvolvimento Web com Ruby on Rails
Repensando o Desenvolvimento Web com Ruby on RailsRepensando o Desenvolvimento Web com Ruby on Rails
Repensando o Desenvolvimento Web com Ruby on Rails
 
Asp netmvc e03
Asp netmvc e03Asp netmvc e03
Asp netmvc e03
 
99% is not enough
99% is not enough99% is not enough
99% is not enough
 
The Ring programming language version 1.5.2 book - Part 7 of 181
The Ring programming language version 1.5.2 book - Part 7 of 181The Ring programming language version 1.5.2 book - Part 7 of 181
The Ring programming language version 1.5.2 book - Part 7 of 181
 
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...
A Practical Approach to Building a Streaming Processing Pipeline for an Onlin...
 
Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015
 
The Ring programming language version 1.5.1 book - Part 12 of 180
The Ring programming language version 1.5.1 book - Part 12 of 180The Ring programming language version 1.5.1 book - Part 12 of 180
The Ring programming language version 1.5.1 book - Part 12 of 180
 
Art and Science Come Together When Mastering Relevance Ranking - Tom Burgmans...
Art and Science Come Together When Mastering Relevance Ranking - Tom Burgmans...Art and Science Come Together When Mastering Relevance Ranking - Tom Burgmans...
Art and Science Come Together When Mastering Relevance Ranking - Tom Burgmans...
 
Web-First Design Patterns
Web-First Design PatternsWeb-First Design Patterns
Web-First Design Patterns
 
Joy of scala
Joy of scalaJoy of scala
Joy of scala
 
Machine Learning Model Bakeoff
Machine Learning Model BakeoffMachine Learning Model Bakeoff
Machine Learning Model Bakeoff
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
 
Java 102
Java 102Java 102
Java 102
 
Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development
 
Php Unit With Zend Framework Zendcon09
Php Unit With Zend Framework   Zendcon09Php Unit With Zend Framework   Zendcon09
Php Unit With Zend Framework Zendcon09
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
 
Symfony 4 Workshop - Limenius
Symfony 4 Workshop - LimeniusSymfony 4 Workshop - Limenius
Symfony 4 Workshop - Limenius
 
An Introduction to Property Based Testing
An Introduction to Property Based TestingAn Introduction to Property Based Testing
An Introduction to Property Based Testing
 

More from Łukasz Chruściel

Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
ConFoo 2024 - Need for Speed: Removing speed bumps in API Projects
ConFoo 2024  - Need for Speed: Removing speed bumps in API ProjectsConFoo 2024  - Need for Speed: Removing speed bumps in API Projects
ConFoo 2024 - Need for Speed: Removing speed bumps in API ProjectsŁukasz Chruściel
 
ConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solution
ConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solutionConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solution
ConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solutionŁukasz Chruściel
 
SyliusCon - Typical pitfalls of Sylius development.pdf
SyliusCon - Typical pitfalls of Sylius development.pdfSyliusCon - Typical pitfalls of Sylius development.pdf
SyliusCon - Typical pitfalls of Sylius development.pdfŁukasz Chruściel
 
Need for Speed: Removing speed bumps in API Projects
Need for Speed: Removing speed bumps in API ProjectsNeed for Speed: Removing speed bumps in API Projects
Need for Speed: Removing speed bumps in API ProjectsŁukasz Chruściel
 
Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...
Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...
Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...Łukasz Chruściel
 
4Developers - Rozterki i decyzje.pdf
4Developers - Rozterki i decyzje.pdf4Developers - Rozterki i decyzje.pdf
4Developers - Rozterki i decyzje.pdfŁukasz Chruściel
 
4Developers - Sylius CRUD generation revisited.pdf
4Developers - Sylius CRUD generation revisited.pdf4Developers - Sylius CRUD generation revisited.pdf
4Developers - Sylius CRUD generation revisited.pdfŁukasz Chruściel
 
BoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API Syliusa
BoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API SyliusaBoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API Syliusa
BoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API SyliusaŁukasz Chruściel
 
SymfonyCon - Dilemmas and decisions..pdf
SymfonyCon - Dilemmas and decisions..pdfSymfonyCon - Dilemmas and decisions..pdf
SymfonyCon - Dilemmas and decisions..pdfŁukasz Chruściel
 
Dutch php a short tale about state machine
Dutch php   a short tale about state machineDutch php   a short tale about state machine
Dutch php a short tale about state machineŁukasz Chruściel
 
A short tale about state machine
A short tale about state machineA short tale about state machine
A short tale about state machineŁukasz Chruściel
 
A short tale about state machine
A short tale about state machineA short tale about state machine
A short tale about state machineŁukasz Chruściel
 
BDD in practice based on an open source project
BDD in practice based on an open source projectBDD in practice based on an open source project
BDD in practice based on an open source projectŁukasz Chruściel
 
Diversified application testing based on a Sylius project
Diversified application testing based on a Sylius projectDiversified application testing based on a Sylius project
Diversified application testing based on a Sylius projectŁukasz Chruściel
 

More from Łukasz Chruściel (16)

Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
ConFoo 2024 - Need for Speed: Removing speed bumps in API Projects
ConFoo 2024  - Need for Speed: Removing speed bumps in API ProjectsConFoo 2024  - Need for Speed: Removing speed bumps in API Projects
ConFoo 2024 - Need for Speed: Removing speed bumps in API Projects
 
ConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solution
ConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solutionConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solution
ConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solution
 
SyliusCon - Typical pitfalls of Sylius development.pdf
SyliusCon - Typical pitfalls of Sylius development.pdfSyliusCon - Typical pitfalls of Sylius development.pdf
SyliusCon - Typical pitfalls of Sylius development.pdf
 
Need for Speed: Removing speed bumps in API Projects
Need for Speed: Removing speed bumps in API ProjectsNeed for Speed: Removing speed bumps in API Projects
Need for Speed: Removing speed bumps in API Projects
 
Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...
Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...
Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...
 
4Developers - Rozterki i decyzje.pdf
4Developers - Rozterki i decyzje.pdf4Developers - Rozterki i decyzje.pdf
4Developers - Rozterki i decyzje.pdf
 
4Developers - Sylius CRUD generation revisited.pdf
4Developers - Sylius CRUD generation revisited.pdf4Developers - Sylius CRUD generation revisited.pdf
4Developers - Sylius CRUD generation revisited.pdf
 
BoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API Syliusa
BoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API SyliusaBoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API Syliusa
BoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API Syliusa
 
SymfonyCon - Dilemmas and decisions..pdf
SymfonyCon - Dilemmas and decisions..pdfSymfonyCon - Dilemmas and decisions..pdf
SymfonyCon - Dilemmas and decisions..pdf
 
Dutch php a short tale about state machine
Dutch php   a short tale about state machineDutch php   a short tale about state machine
Dutch php a short tale about state machine
 
A short tale about state machine
A short tale about state machineA short tale about state machine
A short tale about state machine
 
A short tale about state machine
A short tale about state machineA short tale about state machine
A short tale about state machine
 
BDD in practice based on an open source project
BDD in practice based on an open source projectBDD in practice based on an open source project
BDD in practice based on an open source project
 
Diversified application testing based on a Sylius project
Diversified application testing based on a Sylius projectDiversified application testing based on a Sylius project
Diversified application testing based on a Sylius project
 
Why do I love and hate php?
Why do I love and hate php?Why do I love and hate php?
Why do I love and hate php?
 

Recently uploaded

How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 

Recently uploaded (20)

Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 

How to optimize background processes - when Sylius meets Blackfire

  • 1. How to optimize background processes when Sylius meets Black fi re Photo by Laura Ockel on Unsplash
  • 2. Introduction 01 Photo by Mikhail Vasilyev on Unsplash
  • 3. Photo by Ryan Quintal on Unsplash Feature overview
  • 4. sylius.com 4 Product variants Always have Y Channel Pricings, Where Y equals amount of Channels in shop Product May have from 1 to N variants Channel Pricing Contains end pricing for customer Sylius pricing model
  • 5. sylius.com Discounting rules set 5 Main con fi guration Dates Channels Enabled Priority Exclusiveness Processing scope Variants Products Taxonomy Resulting actions Fixed discount Percentage discount
  • 6. sylius.com 6 1 - 10 To process updates of Products through UI interface Minimal processable scope As a business rule 10k - 100k Default behaviour should Be consider for these values Typical Sylius project Based on the clients we are working the most Over 1kk Feature should be possible To be used with this scope Maximal processable scope From the projects we know Dataset size
  • 7. Photo by Brendan Church on Unsplash Initial dilema
  • 8. sylius.com 8 Take all eligible catalog promotions This step can be outsourced to DB Fetch variants for given promotion To ensure that only correct ones applies Apply promotion for given variants Go to the next promotion Execute second step Catalog Promotion Processing order Take all product variants This step can be outsourced to DB Take all eligible catalog promotions This step can be outsourced to DB Apply promotion for given variant Product Variant
  • 9. Performance test setup Photo by Loubna Aggoun on Unsplash
  • 10. sylius.com ? Dataset 7000 Product Variants 3 Catalog Promotions covering all of products at least once 2 Channels Execution on single catalog promotion update Triggering CatalogPromotionUpdated event Environment Production environment No debug option Removal of cache and cache warmup before each execution < E 10
  • 11. sylius.com 11 Command Batching Doctrine Fetching only codes to avoid hydration Flushing & transaction out-of-the-box Clearance of entity manager Symfony Messenger No need for custom command Flushing & transaction out-of-the-box Sync & async switch is piece of cake
  • 12. Photo by Shane Aldendorff on Unsplash Let’s improve! 02
  • 13. Photo by Bastien Plu on Unsplash First round - bug
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23. sylius.com 23 public function assignLocale( TranslatableInterface $translatableEntity ): void { $fallbackLocale = $this ->translationLocaleProvider ->getDefaultLocaleCode() ; try { $currentLocale = $this->localeContext->getLocaleCode(); } catch (LocaleNotFoundException) { $currentLocale = $fallbackLocale; } $translatableEntity->setCurrentLocale($currentLocale); $translatableEntity->setFallbackLocale($fallbackLocale); }
  • 24. sylius.com 24 public function assignLocale( TranslatableInterface $translatableEntity ): void { $fallbackLocale = $this ->translationLocaleProvider ->getDefaultLocaleCode() ; try { $currentLocale = $this->localeContext->getLocaleCode(); } catch (LocaleNotFoundException) { $currentLocale = $fallbackLocale; } $translatableEntity->setCurrentLocale($currentLocale); $translatableEntity->setFallbackLocale($fallbackLocale); }
  • 25. sylius.com 25 public function assignLocale( TranslatableInterface $translatableEntity ): void { $fallbackLocale = $this ->translationLocaleProvider ->getDefaultLocaleCode() ; try { $currentLocale = $this->localeContext->getLocaleCode(); } catch (LocaleNotFoundException) { $currentLocale = $fallbackLocale; } $translatableEntity->setCurrentLocale($currentLocale); $translatableEntity->setFallbackLocale($fallbackLocale); }
  • 26. sylius.com 26 public function assignLocale( TranslatableInterface $translatableEntity ): void { $fallbackLocale = $this ->translationLocaleProvider ->getDefaultLocaleCode() ; try { $currentLocale = $this->localeContext->getLocaleCode(); } catch (LocaleNotFoundException) { $currentLocale = $fallbackLocale; } $translatableEntity->setCurrentLocale($currentLocale); $translatableEntity->setFallbackLocale($fallbackLocale); }
  • 27. sylius.com 27 public function assignLocale( TranslatableInterface $translatableEntity ): void { $fallbackLocale = $this ->translationLocaleProvider ->getDefaultLocaleCode() ; try { $currentLocale = $this->localeContext->getLocaleCode(); } catch (LocaleNotFoundException) { $currentLocale = $fallbackLocale; } $translatableEntity->setCurrentLocale($currentLocale); $translatableEntity->setFallbackLocale($fallbackLocale); }
  • 28. sylius.com 28 if ($this->commandBasedChecker->isExecutedFromCLI()) { $translatableEntity->setCurrentLocale($fallbackLocale); return; } try { $currentLocale = $this->localeContext->getLocaleCode(); } catch (LocaleNotFoundException) { $currentLocale = $fallbackLocale; }
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 35. Photo by Pietro Mattia on Unsplash Second round - N+1
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41. sylius.com 41 public function findByCodes(array $codes): array { return $this->createQueryBuilder('o') ->andWhere('o.code IN (:codes)') ->setParameter('codes', $codes) ->getQuery() ->getResult() ; }
  • 42. sylius.com 42 public function findByCodes(array $codes): array { return $this->createQueryBuilder('o') ->addSelect('product') ->addSelect('channelPricings') ->addSelect('appliedPromotions') ->addSelect('productTaxon') ->addSelect('taxon') ->leftJoin('o.channelPricings', 'channelPricings') ->leftJoin('channelPricings.appliedPromotions', 'appliedPromotions') ->leftJoin('o.product', 'product') ->leftJoin('product.productTaxons', 'productTaxon') ->leftJoin('productTaxon.taxon', 'taxon') ->andWhere('o.code IN (:codes)') ->setParameter('codes', $codes) ->getQuery() ->getResult() ; }
  • 43. sylius.com 43 public function findByCodes(array $codes): array { return $this->createQueryBuilder('o') ->addSelect('product') ->addSelect('channelPricings') ->addSelect('appliedPromotions') ->addSelect('productTaxon') ->addSelect('taxon') ->leftJoin('o.channelPricings', 'channelPricings') ->leftJoin('channelPricings.appliedPromotions', 'appliedPromotions') ->leftJoin('o.product', 'product') ->leftJoin('product.productTaxons', 'productTaxon') ->leftJoin('productTaxon.taxon', 'taxon') ->andWhere('o.code IN (:codes)') ->setParameter('codes', $codes) ->getQuery() ->getResult() ; }
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 51. Photo by Ralfs Blumbergs on Unsplash Third round - EM Clear
  • 52. sylius.com 52 Up to this moment All operations were executed synchronously
  • 53.
  • 54. sylius.com 54 After implementation of EntityManagerClearer and switching to async processing
  • 55.
  • 57. Photo by Bastien Plu on Unsplash Summary
  • 58.
  • 59.
  • 60. Photo by Glen Rushton on Unsplash Final round - native query
  • 61.
  • 62.
  • 63.
  • 64. sylius.com 64 private function clearChannelPricing( ChannelPricingInterface $channelPricing ): void { if ($channelPricing->getAppliedPromotions()->isEmpty()) { return; } if ($channelPricing->getOriginalPrice() !== null) { $channelPricing->setPrice($channelPricing->getOriginalPrice()); } $channelPricing->clearAppliedPromotions(); }
  • 65. sylius.com 65 private function clearChannelPricing( ChannelPricingInterface $channelPricing ): void { if ($channelPricing->getAppliedPromotions()->isEmpty()) { return; } if ($channelPricing->getOriginalPrice() !== null) { $channelPricing->setPrice($channelPricing->getOriginalPrice()); } $channelPricing->clearAppliedPromotions(); }
  • 66. sylius.com 66 private function clearChannelPricing( ChannelPricingInterface $channelPricing ): void { if ($channelPricing->getAppliedPromotions()->isEmpty()) { return; } if ($channelPricing->getOriginalPrice() !== null) { $channelPricing->setPrice($channelPricing->getOriginalPrice()); } $channelPricing->clearAppliedPromotions(); }
  • 67. sylius.com 67 private function clearChannelPricing( ChannelPricingInterface $channelPricing ): void { if ($channelPricing->getAppliedPromotions()->isEmpty()) { return; } if ($channelPricing->getOriginalPrice() !== null) { $channelPricing->setPrice($channelPricing->getOriginalPrice()); } $channelPricing->clearAppliedPromotions(); }
  • 68. sylius.com 68 public function __invoke( ApplyCatalogPromotionsOnVariants $updateVariants ): void { $catalogPromotions = $this->catalogPromotionsProvider->provide(); $variants = $this->productVariantRepository->findByCodes( $updateVariants->variantsCodes ); foreach ($variants as $variant) { $this->clearer->clearVariant($variant); foreach ($catalogPromotions as $promotion) { $this->catalogPromotionApplicator->applyOnVariant( $variant, $promotion ); } } }
  • 69. sylius.com 69 public function __invoke( ApplyCatalogPromotionsOnVariants $updateVariants ): void { $catalogPromotions = $this->catalogPromotionsProvider->provide(); $variants = $this->productVariantRepository->findByCodes( $updateVariants->variantsCodes ); foreach ($variants as $variant) { $this->clearer->clearVariant($variant); foreach ($catalogPromotions as $promotion) { $this->catalogPromotionApplicator->applyOnVariant( $variant, $promotion ); } } }
  • 70. sylius.com 70 public function __invoke( ApplyCatalogPromotionsOnVariants $updateVariants ): void { $catalogPromotions = $this->catalogPromotionsProvider->provide(); $variants = $this->productVariantRepository->findByCodes( $updateVariants->variantsCodes ); foreach ($variants as $variant) { $this->clearer->clearVariant($variant); foreach ($catalogPromotions as $promotion) { $this->catalogPromotionApplicator->applyOnVariant( $variant, $promotion ); } } }
  • 71. sylius.com 71 public function __invoke( ApplyCatalogPromotionsOnVariants $updateVariants ): void { $catalogPromotions = $this->catalogPromotionsProvider->provide(); $variants = $this->productVariantRepository->findByCodes( $updateVariants->variantsCodes ); foreach ($variants as $variant) { $this->clearer->clearVariant($variant); foreach ($catalogPromotions as $promotion) { $this->catalogPromotionApplicator->applyOnVariant( $variant, $promotion ); } } }
  • 72. sylius.com 72 public function __invoke( ApplyCatalogPromotionsOnVariants $updateVariants ): void { $catalogPromotions = $this->catalogPromotionsProvider->provide(); $variants = $this->productVariantRepository->findByCodes( $updateVariants->variantsCodes ); foreach ($variants as $variant) { $this->clearer->clearVariant($variant); foreach ($catalogPromotions as $promotion) { $this->catalogPromotionApplicator->applyOnVariant( $variant, $promotion ); } } }
  • 73. sylius.com 73 public function __invoke( ApplyCatalogPromotionsOnVariants $updateVariants ): void { $catalogPromotions = $this->catalogPromotionsProvider->provide(); $variants = $this->productVariantRepository->findByCodes( $updateVariants->variantsCodes ); foreach ($variants as $variant) { $this->clearer->clearVariant($variant); foreach ($catalogPromotions as $promotion) { $this->catalogPromotionApplicator->applyOnVariant( $variant, $promotion ); } } }
  • 74. sylius.com 74 public function __invoke( ApplyCatalogPromotionsOnVariants $updateVariants ): void { $catalogPromotions = $this->catalogPromotionsProvider->provide(); $variants = $this->productVariantRepository->findByCodes( $updateVariants->variantsCodes ); foreach ($variants as $variant) { $this->clearer->clearVariant($variant); foreach ($catalogPromotions as $promotion) { $this->catalogPromotionApplicator->applyOnVariant( $variant, $promotion ); } } }
  • 75. sylius.com 75 foreach ($variants as $variant) { $this->clearer->clearVariant($variant); } $codes = array_column($updateVariants->variantsCodes, 'code'); $connection = $this->entityManager->getConnection(); $connection->executeQuery(' DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id WHERE spv.code IN (?)’, [$codes], [Connection::PARAM_STR_ARRAY] ); foreach ($variants as $variant) { // Apply Catalog promotion }
  • 76. sylius.com 76 foreach ($variants as $variant) { $this->clearer->clearVariant($variant); } $codes = array_column($updateVariants->variantsCodes, 'code'); $connection = $this->entityManager->getConnection(); $connection->executeQuery(' DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id WHERE spv.code IN (?)’, [$codes], [Connection::PARAM_STR_ARRAY] ); foreach ($variants as $variant) { // Apply Catalog promotion }
  • 77. sylius.com 77 foreach ($variants as $variant) { $this->clearer->clearVariant($variant); } $codes = array_column($updateVariants->variantsCodes, 'code'); $connection = $this->entityManager->getConnection(); $connection->executeQuery(' DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id WHERE spv.code IN (?)’, [$codes], [Connection::PARAM_STR_ARRAY] ); foreach ($variants as $variant) { // Apply Catalog promotion }
  • 78. sylius.com 78 foreach ($variants as $variant) { $this->clearer->clearVariant($variant); } $codes = array_column($updateVariants->variantsCodes, 'code'); $connection = $this->entityManager->getConnection(); $connection->executeQuery(' DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id WHERE spv.code IN (?)’, [$codes], [Connection::PARAM_STR_ARRAY] ); foreach ($variants as $variant) { // Apply Catalog promotion }
  • 79. sylius.com 79 foreach ($variants as $variant) { $this->clearer->clearVariant($variant); } $codes = array_column($updateVariants->variantsCodes, 'code'); $connection = $this->entityManager->getConnection(); $connection->executeQuery(' DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id WHERE spv.code IN (?)’, [$codes], [Connection::PARAM_STR_ARRAY] ); foreach ($variants as $variant) { // Apply Catalog promotion }
  • 80. sylius.com 80 foreach ($variants as $variant) { $this->clearer->clearVariant($variant); } $codes = array_column($updateVariants->variantsCodes, 'code'); $connection = $this->entityManager->getConnection(); $connection->executeQuery(' DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id WHERE spv.code IN (?)’, [$codes], [Connection::PARAM_STR_ARRAY] ); foreach ($variants as $variant) { // Apply Catalog promotion }
  • 81. sylius.com 81 foreach ($variants as $variant) { $this->clearer->clearVariant($variant); } $codes = array_column($updateVariants->variantsCodes, 'code'); $connection = $this->entityManager->getConnection(); $connection->executeQuery(' DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id WHERE spv.code IN (?)’, [$codes], [Connection::PARAM_STR_ARRAY] ); foreach ($variants as $variant) { // Apply Catalog promotion }
  • 82. sylius.com 82 foreach ($variants as $variant) { $this->clearer->clearVariant($variant); } $codes = array_column($updateVariants->variantsCodes, 'code'); $connection = $this->entityManager->getConnection(); $connection->executeQuery(' DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id WHERE spv.code IN (?)’, [$codes], [Connection::PARAM_STR_ARRAY] ); foreach ($variants as $variant) { // Apply Catalog promotion }
  • 83. sylius.com 83 foreach ($variants as $variant) { $this->clearer->clearVariant($variant); } $codes = array_column($updateVariants->variantsCodes, 'code'); $connection = $this->entityManager->getConnection(); $connection->executeQuery(' DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id WHERE spv.code IN (?)’, [$codes], [Connection::PARAM_STR_ARRAY] ); foreach ($variants as $variant) { // Apply Catalog promotion }
  • 84.
  • 85.
  • 86.
  • 87.
  • 88. sylius.com 88 It didn’t work according to acceptance tests!
  • 89.
  • 90.
  • 91.
  • 92. sylius.com 92 public function __invoke( ClearCatalogPromotionsOnVariants $clearCatalogPromotionsOnVariants ): void { $codes = array_column($clearCatalogPromotionsOnVariants->variantsCodes, ‘code'); $connection = $this->entityManager->getConnection(); $connection->executeQuery(' UPDATE sylius_channel_pricing scp INNER JOIN sylius_channel_pricing_catalog_promotions scpcp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id SET scp.price=scp.original_price WHERE spv.code IN (?);', [$codes], [Connection::PARAM_STR_ARRAY]); $connection->executeQuery(' DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id WHERE spv.code IN (?)', [$codes], [Connection::PARAM_STR_ARRAY]); }
  • 93. sylius.com 93 public function __invoke( ClearCatalogPromotionsOnVariants $clearCatalogPromotionsOnVariants ): void { $codes = array_column($clearCatalogPromotionsOnVariants->variantsCodes, ‘code'); $connection = $this->entityManager->getConnection(); $connection->executeQuery(' UPDATE sylius_channel_pricing scp INNER JOIN sylius_channel_pricing_catalog_promotions scpcp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id SET scp.price=scp.original_price WHERE spv.code IN (?);', [$codes], [Connection::PARAM_STR_ARRAY]); $connection->executeQuery(' DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id WHERE spv.code IN (?)', [$codes], [Connection::PARAM_STR_ARRAY]); }
  • 94. sylius.com 94 public function __invoke( ClearCatalogPromotionsOnVariants $clearCatalogPromotionsOnVariants ): void { $codes = array_column($clearCatalogPromotionsOnVariants->variantsCodes, ‘code'); $connection = $this->entityManager->getConnection(); $connection->executeQuery(' UPDATE sylius_channel_pricing scp INNER JOIN sylius_channel_pricing_catalog_promotions scpcp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id SET scp.price=scp.original_price WHERE spv.code IN (?);', [$codes], [Connection::PARAM_STR_ARRAY]); $connection->executeQuery(' DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id WHERE spv.code IN (?)', [$codes], [Connection::PARAM_STR_ARRAY]); }
  • 95. sylius.com 95 public function __invoke( ClearCatalogPromotionsOnVariants $clearCatalogPromotionsOnVariants ): void { $codes = array_column($clearCatalogPromotionsOnVariants->variantsCodes, ‘code'); $connection = $this->entityManager->getConnection(); $connection->executeQuery(' UPDATE sylius_channel_pricing scp INNER JOIN sylius_channel_pricing_catalog_promotions scpcp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id SET scp.price=scp.original_price WHERE spv.code IN (?);', [$codes], [Connection::PARAM_STR_ARRAY]); $connection->executeQuery(' DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id WHERE spv.code IN (?)', [$codes], [Connection::PARAM_STR_ARRAY]); }
  • 96. sylius.com 96 public function __invoke( ClearCatalogPromotionsOnVariants $clearCatalogPromotionsOnVariants ): void { $codes = array_column($clearCatalogPromotionsOnVariants->variantsCodes, ‘code'); $connection = $this->entityManager->getConnection(); $connection->executeQuery(' UPDATE sylius_channel_pricing scp INNER JOIN sylius_channel_pricing_catalog_promotions scpcp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id SET scp.price=scp.original_price WHERE spv.code IN (?);', [$codes], [Connection::PARAM_STR_ARRAY]); $connection->executeQuery(' DELETE scpcp FROM sylius_channel_pricing_catalog_promotions scpcp JOIN sylius_channel_pricing scp ON scpcp.channel_pricing_id = scp.id JOIN sylius_product_variant spv ON scp.product_variant_id = spv.id WHERE spv.code IN (?)', [$codes], [Connection::PARAM_STR_ARRAY]); }
  • 97.
  • 98.
  • 99.
  • 100.
  • 101. sylius.com ? 101 What if we change the catalog promotion con fi guration?
  • 102.
  • 103.
  • 104.
  • 105.
  • 107.
  • 108. Photo by Mikhail Vasilyev on Unsplash 03 Takeaways
  • 109. sylius.com 109 Check the highest class in your callgraph And look for bugs Remember to clear Entity Manager when batch processing Unless you are executing asynchronously messages with Symfony Messenger Load all data required to perform operation But not more Pure DQL may bring bene fi ts But is hard to do it properly for complicated objects or mix it with ORM
  • 110. sylius.com 110 SyliusCon This autumn - at 27th of October In a Sylius hometown: Łódź
  • 111. sylius.com 111 Thank you! Photo by Maksym Harbar on Unsplash