diff --git a/.github/workflows/databases.yml b/.github/workflows/databases.yml index 05c9c913eff3..689fb4ccde7d 100644 --- a/.github/workflows/databases.yml +++ b/.github/workflows/databases.yml @@ -132,49 +132,49 @@ jobs: DB_CONNECTION: mysql DB_USERNAME: root - # pgsql: - # runs-on: ubuntu-20.04 - - # services: - # postgresql: - # image: postgres:14 - # env: - # POSTGRES_DB: forge - # POSTGRES_USER: forge - # POSTGRES_PASSWORD: password - # ports: - # - 5432:5432 - # options: --health-cmd=pg_isready --health-interval=10s --health-timeout=5s --health-retries=3 - - # strategy: - # fail-fast: true - - # name: PostgreSQL 14 - - # steps: - # - name: Checkout code - # uses: actions/checkout@v2 - - # - name: Setup PHP - # uses: shivammathur/setup-php@v2 - # with: - # php-version: 8.1 - # extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_pgsql - # tools: composer:v2 - # coverage: none - - # - name: Install dependencies - # uses: nick-invision/retry@v1 - # with: - # timeout_minutes: 5 - # max_attempts: 5 - # command: composer update --prefer-stable --prefer-dist --no-interaction --no-progress - - # - name: Execute tests - # run: vendor/bin/phpunit tests/Integration/Database --verbose --exclude-group MySQL - # env: - # DB_CONNECTION: pgsql - # DB_PASSWORD: password + pgsql: + runs-on: ubuntu-20.04 + + services: + postgresql: + image: postgres:14 + env: + POSTGRES_DB: forge + POSTGRES_USER: forge + POSTGRES_PASSWORD: password + ports: + - 5432:5432 + options: --health-cmd=pg_isready --health-interval=10s --health-timeout=5s --health-retries=3 + + strategy: + fail-fast: true + + name: PostgreSQL 14 + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.1 + extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_pgsql + tools: composer:v2 + coverage: none + + - name: Install dependencies + uses: nick-invision/retry@v1 + with: + timeout_minutes: 5 + max_attempts: 5 + command: composer update --prefer-stable --prefer-dist --no-interaction --no-progress + + - name: Execute tests + run: vendor/bin/phpunit tests/Integration/Database --verbose --exclude-group MySQL + env: + DB_CONNECTION: pgsql + DB_PASSWORD: password mssql: runs-on: ubuntu-20.04 diff --git a/src/Illuminate/Console/Scheduling/Event.php b/src/Illuminate/Console/Scheduling/Event.php index 58cee5281cb1..4de88f163dbf 100644 --- a/src/Illuminate/Console/Scheduling/Event.php +++ b/src/Illuminate/Console/Scheduling/Event.php @@ -17,6 +17,7 @@ use Illuminate\Support\Traits\ReflectsClosures; use Psr\Http\Client\ClientExceptionInterface; use Symfony\Component\Process\Process; +use Throwable; class Event { @@ -218,11 +219,17 @@ public function mutexName() */ protected function runCommandInForeground(Container $container) { - $this->callBeforeCallbacks($container); + try { + $this->callBeforeCallbacks($container); - $this->exitCode = Process::fromShellCommandline($this->buildCommand(), base_path(), null, null, null)->run(); + $this->exitCode = Process::fromShellCommandline( + $this->buildCommand(), base_path(), null, null, null + )->run(); - $this->callAfterCallbacks($container); + $this->callAfterCallbacks($container); + } finally { + $this->removeMutex(); + } } /** @@ -233,9 +240,15 @@ protected function runCommandInForeground(Container $container) */ protected function runCommandInBackground(Container $container) { - $this->callBeforeCallbacks($container); + try { + $this->callBeforeCallbacks($container); + + Process::fromShellCommandline($this->buildCommand(), base_path(), null, null, null)->run(); + } catch (Throwable $exception) { + $this->removeMutex(); - Process::fromShellCommandline($this->buildCommand(), base_path(), null, null, null)->run(); + throw $exception; + } } /** @@ -275,7 +288,11 @@ public function callAfterCallbacksWithExitCode(Container $container, $exitCode) { $this->exitCode = (int) $exitCode; - $this->callAfterCallbacks($container); + try { + $this->callAfterCallbacks($container); + } finally { + $this->removeMutex(); + } } /** @@ -647,9 +664,7 @@ public function withoutOverlapping($expiresAt = 1440) $this->expiresAt = $expiresAt; - return $this->then(function () { - $this->mutex->forget($this); - })->skip(function () { + return $this->skip(function () { return $this->mutex->exists($this); }); } @@ -915,4 +930,16 @@ public function preventOverlapsUsing(EventMutex $mutex) return $this; } + + /** + * Delete the mutex for the event. + * + * @return void + */ + protected function removeMutex() + { + if ($this->withoutOverlapping) { + $this->mutex->forget($this); + } + } } diff --git a/src/Illuminate/Database/Schema/PostgresBuilder.php b/src/Illuminate/Database/Schema/PostgresBuilder.php index bceb42d7fb9f..1b3ca413f690 100755 --- a/src/Illuminate/Database/Schema/PostgresBuilder.php +++ b/src/Illuminate/Database/Schema/PostgresBuilder.php @@ -237,7 +237,7 @@ protected function parseSearchPath($searchPath) $searchPath = $matches[0]; } - array_walk($searchPath, function (&$schema) { + array_walk($searchPath ?? [], function (&$schema) { $schema = trim($schema, '\'"'); $schema = $schema === '$user' @@ -245,6 +245,6 @@ protected function parseSearchPath($searchPath) : $schema; }); - return $searchPath; + return $searchPath ?? []; } } diff --git a/src/Illuminate/Queue/SqsQueue.php b/src/Illuminate/Queue/SqsQueue.php index 1ef834bb7bae..dab07b701a6a 100755 --- a/src/Illuminate/Queue/SqsQueue.php +++ b/src/Illuminate/Queue/SqsQueue.php @@ -188,10 +188,28 @@ public function getQueue($queue) $queue = $queue ?: $this->default; return filter_var($queue, FILTER_VALIDATE_URL) === false - ? rtrim($this->prefix, '/').'/'.Str::finish($queue, $this->suffix) + ? $this->suffixQueue($queue, $this->suffix) : $queue; } + /** + * Add the given suffix to the given queue name. + * + * @param string $queue + * @param string $suffix + * @return string + */ + protected function suffixQueue($queue, $suffix = '') + { + if (Str::endsWith($queue, '.fifo')) { + $queue = Str::beforeLast($queue, '.fifo'); + + return rtrim($this->prefix, '/').'/'.Str::finish($queue, $suffix).'.fifo'; + } + + return rtrim($this->prefix, '/').'/'.Str::finish($queue, $this->suffix); + } + /** * Get the underlying SQS instance. * diff --git a/src/Illuminate/View/Engines/EngineResolver.php b/src/Illuminate/View/Engines/EngineResolver.php index 6a5b80026342..674040770be2 100755 --- a/src/Illuminate/View/Engines/EngineResolver.php +++ b/src/Illuminate/View/Engines/EngineResolver.php @@ -32,7 +32,7 @@ class EngineResolver */ public function register($engine, Closure $resolver) { - unset($this->resolved[$engine]); + $this->forget($engine); $this->resolvers[$engine] = $resolver; } diff --git a/tests/Queue/QueueSqsQueueTest.php b/tests/Queue/QueueSqsQueueTest.php index 0ae708f91e9f..2b8c8d7bc9c2 100755 --- a/tests/Queue/QueueSqsQueueTest.php +++ b/tests/Queue/QueueSqsQueueTest.php @@ -144,6 +144,16 @@ public function testGetQueueProperlyResolvesUrlWithPrefix() $this->assertEquals($queueUrl, $queue->getQueue('test')); } + public function testGetQueueProperlyResolvesFifoUrlWithPrefix() + { + $this->queueName = 'emails.fifo'; + $this->queueUrl = $this->prefix.$this->queueName; + $queue = new SqsQueue($this->sqs, $this->queueName, $this->prefix); + $this->assertEquals($this->queueUrl, $queue->getQueue(null)); + $queueUrl = $this->baseUrl.'/'.$this->account.'/test.fifo'; + $this->assertEquals($queueUrl, $queue->getQueue('test.fifo')); + } + public function testGetQueueProperlyResolvesUrlWithoutPrefix() { $queue = new SqsQueue($this->sqs, $this->queueUrl); @@ -152,6 +162,16 @@ public function testGetQueueProperlyResolvesUrlWithoutPrefix() $this->assertEquals($queueUrl, $queue->getQueue($queueUrl)); } + public function testGetQueueProperlyResolvesFifoUrlWithoutPrefix() + { + $this->queueName = 'emails.fifo'; + $this->queueUrl = $this->prefix.$this->queueName; + $queue = new SqsQueue($this->sqs, $this->queueUrl); + $this->assertEquals($this->queueUrl, $queue->getQueue(null)); + $fifoQueueUrl = $this->baseUrl.'/'.$this->account.'/test.fifo'; + $this->assertEquals($fifoQueueUrl, $queue->getQueue($fifoQueueUrl)); + } + public function testGetQueueProperlyResolvesUrlWithSuffix() { $queue = new SqsQueue($this->sqs, $this->queueName, $this->prefix, $suffix = '-staging'); @@ -160,6 +180,15 @@ public function testGetQueueProperlyResolvesUrlWithSuffix() $this->assertEquals($queueUrl, $queue->getQueue('test')); } + public function testGetQueueProperlyResolvesFifoUrlWithSuffix() + { + $this->queueName = 'emails.fifo'; + $queue = new SqsQueue($this->sqs, $this->queueName, $this->prefix, $suffix = '-staging'); + $this->assertEquals("{$this->prefix}emails-staging.fifo", $queue->getQueue(null)); + $queueUrl = $this->baseUrl.'/'.$this->account.'/test'.$suffix.'.fifo'; + $this->assertEquals($queueUrl, $queue->getQueue('test.fifo')); + } + public function testGetQueueEnsuresTheQueueIsOnlySuffixedOnce() { $queue = new SqsQueue($this->sqs, "{$this->queueName}-staging", $this->prefix, $suffix = '-staging'); @@ -167,4 +196,12 @@ public function testGetQueueEnsuresTheQueueIsOnlySuffixedOnce() $queueUrl = $this->baseUrl.'/'.$this->account.'/test'.$suffix; $this->assertEquals($queueUrl, $queue->getQueue('test-staging')); } + + public function testGetFifoQueueEnsuresTheQueueIsOnlySuffixedOnce() + { + $queue = new SqsQueue($this->sqs, "{$this->queueName}-staging.fifo", $this->prefix, $suffix = '-staging'); + $this->assertEquals("{$this->prefix}{$this->queueName}{$suffix}.fifo", $queue->getQueue(null)); + $queueUrl = $this->baseUrl.'/'.$this->account.'/test'.$suffix.'.fifo'; + $this->assertEquals($queueUrl, $queue->getQueue('test-staging.fifo')); + } }