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

[5.4] Add cache forget command and use it in the event Schedule #16201

Merged
merged 7 commits into from
Nov 1, 2016
Merged
Show file tree
Hide file tree
Changes from 3 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
9 changes: 8 additions & 1 deletion src/Illuminate/Cache/CacheServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Illuminate\Support\ServiceProvider;
use Illuminate\Cache\Console\ClearCommand;
use Illuminate\Cache\Console\ForgetCommand;

class CacheServiceProvider extends ServiceProvider
{
Expand Down Expand Up @@ -48,6 +49,12 @@ public function registerCommands()
});

$this->commands('command.cache.clear');

$this->app->singleton('command.cache.forget', function ($app) {
return new ForgetCommand($app['cache']);
});

$this->commands('command.cache.forget');
}

/**
Expand All @@ -58,7 +65,7 @@ public function registerCommands()
public function provides()
{
return [
'cache', 'cache.store', 'memcached.connector', 'command.cache.clear',
'cache', 'cache.store', 'memcached.connector', 'command.cache.clear', 'command.cache.forget',
];
}
}
68 changes: 68 additions & 0 deletions src/Illuminate/Cache/Console/ForgetCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace Illuminate\Cache\Console;

use Illuminate\Console\Command;
use Illuminate\Cache\CacheManager;
use Symfony\Component\Console\Input\InputArgument;

class ForgetCommand extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'cache:forget';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Remove an item from the cache';

/**
* The cache manager instance.
*
* @var \Illuminate\Cache\CacheManager
*/
protected $cache;

/**
* Create a new cache clear command instance.
*
* @param \Illuminate\Cache\CacheManager $cache
* @return void
*/
public function __construct(CacheManager $cache)
{
parent::__construct();

$this->cache = $cache;
}

/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
$this->cache->store($this->argument('store'))
->forget($this->argument('key'));
}

/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return [
['key', InputArgument::REQUIRED, 'The name of the key.'],
['store', InputArgument::OPTIONAL, 'The name of the store.'],
];
}
}
25 changes: 19 additions & 6 deletions src/Illuminate/Console/Scheduling/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ class Event
*/
public $command;

/**
* The cache forget command string.
*
* @var string
*/
public $cacheForget;

/**
* The cron expression representing the event's frequency.
*
Expand Down Expand Up @@ -132,12 +139,14 @@ class Event
*
* @param \Illuminate\Contracts\Cache\Repository $cache
* @param string $command
* @param string $cacheForget
* @return void
*/
public function __construct(Cache $cache, $command)
public function __construct(Cache $cache, $command, $cacheForget)
{
$this->cache = $cache;
$this->command = $command;
$this->cacheForget = $cacheForget;
$this->output = $this->getDefaultOutput();
}

Expand Down Expand Up @@ -168,10 +177,6 @@ public function run(Container $container)
} else {
$this->runCommandInBackground();
}

if ($this->withoutOverlapping) {
$this->cache->forget($this->mutexName());
}
}

/**
Expand Down Expand Up @@ -240,7 +245,15 @@ public function buildCommand()

$redirect = $this->shouldAppendOutput ? ' >> ' : ' > ';

$command = $this->command.$redirect.$output.' 2>&1 &';
if ($this->withoutOverlapping) {
if (windows_os()) {
$command = '('.$this->command.' & '.$this->cacheForget.' "'.$this->mutexName().'")'.$redirect.$output.' 2>&1 &';
} else {
$command = '('.$this->command.'; '.$this->cacheForget.' '.$this->mutexName().')'.$redirect.$output.' 2>&1 &';
}
} else {
$command = $this->command.$redirect.$output.' 2>&1 &';
}

return $this->user && ! windows_os() ? 'sudo -u '.$this->user.' -- sh -c \''.$command.'\'' : $command;
}
Expand Down
28 changes: 22 additions & 6 deletions src/Illuminate/Console/Scheduling/Schedule.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@ class Schedule
*/
protected $cache;

/**
* The PHP executable.
*
* @var string
*/
protected $phpBinary;

/**
* The Artisan console path.
*
* @var string
*/
protected $artisan;

