schmittjoh / JMSJobQueueBundle

Run and Schedule Symfony Console Commands as Background Jobs
http://jmsyst.com/bundles/JMSJobQueueBundle
335 stars 254 forks source link

Constraint violations in jms_job_statistics #147

Open fduch opened 8 years ago

fduch commented 8 years ago

During RunCommand execution i often raise such an exception:

Job 226:   [Doctrine\DBAL\DBALException]                                                                                                                                                                                                     
Job 226:   An exception occurred while executing 'INSERT INTO jms_job_statistics (job_id, characteristic, createdAt, charValue) VALUES (:jobId, :name, :createdAt, :value)' with params ["226", "2016-09-08 14:43:02", "memory", 41265120]:  
Job 226:   SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '226-memory-2016-09-08 14:43:02' for key 'PRIMARY' 

The reason is that jms_job_statistics table has complex primary key consists of job_id, characteristic, createdAt columns. I am facing constraint violations for this key when there are several attempts to write job statistic during the same second (in this case all the values of key columns have the same value).

Theoretically we can try to reduce frequency of Application::onTick calls by increasing the ticks count in Application's declare statement, but this approach is not so reliable.

What if we change jms_job_statistics by creating autoincrement simple primary key and adding index for job_id column (for effective fetching statistics info for the job)?

gido commented 7 years ago

We encounter the same issue with long running job. I currently don't explain how the code can execute 10'000'000 ticks in the same second, I'm not enough familiar with PHP internal.

schmittjoh commented 7 years ago

Instead of changing the database, I would prefer if we ensure that we do not create a new entry for the same timestamp since sub-second resolution is probably not really helpful anyway.

This could be done by tracking the last timestamp we have inserted and just returning if the current timestamp is still the same in the onTick method.