Skip to content

Commit

Permalink
Merge branch '10.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
driesvints committed Oct 30, 2023
2 parents c948905 + 6f06ad4 commit 2acb803
Show file tree
Hide file tree
Showing 22 changed files with 528 additions and 36 deletions.
8 changes: 8 additions & 0 deletions src/Illuminate/Contracts/Events/ShouldDispatchAfterCommit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Illuminate\Contracts\Events;

interface ShouldDispatchAfterCommit
{
//
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Illuminate\Contracts\Events;

interface ShouldHandleEventsAfterCommit
{
//
}
8 changes: 8 additions & 0 deletions src/Illuminate/Contracts/Queue/ShouldQueueAfterCommit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Illuminate\Contracts\Queue;

interface ShouldQueueAfterCommit extends ShouldQueue
{
//
}
18 changes: 18 additions & 0 deletions src/Illuminate/Database/Eloquent/BroadcastsEventsAfterCommit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Illuminate\Database\Eloquent;

trait BroadcastsEventsAfterCommit
{
use BroadcastsEvents;

/**
* Determine if the model event broadcast queued job should be dispatched after all transactions are committed.
*
* @return bool
*/
public function broadcastAfterCommit()
{
return true;
}
}
30 changes: 15 additions & 15 deletions src/Illuminate/Database/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,29 +97,29 @@ class Builder implements BuilderContract
'avg',
'count',
'dd',
'ddRawSql',
'doesntExist',
'doesntExistOr',
'ddrawsql',
'doesntexist',
'doesntexistor',
'dump',
'dumpRawSql',
'dumprawsql',
'exists',
'existsOr',
'existsor',
'explain',
'getBindings',
'getConnection',
'getGrammar',
'getbindings',
'getconnection',
'getgrammar',
'implode',
'insert',
'insertGetId',
'insertOrIgnore',
'insertUsing',
'insertgetid',
'insertorignore',
'insertusing',
'max',
'min',
'raw',
'rawValue',
'rawvalue',
'sum',
'toSql',
'toRawSql',
'tosql',
'torawsql',
];

/**
Expand Down Expand Up @@ -1964,7 +1964,7 @@ public function __call($method, $parameters)
return $this->callNamedScope($method, $parameters);
}

if (in_array($method, $this->passthru)) {
if (in_array(strtolower($method), $this->passthru)) {
return $this->toBase()->{$method}(...$parameters);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ public function withAggregate($relations, $column, $function = null)
* Get the relation hashed column name for the given column and relation.
*
* @param string $column
* @param \Illuminate\Database\Eloquent\Relations\Relationship $relation
* @param \Illuminate\Database\Eloquent\Relations\Relation $relation
* @return string
*/
protected function getRelationHashedColumn($column, $relation)
Expand Down
79 changes: 73 additions & 6 deletions src/Illuminate/Events/Dispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Container\Container as ContainerContract;
use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;
use Illuminate\Contracts\Events\ShouldHandleEventsAfterCommit;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Queue\ShouldQueueAfterCommit;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\Macroable;
Expand Down Expand Up @@ -56,6 +59,13 @@ class Dispatcher implements DispatcherContract
*/
protected $queueResolver;

/**
* The database transaction manager resolver instance.
*
* @var callable
*/
protected $transactionManagerResolver;

