Concurrent requests trying to create the same enti

2019-04-16 07:42发布

I have a function that looks like this:

function findByAndCreateIfNotExists($criteria){

    $entity = $this->findBy(['criteria'=>$criteria]);

    // this is the problem area, if request 1 is still creating the entity, request 2 won't find it yet.

    if (! $entity) {
        $entity = $this->createEntity($criteria);
    }

    return $entity;
}

This function is used by various requests, and I've found that concurrent requests will sometimes try to create the same entity, throwing a DBALException complaining about duplicate entries for the unique key.

I've thought about LOCK TABLES as mentioned here: How to lock a whole table in symfony2 with doctrine2?

But just given the fact there is no function to do this in Doctrine, I'm guessing it's not the preferred method. My question is, how can I prevent concurrent requests attempting to create the same entity and always return the correct one?

2条回答
何必那么认真
2楼-- · 2019-04-16 08:18

As idea create own locking system:

something like:

function findByAndCreateIfNotExists($criteria){

    $entity = $this->findBy(['criteria'=>$criteria]);

    // this is the problem area, if request 1 is still creating the entity, request 2 won't find it yet.
    $lockPath ='/tmp/'.md5($criteria).'.lock';

    if (! $entity && !file_exists($lockPath)) {
        $fh = fopen($lockPath, 'w') or die("Can't create file");
        $entity = $this->createEntity($criteria);
        unlink(($lockPath);
    }

    return $entity;
}
查看更多
混吃等死
3楼-- · 2019-04-16 08:30

But from what you told I think you are doing in wrong direction and it is better to rebuild app architecture little bit and put RabbitMQ queue as intermediate point to serve your requests

查看更多
登录 后发表回答