Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EntityListener not called since 2.2.0 under prod env only #1249

Closed
PierrickMartos opened this issue Nov 10, 2020 · 17 comments
Closed

EntityListener not called since 2.2.0 under prod env only #1249

PierrickMartos opened this issue Nov 10, 2020 · 17 comments

Comments

@PierrickMartos
Copy link

Hello,

Since the release of doctrine-bundle:2.2.0, we are facing a strange issue with our EntityListeners not called only when symfony run under prod env. Note, It works normally on dev and test env.

To give you more context, our EntityListener is registered on a MappedSuperClasss and not directly on the final Entity class. But we never had an issue with this before the 2.2.0 release.

Here is how we register our EntityListener (the service is registered inside a vendor managed by us):

  SAM\DealFlowBundle\EventListener\DealFlowListener:
    arguments:
      - '%sam_entities%'
    tags:
      - { name: doctrine.orm.entity_listener, event: prePersist, entity: SAM\DealFlowBundle\Entity\DealFlow, method: prePersist, lazy: true, priority: 100 }

Here is the DealFlowListener:

<?php

namespace SAM\DealFlowBundle\EventListener;

use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use SAM\CommonBundle\Utils\LoggerUtils;
use SAM\DealFlowBundle\Entity\DealFlow;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

/**
 * class DealFlowListener.
 */
class DealFlowListener
{
    /**
     * @var TokenStorageInterface
     */
    private $tokenStorage;

    /**
     * @var array
     */
    protected $entities;

    /**
     * @var EntityManagerInterface
     */
    protected $em;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * DealFlowListener constructor.
     *
     * @param array                 $entities
     * @param TokenStorageInterface $tokenStorage
     */
    public function __construct($entities, TokenStorageInterface $tokenStorage, LoggerInterface $logger)
    {
        $this->tokenStorage = $tokenStorage;
        $this->entities = $entities;
        $this->logger = $logger;
    }

    /**
     * @param DealFlow                 $deal
     * @param LifecycleEventArgs $args
     *
     * @throws \Exception
     */
    public function prePersist(DealFlow $deal, LifecycleEventArgs $args)
    {
        $this->logger->info('[DealFlowListener] prePersist called');

        // Some code here removed from this snippet to keep it simple
}

The mappedsuperclass, DealFlow:

<?php

namespace SAM\DealFlowBundle\Entity;

use ...

/**
 * @ORM\Table(
 *     name="deal_flow",
 *     indexes={@ORM\Index(name="project_name_index", columns={"project_name"}, flags={"fulltext"})},
 *     uniqueConstraints={@ORM\UniqueConstraint(name="legal_entity_deal_flow", columns={"legal_entity_id", "legal_entity_deal_flow_id"})}
 * )
 * @ORM\MappedSuperclass()
 * @ORM\HasLifecycleCallbacks()
 *
 * @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false)
 */
class DealFlow
{
    // ...
}

And the DealFlow final entity:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use SAM\DealFlowBundle\Entity\DealFlow as BaseDealFlow;

/**
 * @ORM\Entity
 */
class DealFlow extends BaseDealFlow
{

}

Also, when i run bin/console --env=prod debug:container DealFlowListener on production, the service appears and it's registered into the container :

image

For now we have fix our composer.json to doctrine-bundle 2.1.2 and it works.

Our environment :

