[12.x] Use displayName() for custom job identification#57499
Conversation
|
I think your idea has merit, but I personally don't like seeing things like this for BC: method_exists($job, 'jobTypeIdentifier') |
|
Just to clarify your BC concern:
Concern 1: Concern 2: While collision risk is small but not zero, an interface would avoid it entirely: interface HasJobTypeIdentifier
{
public function jobTypeIdentifier(): string;
}
$jobType = $job instanceof HasJobTypeIdentifier
? $job->jobTypeIdentifier()
: get_class($job);This requires explicit opt-in, which I'm fine with. Alternatively, |
|
I think you can just use the existing Mark as ready for review when the changes are made. 🫡 |
|
Updated to check for Why
|
|
I think what @taylorotwell was trying to say is that it should look something like this, which would be BC and use the frameworks existing API: return 'laravel_unique_job:'.$job->resolveName().':'.$uniqueId;Then the package would simply implement the |
|
Thank you for the suggestion. However, return 'laravel_unique_job:'.$job->job->resolveName().':'.$uniqueId;This approach presents issues where 1. Pre-dispatch context 2. Jobs without InteractsWithQueue Relying on the queue wrapper being available would break in above scenarios. The |
|
@taylorotwell I'd like to bring up one additional consideration regarding The method name suggests non-technical usage, as if it's purely for visual representation of jobs. However, this implementation gives it technical implications for lock/cache key generation, which could lead to unexpected behavior. In theory, developers could assign the same A potential solution would be to concatenate both the actual class name and the $jobName = method_exists($job, 'displayName')
? get_class($job).':'.$job->displayName()
: get_class($job);
return 'laravel_unique_job:'.$jobName.':'.$uniqueId;This approach would:
For now, I've kept the PR using |
| */ | ||
| public function __construct($event) | ||
| { | ||
| $this->uniqueId = get_class($event); |
There was a problem hiding this comment.
Did this need to be removed?
There was a problem hiding this comment.
I believe so, yes. Removing it avoids duplicating the event class name in the lock key.
BroadcastEvent::displayName() already returns get_class($this->event):
framework/src/Illuminate/Broadcasting/BroadcastEvent.php
Lines 203 to 211 in 9d517b6
So with the updated UniqueLock::getKey() now using displayName() for the job identifier, keeping that line would result in:
laravel_unique_job:App\Events\MyEvent:App\Events\MyEvent123
Instead of:
laravel_unique_job:App\Events\MyEvent:123
BroadcastManagerTest verifies this expected lock key format in these 3 tests:
framework/tests/Integration/Broadcasting/BroadcastManagerTest.php
Lines 68 to 108 in 9d517b6
This relates to my earlier comment (#57499 (comment)); if multiple jobs share the same displayName(), this PR could introduce lock collisions. I can update it to concatenate both class name and displayName() as proposed there if you prefer that approach.
|
Drafting pending response to above comment. Feel free to mark as ready for reviewed when answered. |
|
Thanks 👍 |
* Add jobTypeIdentifier() method for custom job identification * Use displayName() for custom job identification in locks and middleware * Update UniqueBroadcastEvent to work with displayName() in lock key
Problem
The queue system uses
get_class($job)to identify jobs for:UniqueLock::getKey())ThrottlesExceptions::getKey())WithoutOverlapping::getLockKey())This doesn't support job wrapper patterns where multiple actions use the same wrapper class. This affects popular packages:
Since all actions share the same wrapper class name, they incorrectly share the same lock/cache keys.
Solution
Add an optional
jobTypeIdentifier()method that jobs can implement to provide a custom identifier as an alternative toget_class().Before:
After:
Wrapper packages can then implement:
Changes
Applied the same pattern to all three identification points:
src/Illuminate/Bus/UniqueLock.phpsrc/Illuminate/Queue/Middleware/ThrottlesExceptions.phpsrc/Illuminate/Queue/Middleware/WithoutOverlapping.phpTests added for both default (
get_class()) and custom identifier behavior.Backward Compatibility
✅ Fully backward compatible, existing jobs continue using
get_class()as before.