Skip to content
Open
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
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,29 @@ BARSTOOL_DB_CONNECTION=barstool

The migration and the `Barstool` model both respect this connection.

### Custom table & model

Recordings are stored in a `barstools` table by default. To use a different name, set `table` before running the migrations:

```php
'table' => 'saloon_logs',
```

You can also have Barstool record through your own model — handy for adding relationships, scopes, or casts. It must extend Barstool's model, and it uses the configured `table` automatically:

```php
use Saloon\Barstool\Models\Barstool;

class SaloonLog extends Barstool
{
//
}
```

```php
'model' => App\Models\SaloonLog::class,
```

### Pruning old recordings

Recordings are kept for 30 days by default, controlled by:
Expand Down
13 changes: 13 additions & 0 deletions config/barstool.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

declare(strict_types=1);

use Saloon\Barstool\Models\Barstool;

return [

/*
Expand All @@ -14,6 +16,17 @@
*/
'connection' => env('BARSTOOL_DB_CONNECTION', env('DB_CONNECTION', 'mysql')),

/*
* The database table where recordings will be stored.
*/
'table' => 'barstools',

/*
* The model used to store recordings.
* If you use your own model, it must extend Saloon\Barstool\Models\Barstool.
*/
'model' => Barstool::class,

/*
* The number of days to keep recordings for.
*/
Expand Down
5 changes: 3 additions & 2 deletions database/migrations/add_context_to_barstools_table.php.stub
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ return new class extends Migration
public function up()
{
$schema = Schema::connection($this->getConnection());
$tableName = config('barstool.table', 'barstools');

if ($schema->hasColumn('barstools', 'context')) {
if ($schema->hasColumn($tableName, 'context')) {
return;
}

$schema->table('barstools', function (Blueprint $table) {
$schema->table($tableName, function (Blueprint $table) {
$table->json('context')->nullable();
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ return new class extends Migration
public function up()
{
$schema = Schema::connection($this->getConnection());
$tableName = config('barstool.table', 'barstools');

if ($schema->hasIndex('barstools', 'barstools_created_at_index')) {
// Match the index by column so the check holds for any table name
if ($schema->hasIndex($tableName, ['created_at'])) {
return;
}

$schema->table('barstools', function (Blueprint $table) {
$schema->table($tableName, function (Blueprint $table) {
$table->index('created_at');
});
}
Expand Down
2 changes: 1 addition & 1 deletion database/migrations/create_barstools_table.php.stub
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ return new class extends Migration
{
$schema = Schema::connection($this->getConnection());

$schema->create('barstools', function (Blueprint $table) {
$schema->create(config('barstool.table', 'barstools'), function (Blueprint $table) {
$table->id();
$table->uuid('uuid')->index();
$table->timestamp('created_at')->useCurrent()->index();
Expand Down
14 changes: 13 additions & 1 deletion src/Barstool.php
Original file line number Diff line number Diff line change
Expand Up @@ -322,12 +322,24 @@ private static function persist(RecordingType $type, array $payload, string $uui
return;
}

Models\Barstool::query()->updateOrCreate(
self::getModelClass()::query()->updateOrCreate(
['uuid' => $uuid],
$payload,
);
}

/**
* Get the model class used to store recordings.
*
* @internal
*
* @return class-string<Models\Barstool>
*/
public static function getModelClass(): string
{
return config('barstool.model', Models\Barstool::class);
}

private static function shouldQueue(): bool
{
return config('barstool.queue.enabled', false) === true;
Expand Down
5 changes: 3 additions & 2 deletions src/Jobs/RecordBarstoolJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Saloon\Barstool\Barstool as BarstoolRecorder;

class RecordBarstoolJob implements ShouldBeUnique, ShouldQueue
{
Expand Down Expand Up @@ -40,7 +41,7 @@ public function handle(): void
if ($this->type === RecordingType::REQUEST) {
// updateOrCreate keeps retries idempotent - a job that fails after its
// insert committed must not create a duplicate row on the next attempt.
Barstool::query()
BarstoolRecorder::getModelClass()::query()
->updateOrCreate(
['uuid' => $this->uuid],
$this->data,
Expand All @@ -49,7 +50,7 @@ public function handle(): void
return;
}

$barstool = Barstool::query()
$barstool = BarstoolRecorder::getModelClass()::query()
->where('uuid', $this->uuid)
->first();

Expand Down
1 change: 1 addition & 0 deletions src/Models/Barstool.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public function __construct(array $attributes = [])
parent::__construct($attributes);

$this->setConnection(config('barstool.connection'));
$this->setTable(config('barstool.table', 'barstools'));
}

/**
Expand Down
72 changes: 72 additions & 0 deletions tests/BarstoolTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
use Saloon\Http\Faking\MockClient;
use Saloon\Barstool\Models\Barstool;
use Saloon\Http\Faking\MockResponse;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Artisan;
use Saloon\Barstool\Enums\RecordingType;
use Illuminate\Database\Schema\Blueprint;
use Saloon\Http\Connectors\NullConnector;
use Saloon\Barstool\Jobs\RecordBarstoolJob;
use Saloon\Http\Response as SaloonResponse;
Expand All @@ -25,6 +27,7 @@
use Saloon\Barstool\Barstool as BarstoolRecorder;
use Saloon\Exceptions\Request\FatalRequestException;
use Saloon\Barstool\Tests\Fixtures\Requests\PostRequest;
use Saloon\Barstool\Tests\Fixtures\Models\CustomBarstool;
use Saloon\Barstool\Tests\Fixtures\Requests\GetFileRequest;
use Saloon\Barstool\Tests\Fixtures\Requests\SoloUserRequest;
use Saloon\Barstool\Tests\Fixtures\Connectors\RandomConnector;
Expand Down Expand Up @@ -117,6 +120,75 @@
expect($migration->getConnection())->toBe('mysql');
});

it('can change the table name', function () {
config()->set('barstool.enabled', true);
config()->set('barstool.table', 'saloon_logs');

$migration = include __DIR__.'/../database/migrations/create_barstools_table.php.stub';
$migration->up();

MockClient::global([
SoloUserRequest::class => MockResponse::make(body: ['data' => 'ok'], status: 200),
]);

(new SoloUserRequest)->send();

expect(Barstool::make()->getTable())->toBe('saloon_logs');

assertDatabaseCount('saloon_logs', 1);
assertDatabaseCount('barstools', 0);
});

it('runs the upgrade migrations against the configured table', function () {
config()->set('barstool.table', 'saloon_logs');

$schema = Schema::connection(config('barstool.connection'));

// A table from before the context column and created_at index were added
$schema->create('saloon_logs', function (Blueprint $table) {
$table->id();
$table->timestamp('created_at');
});

$contextMigration = include __DIR__.'/../database/migrations/add_context_to_barstools_table.php.stub';
$contextMigration->up();

$indexMigration = include __DIR__.'/../database/migrations/add_created_at_index_to_barstools_table.php.stub';
$indexMigration->up();

// Running it again must detect the existing index instead of adding a duplicate
$indexMigration->up();

expect($schema->hasColumn('saloon_logs', 'context'))->toBeTrue();
expect($schema->hasIndex('saloon_logs', ['created_at']))->toBeTrue();
});

it('can use a custom model', function (bool $queued) {
Event::fake([
'eloquent.created: '.CustomBarstool::class,
'eloquent.updated: '.CustomBarstool::class,
]);

config()->set('barstool.enabled', true);
config()->set('barstool.model', CustomBarstool::class);
config()->set('barstool.queue.enabled', $queued);
config()->set('queue.default', 'sync');

MockClient::global([
SoloUserRequest::class => MockResponse::make(body: ['data' => 'ok'], status: 200),
]);

(new SoloUserRequest)->send();

Event::assertDispatched('eloquent.created: '.CustomBarstool::class);
Event::assertDispatched('eloquent.updated: '.CustomBarstool::class);

expect(CustomBarstool::sole())->response_status->toBe(200);
})->with([
'synchronously' => false,
'via the queue' => true,
]);

it('can change the number of days to keep recordings for', function () {
// Check the default value is 30
expect(config('barstool.keep_for_days'))->toBe(30);
Expand Down
12 changes: 12 additions & 0 deletions tests/Fixtures/Models/CustomBarstool.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Saloon\Barstool\Tests\Fixtures\Models;

use Saloon\Barstool\Models\Barstool;

class CustomBarstool extends Barstool
{
//
}