  • Symfony 4.4.16

Our composer.json:

{
    "name": "*******",
    "description": "",
    "license": "proprietary",
    "type": "project",
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "App\\Tests\\": "tests/"
        }
    },
    "require": {
        "php": ">=7.2",
        "ext-ctype": "*",
        "ext-dom": "*",
        "ext-gd": "*",
        "ext-iconv": "*",
        "ext-intl": "*",
        "ext-json": "*",
        "ext-ldap": "*",
        "ext-pdo": "*",
        "ext-soap": "*",
        "ext-zip": "*",
        "ext-zlib": "*",
        "algolia/search-bundle": "^4.1",
        "anyx/login-gate-bundle": "^2.0",
        "beberlei/doctrineextensions": "^1.2",
        "cocur/slugify": "^4.0",
        "composer/package-versions-deprecated": "^1.8",
        "damienharper/doctrine-audit-bundle": "^3.4",
        "debril/rss-atom-bundle": "^5.0",
        "doctrine/common": "^2.11",
        "doctrine/doctrine-bundle": "^2.1",
        "doctrine/doctrine-fixtures-bundle": "^3.3",
        "doctrine/doctrine-migrations-bundle": "^3.0",
        "doctrine/orm": "^2.7",
        "eightpoints/guzzle-bundle": "^8.2",
        "endroid/qr-code": "^3.9",
        "endroid/qr-code-bundle": "^3.4",
        "enqueue/amqp-lib": "^0.9.12",
        "enqueue/enqueue-bundle": "^0.10.3",
        "evence/soft-deleteable-extension-bundle": "^2.0.0",
        "fresh/doctrine-enum-bundle": "^6.6",
        "friendsofsymfony/ckeditor-bundle": "^2.2",
        "friendsofsymfony/jsrouting-bundle": "^2.6",
        "friendsofsymfony/user-bundle": "^2.1",
        "fzaninotto/faker": "^1.9",
        "garethp/php-ews": "^0.9.9",
        "guzzlehttp/guzzle": "~6.0",
        "incenteev/composer-parameter-handler": "^2.1",
        "jeroendesloovere/vcard": "^1.7",
        "knplabs/knp-gaufrette-bundle": "^0.7.1",
        "knplabs/knp-paginator-bundle": "^5.3",
        "knplabs/knp-snappy-bundle": "^1.7",
        "knplabs/knp-time-bundle": "^1.13",
        "kunalvarma05/dropbox-php-sdk": "^0.2.1",
        "lexxpavlov/settingsbundle": "^1.5.1",
        "liip/imagine-bundle": "^2.3",
        "loilo/fuse": "^3.6",
        "monolog/monolog": "^1.3",
        "mysam/environment-symfony-tools": "^2.0",
        "mysam/sortable-behavior-bundle": "^1.5",
        "nyholm/effective-interest-rate": "^1.0",
        "ocramius/proxy-manager": "2.1.*",
        "phpoffice/phpspreadsheet": "^1.15",
        "portphp/spreadsheet": "^1.0",
        "scheb/two-factor-bundle": "^4.18",
        "sensio/framework-extra-bundle": "^5.6",
        "sentry/sentry-symfony": "^3.5",
        "sonata-project/admin-bundle": "^3.63",
        "sonata-project/doctrine-extensions": "^1.9",
        "sonata-project/doctrine-orm-admin-bundle": "^3.22",
        "sonata-project/exporter": "^2.4",
        "sonata-project/form-extensions": "^1.6",
        "sonata-project/twig-extensions": "^1.4",
        "stechstudio/backoff": "^1.1",
        "stof/doctrine-extensions-bundle": "^1.5",
        "suncat/mobile-detect-bundle": "dev-master",
        "symfony/asset": "4.4.*",
        "symfony/cache": "4.4.*",
        "symfony/console": "4.4.*",
        "symfony/dotenv": "4.4.*",
        "symfony/flex": "^1.3.1",
        "symfony/framework-bundle": "4.4.*",
        "symfony/ldap": "4.4.*",
        "symfony/lock": "4.4.*",
        "symfony/mailer": "4.4.*",
        "symfony/monolog-bundle": "^3.5",
        "symfony/polyfill-apcu": "^1.18",
        "symfony/property-info": "4.4.*",
        "symfony/proxy-manager-bridge": "4.4.*",
        "symfony/serializer": "4.4.*",
        "symfony/translation": "4.4.*",
        "symfony/twig-bundle": "4.4.*",
        "twig/extensions": "^1.5",
        "twig/extra-bundle": "^2.12|^3.0",
        "twig/twig": "^2.12",
        "vich/uploader-bundle": "^1.15"
    },
    "require-dev": {
        "dama/doctrine-test-bundle": "^6.3",
        "doctrine/data-fixtures": "^1.4",
        "escapestudios/symfony2-coding-standard": "^3.11",
        "hautelook/alice-bundle": "^2.7",
        "johnkary/phpunit-speedtrap": "^3.2",
        "liuggio/fastest": "^1.7",
        "phpunit/phpunit": "8.5.8",
        "sempro/phpunit-pretty-print": "^1.2",
        "symfony/browser-kit": "^4.4",
        "symfony/css-selector": "4.4.*",
        "symfony/debug-bundle": "^4.4",
        "symfony/maker-bundle": "^1.21",
        "symfony/phpunit-bridge": "^5.1",
        "symfony/stopwatch": "^4.4",
        "symfony/var-dumper": "^4.4",
        "symfony/web-profiler-bundle": "^4.4",
        "symplify/easy-coding-standard": "^8.3",
        "theofidry/alice-data-fixtures": "^1.2"
    },
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/Software-For-Asset-Management/MobileDetectBundle"
        }
    ],
    "scripts": {
        "php-cs-fixer": "php vendor/friendsofphp/php-cs-fixer/php-cs-fixer fix vendor/sam/ --rules=@Symfony",
        "auto-scripts": {
            "cache:clear": "symfony-cmd",
            "ckeditor:install --clear=drop": "symfony-cmd",
            "assets:install --symlink --relative %PUBLIC_DIR%": "symfony-cmd",
            "sam:bin:install": "symfony-cmd",
            "assets:install %PUBLIC_DIR%": "symfony-cmd"
        },
        "post-install-cmd": [
            "@auto-scripts"
        ],
        "post-update-cmd": [
            "@auto-scripts"
        ]
    },
    "replace": {
        "paragonie/random_compat": "2.*",
        "symfony/polyfill-ctype": "*",
        "symfony/polyfill-iconv": "*",
        "symfony/polyfill-php71": "*",
        "symfony/polyfill-php70": "*",
        "symfony/polyfill-php56": "*"
    },
    "conflict": {
        "symfony/symfony": "*"
    },
    "config": {
        "preferred-install": {
            "*": "dist"
        },
        "sort-packages": true,
        "platform": {
            "php": "7.2.22"
        }
    },
    "extra": {
        "symfony": {
            "allow-contrib": true,
            "require": "4.4.*"
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true
}
@ostrolucky
Copy link
Member

This might very well be relevant #1196. Can you check if reverting those changes fixes your issue?

@PierrickMartos
Copy link
Author

PierrickMartos commented Nov 10, 2020

Hi @ostrolucky , i confirm, by reverting the two commits it works.

Here is the repository with the revert commits: https://github.com/Software-For-Asset-Management/DoctrineBundle/tree/master

@ostrolucky
Copy link
Member

Reproducer would be more useful. I'm unable to reproduce the issue. Tried with 2.2.0, under prod, with prePersist, with @ORM\MappedSuperclass, without @ORM\EntityListeners. Listener is triggered every time.

@zubov-ruslan
Copy link

Have the same issue with 2.2.0, with postPersist event.
For reproduce just needed run cache warm up:
bin/console cache:warmup --env=prod --no-debug

image

@ostrolucky
Copy link
Member

Indeed, I've reproduced this now

@dmaicher
Copy link
Contributor

@zubov-ruslan how exactly did you produce this diff in the screenshot? So in one default_metadata.php file the entitylisteners are present and in the other one not?

So far I can reproduce the missing case. But I cannot get it to show entitylisteners with 2.2.0 on my project

@zubov-ruslan
Copy link

@dmaicher it happens when you run bin/console cache:warmup --env=prod --no-debug for the second time

@ostrolucky
Copy link
Member

We decided to rollback the change which caused this issue. We released 2.2.1 which should fix your issue.

@ossinkine
Copy link
Contributor

@dmaicher Did you be able to reproduce?
@zubov-ruslan I can't reproduce even after run cache warmup multiple times. Do you do something between two calls of cache warmup? What is your metadata_cache_driver configuration? Do you use one or several entity managers?

@ostrolucky
Copy link
Member

Crucial part for reproducing is not defining @ORM\EntityListeners, listener needs to be solely defined via service definition only.

@ossinkine
Copy link
Contributor

@ostrolucky I've changed the listener definition from annotations to services, but everything still works. Just difference is a new service listener appears in the container.

@ostrolucky
Copy link
Member

bug is only in prod mode, with warmed up cache, since that's where feature works

@ossinkine
Copy link
Contributor

I've reproduced this. When entity listeners declared using services config they are added to metadata using event manager in AttachEntityListenersListener. When we warming up the php array cache we creating a clear ClassMetadataFactory with no event listeners. Using ClassMetadataFactory from container should fix this, I'll try to create a fix.

@ossinkine
Copy link
Contributor

Since AttachEntityListenersListener attach listener only once the best solution I see is to set the highest priority to DoctrineMetadataCacheWarmer.
@PierrickMartos @zubov-ruslan Could you please check this solution, please checkout to 2.2.0 and change this line ->addTag('kernel.cache_warmer'); to ->addTag('kernel.cache_warmer', ['priority' => 1000]);?

@ostrolucky
Copy link
Member

I would really suggest to give us a feedback and try the suggested changes if you don't want us to break your application again in next release.

@PierrickMartos
Copy link
Author

I try to find a moment to reproduce it in coming days

@PierrickMartos
Copy link
Author

Hi @ossinkine i've made some tests, i confirm that it doesnt work when changing ->addTag('kernel.cache_warmer'); to ->addTag('kernel.cache_warmer', ['priority' => 1000]);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants