diff --git a/assets/TenancyServiceProvider.stub.php b/assets/TenancyServiceProvider.stub.php index c2fcdd94..9bc2cad0 100644 --- a/assets/TenancyServiceProvider.stub.php +++ b/assets/TenancyServiceProvider.stub.php @@ -49,11 +49,11 @@ class TenancyServiceProvider extends ServiceProvider })->shouldBeQueued(false), // `false` by default, but you probably want to make this `true` for production. ], - // Readied events - Events\ReadyingTenant::class => [], - Events\TenantReadied::class => [], - Events\PullingReadiedTenant::class => [], - Events\ReadiedTenantPulled::class => [], + // Pending events + Events\CreatingPendingTenant::class => [], + Events\PendingTenantCreated::class => [], + Events\PullingPendingTenant::class => [], + Events\PendingTenantPulled::class => [], // Domain events Events\CreatingDomain::class => [], diff --git a/assets/config.php b/assets/config.php index 3b41f5a9..8f389710 100644 --- a/assets/config.php +++ b/assets/config.php @@ -37,33 +37,33 @@ return [ /** - * Readied tenancy config. + * Pending tenancy config. * This is useful if you're looking for a way to always have a tenant ready to be used. */ - 'readied' => [ + 'pending' => [ /** - * If disabled, readied tenants will be excluded from all tenant queries. Unless if - * told otherwise with ::withReadied() or ::onlyReadied(). + * If disabled, pending tenants will be excluded from all tenant queries. Unless if + * told otherwise with ::withPending() or ::onlyPending(). * Note: when disabled, this will also ignore tenants when runnings any tenants commands (migration, seed, etc.) */ 'include_in_queries' => true, /** - * Defines how many tenants you want to be in a readied state. + * Defines how many tenants you want to be in a pending state. * This value should be changed depending on how often a new tenant is created - * and how often you run the `tenancy:readied` command via the scheduler. + * and how often you run the `tenancy:pending` command via the scheduler. */ - 'count' => env('TENANCY_READIED_COUNT', 5), + 'count' => env('TENANCY_PENDING_COUNT', 5), /** - * If needed, you can define a time limite after when an unused readied tenant + * If needed, you can define a time limite after when an unused pending tenant * will automatically be deleted. - * For this to work automatically, make sure to call the `tenancy:readied-clear` command in the scheduler. + * For this to work automatically, make sure to call the `tenancy:pending-clear` command in the scheduler. * - * If both values are set to null, not time limit will be set and all readied tenants will be deleted. + * If both values are set to null, not time limit will be set and all pending tenants will be deleted. */ - 'older_than_days' => env('TENANCY_READIED_OLDER_THAN_DAYS', null), + 'older_than_days' => env('TENANCY_PENDING_OLDER_THAN_DAYS', null), - 'older_than_hours' => env('TENANCY_READIED_OLDER_THAN_HOURS', null), + 'older_than_hours' => env('TENANCY_PENDING_OLDER_THAN_HOURS', null), ], /** diff --git a/src/Commands/ClearReadiedTenants.php b/src/Commands/ClearPendingTenants.php similarity index 66% rename from src/Commands/ClearReadiedTenants.php rename to src/Commands/ClearPendingTenants.php index 05b0adcb..67d77d56 100644 --- a/src/Commands/ClearReadiedTenants.php +++ b/src/Commands/ClearPendingTenants.php @@ -7,24 +7,24 @@ namespace Stancl\Tenancy\Commands; use Illuminate\Console\Command; use Illuminate\Database\Eloquent\Builder; -class ClearReadiedTenants extends Command +class ClearPendingTenants extends Command { /** * The name and signature of the console command. * * @var string */ - protected $signature = 'tenants:readied-clear - {--all : Override the default settings and deletes all readied tenants} - {--older-days= : Deletes all readied older than the amount of days} - {--older-hours= : Deletes all readied older than the amount of hours}'; + protected $signature = 'tenants:pending-clear + {--all : Override the default settings and deletes all pending tenants} + {--older-days= : Deletes all pending older than the amount of days} + {--older-hours= : Deletes all pending older than the amount of hours}'; /** * The console command description. * * @var string */ - protected $description = 'Removes any readied tenants'; + protected $description = 'Removes any pending tenants'; /** * Execute the console command. @@ -33,7 +33,7 @@ class ClearReadiedTenants extends Command */ public function handle() { - $this->info('Cleaning readied tenants.'); + $this->info('Cleaning pending tenants.'); $expireDate = now(); // At the end, we will check if the value has been changed by comparing the two dates @@ -41,27 +41,27 @@ class ClearReadiedTenants extends Command // If the all option is given, skip the expiry date configuration if (! $this->option('all')) { - if ($olderThanDays = $this->option('older-days') ?? config('tenancy.readied.older_than_days')) { + if ($olderThanDays = $this->option('older-days') ?? config('tenancy.pending.older_than_days')) { $expireDate->subDays($olderThanDays); } - if ($olderThanHours = $this->option('older-hours') ?? config('tenancy.readied.older_than_hours')) { + if ($olderThanHours = $this->option('older-hours') ?? config('tenancy.pending.older_than_hours')) { $expireDate->subHours($olderThanHours); } } - $readiedTenantsDeletedCount = tenancy() + $deletedPendingCount = tenancy() ->query() - ->onlyReadied() + ->onlyPending() ->when($savedExpiredDate->notEqualTo($expireDate), function (Builder $query) use ($expireDate) { - $query->where('data->readied', '<', $expireDate->timestamp); + $query->where('data->pending_since', '<', $expireDate->timestamp); }) ->get() ->each // This makes sure the events or triggered on the model ->delete() ->count(); - $this->info("$readiedTenantsDeletedCount readied tenant(s) deleted."); + $this->info("$deletedPendingCount pending tenant(s) deleted."); } } diff --git a/src/Commands/CreatePendingTenants.php b/src/Commands/CreatePendingTenants.php new file mode 100644 index 00000000..45e15853 --- /dev/null +++ b/src/Commands/CreatePendingTenants.php @@ -0,0 +1,64 @@ +info('Deploying pendgin tenants.'); + + $pendingObjectifCount = (int)config('tenancy.pending.count'); + + $pendingCurrentCount = $this->getPendingTenantCount(); + + $deployedCount = 0; + while ($pendingCurrentCount < $pendingObjectifCount) { + tenancy()->model()::createPending(); + // We update the number of pending tenants every time with a query to get a live count. + // this prevents to deploy too many tenants if pending tenants are being created simultaneous somewhere else + // during the runtime of this command. + $pendingCurrentCount = $this->getPendingTenantCount(); + $deployedCount++; + } + + $this->info("$deployedCount tenants deployed, $pendingObjectifCount tenant(s) are ready to be used."); + + return self::SUCCESS; + } + + /** + * Calculates the number of pending tenants currently deployed + * @return int + */ + private function getPendingTenantCount(): int + { + return tenancy() + ->query() + ->onlyPending() + ->count(); + } +} diff --git a/src/Commands/CreateReadiedTenants.php b/src/Commands/CreateReadiedTenants.php deleted file mode 100644 index 90304198..00000000 --- a/src/Commands/CreateReadiedTenants.php +++ /dev/null @@ -1,62 +0,0 @@ -info('Deploying readied tenants.'); - - $readiedCountObjectif = (int)config('tenancy.readied.count'); - - $readiedTenantCount = $this->getReadiedTenantCount(); - - $deployedCount = 0; - while ($readiedTenantCount < $readiedCountObjectif) { - tenancy()->model()::createReadied(); - // We update the number of readied tenant every time with a query to get a live count. - // this prevents to deploy too many tenants if readied tenants have been deployed - // while this command is running. - $readiedTenantCount = $this->getReadiedTenantCount(); - $deployedCount++; - } - - $this->info("$deployedCount tenants deployed, $readiedCountObjectif tenant(s) are ready to be used."); - } - - /** - * Calculates the number of readied tenants currently deployed - * @return int - */ - private function getReadiedTenantCount(): int - { - return tenancy() - ->query() - ->onlyReadied() - ->count(); - } -} diff --git a/src/Database/Concerns/HasPending.php b/src/Database/Concerns/HasPending.php new file mode 100644 index 00000000..5187733e --- /dev/null +++ b/src/Database/Concerns/HasPending.php @@ -0,0 +1,90 @@ +casts['pending_since'] = 'timestamp'; + } + + + /** + * Determine if the model instance is in a pending state. + * + * @return bool + */ + public function pending() + { + return !is_null($this->pending_since); + } + + public static function createPending($attributes = []): void + { + $tenant = static::create($attributes); + + event(new CreatingPendingTenant($tenant)); + + // We add the pending value only after the model has then been created. + // this ensures the model is not marked as pending until the migrations, seeders, etc. are done + $tenant->update([ + 'pending_since' => now()->timestamp + ]); + + event(new PendingTenantCreated($tenant)); + } + + public static function pullPendingTenant(bool $firstOrCreate = false): ?Tenant + { + if (!static::onlyPending()->exists()) { + if (!$firstOrCreate) { + return null; + } + static::createPending(); + } + + // At this point we can guarantee a pending tenant is free and can be called. + $tenant = static::onlyPending()->first(); + + event(new PullingPendingTenant($tenant)); + + $tenant->update([ + 'pending_since' => null + ]); + + event(new PendingTenantPulled($tenant)); + + return $tenant; + } +} diff --git a/src/Database/Concerns/ReadiedScope.php b/src/Database/Concerns/PendingScope.php similarity index 63% rename from src/Database/Concerns/ReadiedScope.php rename to src/Database/Concerns/PendingScope.php index 0062e367..c5fad50c 100644 --- a/src/Database/Concerns/ReadiedScope.php +++ b/src/Database/Concerns/PendingScope.php @@ -8,7 +8,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Scope; -class ReadiedScope implements Scope +class PendingScope implements Scope { /** @@ -16,7 +16,7 @@ class ReadiedScope implements Scope * * @var string[] */ - protected $extensions = ['WithReadied', 'WithoutReadied', 'OnlyReadied']; + protected $extensions = ['WithPending', 'WithoutPending', 'OnlyPending']; /** * Apply the scope to a given Eloquent query builder. @@ -27,8 +27,8 @@ class ReadiedScope implements Scope */ public function apply(Builder $builder, Model $model) { - $builder->when(!config('tenancy.readied.include_in_queries'), function (Builder $builder){ - $builder->whereNull('data->readied'); + $builder->when(!config('tenancy.pending.include_in_queries'), function (Builder $builder){ + $builder->whereNull('data->pending_since'); }); } @@ -45,16 +45,16 @@ class ReadiedScope implements Scope } } /** - * Add the with-readied extension to the builder. + * Add the with-pending extension to the builder. * * @param \Illuminate\Database\Eloquent\Builder $builder * @return void */ - protected function addWithReadied(Builder $builder) + protected function addWithPending(Builder $builder) { - $builder->macro('withReadied', function (Builder $builder, $withReadied = true) { - if (! $withReadied) { - return $builder->withoutReadied(); + $builder->macro('withPending', function (Builder $builder, $withPending = true) { + if (! $withPending) { + return $builder->withoutPending(); } return $builder->withoutGlobalScope($this); @@ -62,32 +62,32 @@ class ReadiedScope implements Scope } /** - * Add the without-readied extension to the builder. + * Add the without-pending extension to the builder. * * @param \Illuminate\Database\Eloquent\Builder $builder * @return void */ - protected function addWithoutReadied(Builder $builder) + protected function addWithoutPending(Builder $builder) { - $builder->macro('withoutReadied', function (Builder $builder) { + $builder->macro('withoutPending', function (Builder $builder) { - $builder->withoutGlobalScope($this)->whereNull('data->readied'); + $builder->withoutGlobalScope($this)->whereNull('data->pending_since'); return $builder; }); } /** - * Add the only-readied extension to the builder. + * Add the only-pending extension to the builder. * * @param \Illuminate\Database\Eloquent\Builder $builder * @return void */ - protected function addOnlyReadied(Builder $builder) + protected function addOnlyPending(Builder $builder) { - $builder->macro('onlyReadied', function (Builder $builder) { + $builder->macro('onlyPending', function (Builder $builder) { - $builder->withoutGlobalScope($this)->whereNotNull('data->readied'); + $builder->withoutGlobalScope($this)->whereNotNull('data->pending_since'); return $builder; }); diff --git a/src/Database/Concerns/WithReadied.php b/src/Database/Concerns/WithReadied.php deleted file mode 100644 index 2e7ccf3f..00000000 --- a/src/Database/Concerns/WithReadied.php +++ /dev/null @@ -1,90 +0,0 @@ -casts['readied'] = 'timestamp'; - } - - - /** - * Determine if the model instance is in a readied state. - * - * @return bool - */ - public function readied() - { - return !is_null($this->readied); - } - - public static function createReadied($attributes = []): void - { - $tenant = static::create($attributes); - - event(new ReadyingTenant($tenant)); - - // We add the readied value only after the model has then been created. - // this ensures the model is not marked as readied until the migrations, seeders, etc. are done - $tenant->update([ - 'readied' => now()->timestamp - ]); - - event(new TenantReadied($tenant)); - } - - public static function pullReadiedTenant(bool $firstOrCreate = false): ?Tenant - { - if (!static::onlyReadied()->exists()) { - if (!$firstOrCreate) { - return null; - } - static::createReadied(); - } - - // At this point we can guarantee a readied tenant is free and can be called - $tenant = static::onlyReadied()->first(); - - event(new PullingReadiedTenant($tenant)); - - $tenant->update([ - 'readied' => null - ]); - - event(new ReadiedTenantPulled($tenant)); - - return $tenant; - } -} diff --git a/src/Database/Models/Tenant.php b/src/Database/Models/Tenant.php index b575ff8f..625ec71c 100644 --- a/src/Database/Models/Tenant.php +++ b/src/Database/Models/Tenant.php @@ -27,7 +27,7 @@ class Tenant extends Model implements Contracts\Tenant Concerns\HasInternalKeys, Concerns\TenantRun, Concerns\InvalidatesResolverCache, - Concerns\WithReadied; + Concerns\HasPending; protected $table = 'tenants'; protected $primaryKey = 'id'; diff --git a/src/Events/TenantReadied.php b/src/Events/CreatingPendingTenant.php similarity index 55% rename from src/Events/TenantReadied.php rename to src/Events/CreatingPendingTenant.php index 526d3514..dfbe6c70 100644 --- a/src/Events/TenantReadied.php +++ b/src/Events/CreatingPendingTenant.php @@ -4,6 +4,6 @@ declare(strict_types=1); namespace Stancl\Tenancy\Events; -class TenantReadied extends Contracts\TenantEvent +class CreatingPendingTenant extends Contracts\TenantEvent { } diff --git a/src/Events/PullingReadiedTenant.php b/src/Events/PendingTenantCreated.php similarity index 55% rename from src/Events/PullingReadiedTenant.php rename to src/Events/PendingTenantCreated.php index fd71b21f..f75f1a8e 100644 --- a/src/Events/PullingReadiedTenant.php +++ b/src/Events/PendingTenantCreated.php @@ -4,6 +4,6 @@ declare(strict_types=1); namespace Stancl\Tenancy\Events; -class PullingReadiedTenant extends Contracts\TenantEvent +class PendingTenantCreated extends Contracts\TenantEvent { } diff --git a/src/Events/ReadiedTenantPulled.php b/src/Events/PendingTenantPulled.php similarity index 55% rename from src/Events/ReadiedTenantPulled.php rename to src/Events/PendingTenantPulled.php index 5bced1e3..b60740f4 100644 --- a/src/Events/ReadiedTenantPulled.php +++ b/src/Events/PendingTenantPulled.php @@ -4,6 +4,6 @@ declare(strict_types=1); namespace Stancl\Tenancy\Events; -class ReadiedTenantPulled extends Contracts\TenantEvent +class PendingTenantPulled extends Contracts\TenantEvent { } diff --git a/src/Events/ReadyingTenant.php b/src/Events/PullingPendingTenant.php similarity index 55% rename from src/Events/ReadyingTenant.php rename to src/Events/PullingPendingTenant.php index 3e10a05f..2997c107 100644 --- a/src/Events/ReadyingTenant.php +++ b/src/Events/PullingPendingTenant.php @@ -4,6 +4,6 @@ declare(strict_types=1); namespace Stancl\Tenancy\Events; -class ReadyingTenant extends Contracts\TenantEvent +class PullingPendingTenant extends Contracts\TenantEvent { } diff --git a/src/Jobs/ClearReadiedTenants.php b/src/Jobs/ClearPendingTenants.php similarity index 81% rename from src/Jobs/ClearReadiedTenants.php rename to src/Jobs/ClearPendingTenants.php index 6ca3d4ab..31720904 100644 --- a/src/Jobs/ClearReadiedTenants.php +++ b/src/Jobs/ClearPendingTenants.php @@ -12,7 +12,7 @@ use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\Artisan; use Stancl\Tenancy\Contracts\TenantWithDatabase; -class ClearReadiedTenants implements ShouldQueue +class ClearPendingTenants implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; @@ -23,6 +23,6 @@ class ClearReadiedTenants implements ShouldQueue */ public function handle() { - Artisan::call('tenants:readied-clear'); + Artisan::call(\Stancl\Tenancy\Commands\ClearPendingTenants::class); } } diff --git a/src/Jobs/CreateReadiedTenants.php b/src/Jobs/CreatePendingTenants.php similarity index 80% rename from src/Jobs/CreateReadiedTenants.php rename to src/Jobs/CreatePendingTenants.php index d1db676e..bdd68e9a 100644 --- a/src/Jobs/CreateReadiedTenants.php +++ b/src/Jobs/CreatePendingTenants.php @@ -12,7 +12,7 @@ use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\Artisan; use Stancl\Tenancy\Contracts\TenantWithDatabase; -class CreateReadiedTenants implements ShouldQueue +class CreatePendingTenants implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; @@ -23,6 +23,6 @@ class CreateReadiedTenants implements ShouldQueue */ public function handle() { - Artisan::call('tenants:readied'); + Artisan::call(\Stancl\Tenancy\Commands\CreatePendingTenants::class); } } diff --git a/src/TenancyServiceProvider.php b/src/TenancyServiceProvider.php index 69fb5165..a7e09b48 100644 --- a/src/TenancyServiceProvider.php +++ b/src/TenancyServiceProvider.php @@ -89,8 +89,8 @@ class TenancyServiceProvider extends ServiceProvider Commands\Rollback::class, Commands\TenantList::class, Commands\MigrateFresh::class, - Commands\CreateReadiedTenants::class, - Commands\ClearReadiedTenants::class, + Commands\CreatePendingTenants::class, + Commands\ClearPendingTenants::class, ]); $this->publishes([ diff --git a/tests/Etc/Tenant.php b/tests/Etc/Tenant.php index bc801f3b..8e817d97 100644 --- a/tests/Etc/Tenant.php +++ b/tests/Etc/Tenant.php @@ -7,10 +7,10 @@ namespace Stancl\Tenancy\Tests\Etc; use Stancl\Tenancy\Contracts\TenantWithDatabase; use Stancl\Tenancy\Database\Concerns\HasDatabase; use Stancl\Tenancy\Database\Concerns\HasDomains; -use Stancl\Tenancy\Database\Concerns\WithReadied; +use Stancl\Tenancy\Database\Concerns\HasPending; use Stancl\Tenancy\Database\Models; class Tenant extends Models\Tenant implements TenantWithDatabase { - use HasDatabase, HasDomains, WithReadied; + use HasDatabase, HasDomains, HasPending; } diff --git a/tests/Etc/tmp/queuetest.json b/tests/Etc/tmp/queuetest.json index dc158c6b..00cf7c37 100644 --- a/tests/Etc/tmp/queuetest.json +++ b/tests/Etc/tmp/queuetest.json @@ -1 +1 @@ -{"userName":"Bar","shouldFail":false,"tenant_id":"The current tenant id is: a7f73c10-9879-40ae-b7b0-1ded7c1f7b1b"} \ No newline at end of file +{"tenant_id":"The current tenant id is: acme"} \ No newline at end of file diff --git a/tests/PendingTenantsTest.php b/tests/PendingTenantsTest.php new file mode 100644 index 00000000..ff26e9b9 --- /dev/null +++ b/tests/PendingTenantsTest.php @@ -0,0 +1,172 @@ +assertCount(1, Tenant::onlyPending()->get()); + + Tenant::onlyPending()->first()->update([ + 'pending_since' => null + ]); + + $this->assertCount(0, Tenant::onlyPending()->get()); + } + + /** @test */ + public function pending_trait_imports_query_scopes() + { + Tenant::createPending(); + Tenant::create(); + Tenant::create(); + + $this->assertCount(1, Tenant::onlyPending()->get()); + + $this->assertCount(3, Tenant::withPending(true)->get()); + + $this->assertCount(2, Tenant::withPending(false)->get()); + + $this->assertCount(2, Tenant::withoutPending()->get()); + } + + /** @test */ + public function pending_tenants_are_created_and_deleted_from_the_commands() + { + config(['tenancy.pending.count' => 4]); + + Artisan::call(CreatePendingTenants::class); + + $this->assertCount(4, Tenant::onlyPending()->get()); + + Artisan::call(ClearPendingTenants::class); + + $this->assertCount(0, Tenant::onlyPending()->get()); + } + + /** @test */ + public function clear_pending_tenants_command_only_delete_pending_tenants_older_than() + { + config(['tenancy.pending.count' => 2]); + + Artisan::call(CreatePendingTenants::class); + + config(['tenancy.pending.older_than_days' => 2]); + + tenancy()->model()->query()->onlyPending()->first()->update([ + 'pending_since' => now()->subDays(5)->timestamp + ]); + + Artisan::call(ClearPendingTenants::class); + + $this->assertCount(1, Tenant::onlyPending()->get()); + } + + /** @test */ + public function clear_pending_tenants_command_all_option_overrides_config() + { + Tenant::createPending(); + Tenant::createPending(); + + tenancy()->model()->query()->onlyPending()->first()->update([ + 'pending_since' => now()->subDays(10) + ]); + + config(['tenancy.pending.older_than_days' => 4]); + + Artisan::call(ClearPendingTenants::class, [ + '--all' => true + ]); + + $this->assertCount(0, Tenant::onlyPending()->get()); + } + + /** @test */ + public function tenancy_can_check_for_rpending_tenants() + { + Tenant::query()->delete(); + + $this->assertFalse(Tenant::onlyPending()->exists()); + + Tenant::createPending(); + + $this->assertTrue(Tenant::onlyPending()->exists()); + } + + /** @test */ + public function tenancy_can_pull_a_pending_tenant() + { + $this->assertNull(Tenant::pullPendingTenant()); + + Tenant::createPending(); + + $this->assertInstanceOf(Tenant::class, Tenant::pullPendingTenant(true)); + } + + /** @test */ + public function tenancy_can_create_if_none_are_pending() + { + $this->assertCount(0, Tenant::all()); + + Tenant::pullPendingTenant(true); + + $this->assertCount(1, Tenant::all()); + } + + /** @test */ + public function pending_tenants_global_scope_config_can_include_or_exclude() + { + Tenant::createPending(); + + config(['tenancy.pending.include_in_queries' => false]); + + $this->assertCount(0, Tenant::all()); + + config(['tenancy.pending.include_in_queries' => true]); + + $this->assertCount(1, Tenant::all()); + Tenant::all(); + } + + /** @test */ + public function pending_events_are_triggerred() + { + Event::fake([ + CreatingPendingTenant::class, + PendingTenantCreated::class, + PullingPendingTenant::class, + PendingTenantPulled::class, + ]); + + Tenant::createPending(); + + Event::assertDispatched(CreatingPendingTenant::class); + Event::assertDispatched(PendingTenantCreated::class); + + Tenant::pullPendingTenant(); + + Event::assertDispatched(PullingPendingTenant::class); + Event::assertDispatched(PendingTenantPulled::class); + } +} diff --git a/tests/ReadiedTenantsTest.php b/tests/ReadiedTenantsTest.php deleted file mode 100644 index dcd2a336..00000000 --- a/tests/ReadiedTenantsTest.php +++ /dev/null @@ -1,172 +0,0 @@ -assertCount(1, Tenant::onlyReadied()->get()); - - Tenant::onlyReadied()->first()->update([ - 'readied' => null - ]); - - $this->assertCount(0, Tenant::onlyReadied()->get()); - } - - /** @test */ - public function readied_trait_imports_query_scopes() - { - Tenant::createReadied(); - Tenant::create(); - Tenant::create(); - - $this->assertCount(1, Tenant::onlyReadied()->get()); - - $this->assertCount(3, Tenant::withReadied(true)->get()); - - $this->assertCount(2, Tenant::withReadied(false)->get()); - - $this->assertCount(2, Tenant::withoutReadied()->get()); - } - - /** @test */ - public function readied_tenants_are_created_and_deleted_from_the_commands() - { - config(['tenancy.readied.count' => 4]); - - Artisan::call(CreateReadiedTenants::class); - - $this->assertCount(4, Tenant::onlyReadied()->get()); - - Artisan::call(ClearReadiedTenants::class); - - $this->assertCount(0, Tenant::onlyReadied()->get()); - } - - /** @test */ - public function clear_readied_tenants_command_only_delete_readied_tenants_older_than() - { - config(['tenancy.readied.count' => 2]); - - Artisan::call(CreateReadiedTenants::class); - - config(['tenancy.readied.older_than_days' => 2]); - - tenancy()->model()->query()->onlyReadied()->first()->update([ - 'readied' => now()->subDays(5)->timestamp - ]); - - Artisan::call(ClearReadiedTenants::class); - - $this->assertCount(1, Tenant::onlyReadied()->get()); - } - - /** @test */ - public function clear_readied_tenants_command_all_option_overrides_config() - { - Tenant::createReadied(); - Tenant::createReadied(); - - tenancy()->model()->query()->onlyReadied()->first()->update([ - 'readied' => now()->subDays(10) - ]); - - config(['tenancy.readied.older_than_days' => 4]); - - Artisan::call(ClearReadiedTenants::class, [ - '--all' => true - ]); - - $this->assertCount(0, Tenant::onlyReadied()->get()); - } - - /** @test */ - public function tenancy_can_check_for_readied_tenants() - { - Tenant::query()->delete(); - - $this->assertFalse(Tenant::onlyReadied()->exists()); - - Tenant::createReadied(); - - $this->assertTrue(Tenant::onlyReadied()->exists()); - } - - /** @test */ - public function tenancy_can_pull_a_readied_tenant() - { - $this->assertNull(Tenant::pullReadiedTenant()); - - Tenant::createReadied(); - - $this->assertInstanceOf(Tenant::class, Tenant::pullReadiedTenant(true)); - } - - /** @test */ - public function tenancy_can_create_if_none_are_readied() - { - $this->assertCount(0, Tenant::all()); - - Tenant::pullReadiedTenant(true); - - $this->assertCount(1, Tenant::all()); - } - - /** @test */ - public function readied_tenants_global_scope_config_can_include_or_exclude() - { - Tenant::createReadied(); - - config(['tenancy.readied.include_in_queries' => false]); - - $this->assertCount(0, Tenant::all()); - - config(['tenancy.readied.include_in_queries' => true]); - - $this->assertCount(1, Tenant::all()); - Tenant::all(); - } - - /** @test */ - public function readied_events_are_triggerred() - { - Event::fake([ - ReadyingTenant::class, - TenantReadied::class, - PullingReadiedTenant::class, - ReadiedTenantPulled::class, - ]); - - Tenant::createReadied(); - - Event::assertDispatched(ReadyingTenant::class); - Event::assertDispatched(TenantReadied::class); - - Tenant::pullReadiedTenant(); - - Event::assertDispatched(PullingReadiedTenant::class); - Event::assertDispatched(ReadiedTenantPulled::class); - } -}