/**
* Create a new event instance.
*
Expand All @@ -25,6 +39,10 @@ class Schedule
public function __construct(Cache $cache)
{
$this->cache = $cache;

$this->phpBinary = ProcessUtils::escapeArgument((new PhpExecutableFinder)->find(false));

$this->artisan = defined('ARTISAN_BINARY') ? ProcessUtils::escapeArgument(ARTISAN_BINARY) : 'artisan';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to extract this to some static method on a class or something that way we don't have to do all this just to pass a command name into the event class.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me it seems like we should be able to call like Something('cache:forget') and receive back a fully formatted call to php artisan cache:forget.

}

/**
Expand Down Expand Up @@ -61,11 +79,7 @@ public function command($command, array $parameters = [])
$command = Container::getInstance()->make($command)->getName();
}

$binary = ProcessUtils::escapeArgument((new PhpExecutableFinder)->find(false));

$artisan = defined('ARTISAN_BINARY') ? ProcessUtils::escapeArgument(ARTISAN_BINARY) : 'artisan';

return $this->exec("{$binary} {$artisan} {$command}", $parameters);
return $this->exec("{$this->phpBinary} {$this->artisan} {$command}", $parameters);
}

/**
Expand All @@ -81,7 +95,9 @@ public function exec($command, array $parameters = [])
$command .= ' '.$this->compileParameters($parameters);
}

$this->events[] = $event = new Event($this->cache, $command);
$cacheForget = "{$this->phpBinary} {$this->artisan} cache:forget";

$this->events[] = $event = new Event($this->cache, $command, $cacheForget);

return $event;
}
Expand Down
36 changes: 18 additions & 18 deletions tests/Console/ConsoleScheduledEventTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function testBasicCronCompilation()
$app->shouldReceive('isDownForMaintenance')->andReturn(false);
$app->shouldReceive('environment')->andReturn('production');

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$this->assertEquals('* * * * * *', $event->getExpression());
$this->assertTrue($event->isDue($app));
$this->assertTrue($event->skip(function () {
Expand All @@ -42,49 +42,49 @@ public function testBasicCronCompilation()
return true;
})->filtersPass($app));

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$this->assertEquals('* * * * * *', $event->getExpression());
$this->assertFalse($event->environments('local')->isDue($app));

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$this->assertEquals('* * * * * *', $event->getExpression());
$this->assertFalse($event->when(function () {
return false;
})->filtersPass($app));

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$this->assertEquals('*/5 * * * * *', $event->everyFiveMinutes()->getExpression());

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$this->assertEquals('0 0 * * * *', $event->daily()->getExpression());

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$this->assertEquals('0 3,15 * * * *', $event->twiceDaily(3, 15)->getExpression());

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$this->assertEquals('*/5 * * * 3 *', $event->everyFiveMinutes()->wednesdays()->getExpression());

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$this->assertEquals('0 * * * * *', $event->everyFiveMinutes()->hourly()->getExpression());

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$this->assertEquals('0 15 4 * * *', $event->monthlyOn(4, '15:00')->getExpression());

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$this->assertEquals('0 0 * * 1-5 *', $event->weekdays()->daily()->getExpression());

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$this->assertEquals('0 * * * 1-5 *', $event->weekdays()->hourly()->getExpression());

// chained rules should be commutative
$eventA = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$eventB = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$eventA = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$eventB = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$this->assertEquals(
$eventA->daily()->hourly()->getExpression(),
$eventB->hourly()->daily()->getExpression());

$eventA = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$eventB = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$eventA = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$eventB = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$this->assertEquals(
$eventA->weekdays()->hourly()->getExpression(),
$eventB->hourly()->weekdays()->getExpression());
Expand All @@ -97,11 +97,11 @@ public function testEventIsDueCheck()
$app->shouldReceive('environment')->andReturn('production');
Carbon::setTestNow(Carbon::create(2015, 1, 1, 0, 0, 0));

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$this->assertEquals('* * * * 4 *', $event->thursdays()->getExpression());
$this->assertTrue($event->isDue($app));

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$this->assertEquals('0 19 * * 3 *', $event->wednesdays()->at('19:00')->timezone('EST')->getExpression());
$this->assertTrue($event->isDue($app));
}
Expand All @@ -113,7 +113,7 @@ public function testTimeBetweenChecks()
$app->shouldReceive('environment')->andReturn('production');
Carbon::setTestNow(Carbon::now()->startOfDay()->addHours(9));

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php foo', 'cache:forget');
$this->assertTrue($event->between('8:00', '10:00')->filtersPass($app));
$this->assertTrue($event->between('9:00', '9:00')->filtersPass($app));
$this->assertFalse($event->between('10:00', '11:00')->filtersPass($app));
Expand Down
10 changes: 5 additions & 5 deletions tests/Console/Scheduling/EventTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public function testBuildCommand()
{
$quote = (DIRECTORY_SEPARATOR == '\\') ? '"' : "'";

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php -i');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php -i', 'cache:forget');

$defaultOutput = (DIRECTORY_SEPARATOR == '\\') ? 'NUL' : '/dev/null';
$this->assertSame("php -i > {$quote}{$defaultOutput}{$quote} 2>&1 &", $event->buildCommand());
Expand All @@ -24,12 +24,12 @@ public function testBuildCommandSendOutputTo()
{
$quote = (DIRECTORY_SEPARATOR == '\\') ? '"' : "'";

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php -i');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php -i', 'cache:forget');

$event->sendOutputTo('/dev/null');
$this->assertSame("php -i > {$quote}/dev/null{$quote} 2>&1 &", $event->buildCommand());

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php -i');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php -i', 'cache:forget');

$event->sendOutputTo('/my folder/foo.log');
$this->assertSame("php -i > {$quote}/my folder/foo.log{$quote} 2>&1 &", $event->buildCommand());
Expand All @@ -39,7 +39,7 @@ public function testBuildCommandAppendOutput()
{
$quote = (DIRECTORY_SEPARATOR == '\\') ? '"' : "'";

$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php -i');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php -i', 'cache:forget');

$event->appendOutputTo('/dev/null');
$this->assertSame("php -i >> {$quote}/dev/null{$quote} 2>&1 &", $event->buildCommand());
Expand All @@ -50,7 +50,7 @@ public function testBuildCommandAppendOutput()
*/
public function testEmailOutputToThrowsExceptionIfOutputFileWasNotSpecified()
{
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php -i');
$event = new Event(m::mock('Illuminate\Contracts\Cache\Repository'), 'php -i', 'cache:forget');
$event->emailOutputTo('foo@example.com');

$event->buildCommand();
Expand Down