diff --git a/src/Git/CommitJob.php b/src/Git/CommitJob.php index 726443d76b4..8d5a651060f 100644 --- a/src/Git/CommitJob.php +++ b/src/Git/CommitJob.php @@ -3,15 +3,22 @@ namespace Statamic\Git; use Illuminate\Bus\Queueable; +use Illuminate\Contracts\Queue\ShouldBeUnique; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Support\Facades\Cache; use Statamic\Facades\Git; -class CommitJob implements ShouldQueue +class CommitJob implements ShouldBeUnique, ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable; + /** + * The number of seconds after which the job's unique lock will be released. + */ + public int $uniqueFor = 120; + /** * Create a new job instance. */ @@ -24,6 +31,8 @@ public function __construct(public $message = null, public $committer = null) */ public function handle() { - Git::as($this->committer)->commit($this->message); + $committer = Cache::pull('statamic-git-pending-saves', 0) > 1 ? null : $this->committer; + + Git::as($committer)->commit($this->message); } } diff --git a/src/Git/Git.php b/src/Git/Git.php index 473ce1e6ea0..368fd653964 100644 --- a/src/Git/Git.php +++ b/src/Git/Git.php @@ -4,6 +4,7 @@ use Illuminate\Filesystem\Filesystem; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Cache; use Statamic\Console\Processes\Git as GitProcess; use Statamic\Contracts\Auth\User as UserContract; use Statamic\Facades\Antlers; @@ -93,6 +94,8 @@ public function dispatchCommit($message = null) $message = null; } + Cache::increment('statamic-git-pending-saves'); + CommitJob::dispatch($message, $this->authenticatedUser()) ->onConnection(config('statamic.git.queue_connection')) ->delay($delayInMinutes ?? null); diff --git a/tests/Git/GitTest.php b/tests/Git/GitTest.php index 38c1a15b3f9..f6cf140e892 100644 --- a/tests/Git/GitTest.php +++ b/tests/Git/GitTest.php @@ -3,6 +3,7 @@ namespace Tests\Git; use Illuminate\Filesystem\Filesystem; +use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Queue; use PHPUnit\Framework\Attributes\Test; use Statamic\Console\Processes\Git as GitProcess; @@ -400,6 +401,44 @@ public function it_dispatches_commit_job() Queue::assertPushed(\Statamic\Git\CommitJob::class, 1); } + #[Test] + public function it_only_dispatches_one_commit_job_at_a_time() + { + Queue::fake(); + + Git::dispatchCommit(); + Git::dispatchCommit(); + Git::dispatchCommit(); + + Queue::assertPushed(\Statamic\Git\CommitJob::class, 1); + } + + #[Test] + public function it_attributes_coalesced_commits_to_the_configured_user() + { + Cache::put('statamic-git-pending-saves', 3); + + $user = User::make()->email('alice@example.com'); + + Git::shouldReceive('as')->with(null)->andReturnSelf()->once(); + Git::shouldReceive('commit')->with('Entry saved')->once(); + + (new \Statamic\Git\CommitJob('Entry saved', $user))->handle(); + } + + #[Test] + public function it_attributes_non_coalesced_commits_to_the_authenticated_user() + { + Cache::put('statamic-git-pending-saves', 1); + + $user = User::make()->email('alice@example.com'); + + Git::shouldReceive('as')->with($user)->andReturnSelf()->once(); + Git::shouldReceive('commit')->with('Entry saved')->once(); + + (new \Statamic\Git\CommitJob('Entry saved', $user))->handle(); + } + #[Test] public function it_doesnt_push_by_default() {