/**
* Create a new event dispatcher instance.
*
Expand Down Expand Up @@ -235,10 +245,37 @@ public function dispatch($event, $payload = [], $halt = false)
// When the given "event" is actually an object we will assume it is an event
// object and use the class as the event name and this event itself as the
// payload to the handler, which makes object based events quite simple.
[$event, $payload] = $this->parseEventAndPayload(
$event, $payload
);
[$isEventObject, $event, $payload] = [
is_object($event),
...$this->parseEventAndPayload($event, $payload),
];

// If the event is not intended to be dispatched unless the current database
// transaction is successful, we'll register a callback which will handle
// dispatching this event on the next successful DB transaction commit.
if ($isEventObject &&
$payload[0] instanceof ShouldDispatchAfterCommit &&
! is_null($transactions = $this->resolveTransactionManager())) {
$transactions->addCallback(
fn () => $this->invokeListeners($event, $payload, $halt)
);

return null;
}

return $this->invokeListeners($event, $payload, $halt);
}

/**
* Broadcast an event and call its listeners.
*
* @param string|object $event
* @param mixed $payload
* @param bool $halt
* @return array|null
*/
protected function invokeListeners($event, $payload, $halt = false)
{
if ($this->shouldBroadcast($payload)) {
$this->broadcastEvent($payload[0]);
}
Expand Down Expand Up @@ -525,7 +562,9 @@ protected function createQueuedHandlerCallable($class, $method)
*/
protected function handlerShouldBeDispatchedAfterDatabaseTransactions($listener)
{
return ($listener->afterCommit ?? null) && $this->container->bound('db.transactions');
return (($listener->afterCommit ?? null) ||
$listener instanceof ShouldHandleEventsAfterCommit) &&
$this->resolveTransactionManager();
}

/**
Expand All @@ -540,7 +579,7 @@ protected function createCallbackForListenerRunningAfterCommits($listener, $meth
return function () use ($method, $listener) {
$payload = func_get_args();

$this->container->make('db.transactions')->addCallback(
$this->resolveTransactionManager()->addCallback(
function () use ($listener, $method, $payload) {
$listener->$method(...$payload);
}
Expand Down Expand Up @@ -624,7 +663,12 @@ protected function propagateListenerOptions($listener, $job)
return tap($job, function ($job) use ($listener) {
$data = array_values($job->data);

$job->afterCommit = property_exists($listener, 'afterCommit') ? $listener->afterCommit : null;
if ($listener instanceof ShouldQueueAfterCommit) {
$job->afterCommit = true;
} else {
$job->afterCommit = property_exists($listener, 'afterCommit') ? $listener->afterCommit : null;
}

$job->backoff = method_exists($listener, 'backoff') ? $listener->backoff(...$data) : ($listener->backoff ?? null);
$job->maxExceptions = $listener->maxExceptions ?? null;
$job->retryUntil = method_exists($listener, 'retryUntil') ? $listener->retryUntil(...$data) : null;
Expand Down Expand Up @@ -697,6 +741,29 @@ public function setQueueResolver(callable $resolver)
return $this;
}

/**
* Get the database transaction manager implementation from the resolver.
*
* @return \Illuminate\Database\DatabaseTransactionsManager|null
*/
protected function resolveTransactionManager()
{
return call_user_func($this->transactionManagerResolver);
}

/**
* Set the database transaction manager resolver implementation.
*
* @param callable $resolver
* @return $this
*/
public function setTransactionManagerResolver(callable $resolver)
{
$this->transactionManagerResolver = $resolver;

return $this;
}

/**
* Gets the raw, unprepared listeners.
*
Expand Down
4 changes: 4 additions & 0 deletions src/Illuminate/Events/EventServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ public function register()
$this->app->singleton('events', function ($app) {
return (new Dispatcher($app))->setQueueResolver(function () use ($app) {
return $app->make(QueueFactoryContract::class);
})->setTransactionManagerResolver(function () use ($app) {
return $app->bound('db.transactions')
? $app->make('db.transactions')
: null;
});
});
}
Expand Down
5 changes: 2 additions & 3 deletions src/Illuminate/Http/Client/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -339,9 +339,8 @@ public function throwIfStatus($statusCode)
*/
public function throwUnlessStatus($statusCode)
{
if (is_callable($statusCode) &&
! $statusCode($this->status(), $this)) {
return $this->throw();
if (is_callable($statusCode)) {
return $statusCode($this->status(), $this) ? $this : $this->throw();
}

return $this->status() === $statusCode ? $this : $this->throw();
Expand Down
8 changes: 7 additions & 1 deletion src/Illuminate/Mail/SendQueuedMailable.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Illuminate\Contracts\Mail\Factory as MailFactory;
use Illuminate\Contracts\Mail\Mailable as MailableContract;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueueAfterCommit;
use Illuminate\Queue\InteractsWithQueue;

class SendQueuedMailable
Expand Down Expand Up @@ -57,7 +58,12 @@ public function __construct(MailableContract $mailable)
{
$this->mailable = $mailable;

$this->afterCommit = property_exists($mailable, 'afterCommit') ? $mailable->afterCommit : null;
if ($mailable instanceof ShouldQueueAfterCommit) {
$this->afterCommit = true;
} else {
$this->afterCommit = property_exists($mailable, 'afterCommit') ? $mailable->afterCommit : null;
}

$this->connection = property_exists($mailable, 'connection') ? $mailable->connection : null;
$this->maxExceptions = property_exists($mailable, 'maxExceptions') ? $mailable->maxExceptions : null;
$this->queue = property_exists($mailable, 'queue') ? $mailable->queue : null;
Expand Down
9 changes: 8 additions & 1 deletion src/Illuminate/Notifications/SendQueuedNotifications.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Queue\ShouldQueueAfterCommit;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Queue\InteractsWithQueue;
Expand Down Expand Up @@ -80,7 +81,13 @@ public function __construct($notifiables, $notification, array $channels = null)
$this->tries = property_exists($notification, 'tries') ? $notification->tries : null;
$this->timeout = property_exists($notification, 'timeout') ? $notification->timeout : null;
$this->maxExceptions = property_exists($notification, 'maxExceptions') ? $notification->maxExceptions : null;
$this->afterCommit = property_exists($notification, 'afterCommit') ? $notification->afterCommit : null;

if ($notification instanceof ShouldQueueAfterCommit) {
$this->afterCommit = true;
} else {
$this->afterCommit = property_exists($notification, 'afterCommit') ? $notification->afterCommit : null;
}

$this->shouldBeEncrypted = $notification instanceof ShouldBeEncrypted;
}

Expand Down
20 changes: 19 additions & 1 deletion src/Illuminate/Queue/MaxAttemptsExceededException.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,23 @@

class MaxAttemptsExceededException extends RuntimeException
{
//
/**
* The job instance.
*
* @var \Illuminate\Contracts\Queue\Job|null
*/
public $job;

/**
* Create a new instance for the job.
*
* @param \Illuminate\Contracts\Queue\Job $job
* @return static
*/
public static function forJob($job)
{
return tap(new static($job->resolveName().' has been attempted too many times.'), function ($e) use ($job) {
$e->job = $job;
});
}
}
5 changes: 5 additions & 0 deletions src/Illuminate/Queue/Queue.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Illuminate\Container\Container;
use Illuminate\Contracts\Encryption\Encrypter;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueueAfterCommit;
use Illuminate\Queue\Events\JobQueued;
use Illuminate\Support\Arr;
use Illuminate\Support\InteractsWithTime;
Expand Down Expand Up @@ -325,6 +326,10 @@ function () use ($payload, $queue, $delay, $callback, $job) {
*/
protected function shouldDispatchAfterCommit($job)
{
if (is_object($job) && $job instanceof ShouldQueueAfterCommit) {
return true;
}

if (! $job instanceof Closure && is_object($job) && isset($job->afterCommit)) {
return $job->afterCommit;
}
Expand Down
13 changes: 12 additions & 1 deletion src/Illuminate/Queue/TimeoutExceededException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,16 @@

class TimeoutExceededException extends MaxAttemptsExceededException
{
//
/**
* Create a new instance for the job.
*
* @param \Illuminate\Contracts\Queue\Job $job
* @return static
*/
public static function forJob($job)
{
return tap(new static($job->resolveName().' has timed out.'), function ($e) use ($job) {
$e->job = $job;
});
}
}
8 changes: 2 additions & 6 deletions src/Illuminate/Queue/Worker.php
Original file line number Diff line number Diff line change
Expand Up @@ -782,9 +782,7 @@ public function kill($status = 0, $options = null)
*/
protected function maxAttemptsExceededException($job)
{
return new MaxAttemptsExceededException(
$job->resolveName().' has been attempted too many times.'
);
return MaxAttemptsExceededException::forJob($job);
}

/**
Expand All @@ -795,9 +793,7 @@ protected function maxAttemptsExceededException($job)
*/
protected function timeoutExceededException($job)
{
return new TimeoutExceededException(
$job->resolveName().' has timed out.'
);
return TimeoutExceededException::forJob($job);
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/Illuminate/Support/Facades/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* @method static void forget(string $event)
* @method static void forgetPushed()
* @method static \Illuminate\Events\Dispatcher setQueueResolver(callable $resolver)
* @method static \Illuminate\Events\Dispatcher setTransactionManagerResolver(callable $resolver)
* @method static array getRawListeners()
* @method static void macro(string $name, object|callable $macro)
* @method static void mixin(object $mixin, bool $replace = true)
Expand Down
Loading

0 comments on commit 2acb803

Please sign in to comment.