Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run queue tests with Laravel 5.1 #507

Merged
merged 1 commit into from
Dec 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions features/fixtures/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ version: '3.8'

services:
laravel51:
init: true
build:
context: laravel51
args:
Expand Down
8 changes: 2 additions & 6 deletions features/fixtures/laravel51/.env
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,11 @@ APP_ENV=local
APP_DEBUG=true
APP_KEY=SomeRandomString

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
DB_CONNECTION=sqlite

CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync
QUEUE_DRIVER=database

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
Expand Down
3 changes: 3 additions & 0 deletions features/fixtures/laravel51/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ COPY --from=composer:2.2 /usr/bin/composer /usr/local/bin/composer
RUN composer install --no-dev
RUN php artisan key:generate

# create database & apply migrations
RUN touch database/database.sqlite && php artisan migrate --no-interaction

CMD php artisan serve --port=8000 --host=0.0.0.0
8 changes: 8 additions & 0 deletions features/fixtures/laravel51/app/Http/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@
return view('handlederror');
});

Route::get('/queue/unhandled', function () {
Queue::push(new \App\Jobs\UnhandledJob());
});

Route::get('/queue/handled', function () {
Queue::push(new \App\Jobs\HandledJob());
});

/**
* Return some diagnostics if an OOM did not happen when it should have.
*
Expand Down
22 changes: 22 additions & 0 deletions features/fixtures/laravel51/app/Jobs/HandledJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace App\Jobs;

use Exception;
use App\Jobs\Job;
use Illuminate\Contracts\Bus\SelfHandling;
use Illuminate\Contracts\Queue\ShouldQueue;
use Bugsnag\BugsnagLaravel\Facades\Bugsnag;

class HandledJob extends Job implements SelfHandling, ShouldQueue
{
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
Bugsnag::notifyException(new Exception('Handled :)'));
}
}
21 changes: 21 additions & 0 deletions features/fixtures/laravel51/app/Jobs/UnhandledJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace App\Jobs;

use App\Jobs\Job;
use RuntimeException;
use Illuminate\Contracts\Bus\SelfHandling;
use Illuminate\Contracts\Queue\ShouldQueue;

class UnhandledJob extends Job implements SelfHandling, ShouldQueue
{
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
throw new RuntimeException('uh oh :o');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateJobsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('jobs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('queue');
$table->longText('payload');
$table->tinyInteger('attempts')->unsigned();
$table->tinyInteger('reserved')->unsigned();
$table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('available_at');
$table->unsignedInteger('created_at');
$table->index(['queue', 'reserved', 'reserved_at']);
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('jobs');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateFailedJobsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('failed_jobs', function (Blueprint $table) {
$table->increments('id');
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->timestamp('failed_at')->useCurrent();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('failed_jobs');
}
}
25 changes: 25 additions & 0 deletions features/lib/laravel.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ def major_version
Integer(/^(?:laravel|lumen)(\d)/.match(fixture)[1])
end

def version
# e.g. laravel56 -> 56, lumen8 -> 8
raw_digits = /^(?:laravel|lumen)(\d+)/.match(fixture)[1]

# convert the raw digits to an array of: [major, minor, patch]
# in practice we only have 1 or 2 digits in our fixture names, so fill the
# rest with 0s to make sure Gem::Version doesn't get confused
# e.g. ['5', '6'] -> ['5', '6', '0'], ['8'] -> ['8', '0', '0']
version_string = raw_digits.chars
version_string.fill("0", version_string.length..2)

Gem::Version.new(version_string.join("."))
end

twometresteve marked this conversation as resolved.
Show resolved Hide resolved
def lumen?
fixture.start_with?("lumen")
end
Expand All @@ -46,6 +60,17 @@ def supports_sessions?
true
end

def queue_worker_command(tries:)
# the command to run the queue worker was 'queue:listen' but changed to
# 'queue:work' in Laravel 5.3 ('queue:work' exists on older Laravels, but
# is not quite equivalent)
if version < '5.3.0'
"php artisan queue:listen --tries=#{tries}"
else
"php artisan queue:work --tries=#{tries}"
end
end

private

def load_port_from_docker_compose
Expand Down
83 changes: 44 additions & 39 deletions features/queues.feature
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Feature: Queue support

@not-laravel-latest @not-laravel51 @not-lumen8
@not-laravel-latest @not-lumen8
Scenario: Unhandled exceptions are delivered from queues
Given I start the laravel fixture
And I start the laravel queue worker
Expand All @@ -9,36 +9,38 @@ Scenario: Unhandled exceptions are delivered from queues
Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier
And the exception "errorClass" equals "RuntimeException"
And the exception "message" equals "uh oh :o"
And the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call"
And the event "metaData.job.queue" equals "default"
And the event "metaData.job.attempts" equals 1
And the event "metaData.job.connection" equals "database"
And the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob"
And the event "app.type" equals "Queue"
And the event "context" equals "App\Jobs\UnhandledJob"
And on Laravel versions > 5.1 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call"
And on Laravel versions > 5.1 the event "metaData.job.queue" equals "default"
And on Laravel versions > 5.1 the event "metaData.job.attempts" equals 1
And on Laravel versions > 5.1 the event "metaData.job.connection" equals "database"
And on Laravel versions > 5.1 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob"
And on Laravel versions > 5.1 the event "app.type" equals "Queue"
And on Laravel versions > 5.1 the event "context" equals "App\Jobs\UnhandledJob"
And on Laravel versions == 5.1 the event "metaData.job" is null
And the event "severity" equals "error"
And the event "unhandled" is true
And the event "severityReason.type" equals "unhandledExceptionMiddleware"
And the event "severityReason.attributes.framework" equals "Laravel"

@not-laravel-latest @not-laravel51 @not-lumen8
@not-laravel-latest @not-lumen8
Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts
Given I start the laravel fixture
And I start the laravel queue worker
And I start the laravel queue worker with --tries=3
When I navigate to the route "/queue/unhandled?tries=3"
And I wait to receive 3 errors

# attempt 1
Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier
And the exception "errorClass" equals "RuntimeException"
And the exception "message" equals "uh oh :o"
And the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call"
And the event "metaData.job.queue" equals "default"
And the event "metaData.job.attempts" equals 1
And the event "metaData.job.connection" equals "database"
And the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob"
And the event "app.type" equals "Queue"
And the event "context" equals "App\Jobs\UnhandledJob"
And on Laravel versions > 5.1 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call"
And on Laravel versions > 5.1 the event "metaData.job.queue" equals "default"
And on Laravel versions > 5.1 the event "metaData.job.attempts" equals 1
And on Laravel versions > 5.1 the event "metaData.job.connection" equals "database"
And on Laravel versions > 5.1 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob"
And on Laravel versions > 5.1 the event "app.type" equals "Queue"
And on Laravel versions > 5.1 the event "context" equals "App\Jobs\UnhandledJob"
And on Laravel versions == 5.1 the event "metaData.job" is null
And the event "severity" equals "error"
And the event "unhandled" is true
And the event "severityReason.type" equals "unhandledExceptionMiddleware"
Expand All @@ -49,13 +51,14 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm
Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier
And the exception "errorClass" equals "RuntimeException"
And the exception "message" equals "uh oh :o"
And the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call"
And the event "metaData.job.queue" equals "default"
And the event "metaData.job.attempts" equals 2
And the event "metaData.job.connection" equals "database"
And the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob"
And the event "app.type" equals "Queue"
And the event "context" equals "App\Jobs\UnhandledJob"
And on Laravel versions > 5.1 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call"
And on Laravel versions > 5.1 the event "metaData.job.queue" equals "default"
And on Laravel versions > 5.1 the event "metaData.job.attempts" equals 2
And on Laravel versions > 5.1 the event "metaData.job.connection" equals "database"
And on Laravel versions > 5.1 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob"
And on Laravel versions > 5.1 the event "app.type" equals "Queue"
And on Laravel versions > 5.1 the event "context" equals "App\Jobs\UnhandledJob"
And on Laravel versions == 5.1 the event "metaData.job" is null
And the event "severity" equals "error"
And the event "unhandled" is true
And the event "severityReason.type" equals "unhandledExceptionMiddleware"
Expand All @@ -66,19 +69,20 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm
Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier
And the exception "errorClass" equals "RuntimeException"
And the exception "message" equals "uh oh :o"
And the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call"
And the event "metaData.job.queue" equals "default"
And the event "metaData.job.attempts" equals 3
And the event "metaData.job.connection" equals "database"
And the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob"
And the event "app.type" equals "Queue"
And the event "context" equals "App\Jobs\UnhandledJob"
And on Laravel versions > 5.1 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call"
And on Laravel versions > 5.1 the event "metaData.job.queue" equals "default"
And on Laravel versions > 5.1 the event "metaData.job.attempts" equals 3
And on Laravel versions > 5.1 the event "metaData.job.connection" equals "database"
And on Laravel versions > 5.1 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob"
And on Laravel versions > 5.1 the event "app.type" equals "Queue"
And on Laravel versions > 5.1 the event "context" equals "App\Jobs\UnhandledJob"
And on Laravel versions == 5.1 the event "metaData.job" is null
And the event "severity" equals "error"
And the event "unhandled" is true
And the event "severityReason.type" equals "unhandledExceptionMiddleware"
And the event "severityReason.attributes.framework" equals "Laravel"

@not-laravel-latest @not-laravel51 @not-lumen8
@not-laravel-latest @not-lumen8
Scenario: Handled exceptions are delivered from queues
Given I start the laravel fixture
And I start the laravel queue worker
Expand All @@ -87,13 +91,14 @@ Scenario: Handled exceptions are delivered from queues
Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier
And the exception "errorClass" equals "Exception"
And the exception "message" equals "Handled :)"
And the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call"
And the event "metaData.job.queue" equals "default"
And the event "metaData.job.attempts" equals 1
And the event "metaData.job.connection" equals "database"
And the event "metaData.job.resolved" equals "App\Jobs\HandledJob"
And the event "app.type" equals "Queue"
And the event "context" equals "App\Jobs\HandledJob"
And on Laravel versions > 5.1 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call"
And on Laravel versions > 5.1 the event "metaData.job.queue" equals "default"
And on Laravel versions > 5.1 the event "metaData.job.attempts" equals 1
And on Laravel versions > 5.1 the event "metaData.job.connection" equals "database"
And on Laravel versions > 5.1 the event "metaData.job.resolved" equals "App\Jobs\HandledJob"
And on Laravel versions > 5.1 the event "app.type" equals "Queue"
And on Laravel versions > 5.1 the event "context" equals "App\Jobs\HandledJob"
And on Laravel versions == 5.1 the event "metaData.job" is null
And the event "severity" equals "warning"
And the event "unhandled" is false
And the event "severityReason.type" equals "handledException"
23 changes: 22 additions & 1 deletion features/steps/laravel_steps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ def exec(service, command, detach: false)
end

When("I start the laravel queue worker") do
Maze::Docker.exec(Laravel.fixture, "php artisan queue:work", detach: true)
step("I start the laravel queue worker with --tries=1")
end

When("I start the laravel queue worker with --tries={int}") do |tries|
Maze::Docker.exec(Laravel.fixture, Laravel.queue_worker_command(tries: tries), detach: true)
end

When("I navigate to the route {string}") do |route|
Expand Down Expand Up @@ -99,3 +103,20 @@ def exec(service, command, detach: false)

step("the session payload field '#{path}' matches the regex '^((\\d+\\.){2}\\d+|\\d\\.x-dev)$'")
end

# conditionally run a step if the laravel version matches a specified version
#
# e.g. this will only check app.type on Laravel 5.2 and above:
# on Laravel versions > 5.1 the event "app.type" equals "Queue"
Then(/^on Laravel versions (>=?|<=?|==) ([0-9.]+) (.*)$/) do |operator, version, step_to_run|
should_run_step = Laravel.version.send(operator, version)

# make sure this step is debuggable!
$logger.debug("Laravel v#{Laravel.version} #{operator} #{version}? #{should_run_step}")

if should_run_step
step(step_to_run)
else
$logger.info("Skipping step on Laravel v#{Laravel.version}: #{step_to_run}")
end
end