All Projects → mac-cain13 → Daemonizable Command

mac-cain13 / Daemonizable Command

Daemonizable (endless running) commands for Symfony.

Projects that are alternatives of or similar to Daemonizable Command

Rabbitmq Supervisor Bundle
Symfony bundle to automatically create and update supervisor configurations for RabbitMQ consumer daemons
Stars: ✭ 103 (-45.5%)
Mutual labels:  daemon, symfony
Demo
Demo app for the API Platform framework
Stars: ✭ 184 (-2.65%)
Mutual labels:  symfony
Kreta
Modern project management solution
Stars: ✭ 177 (-6.35%)
Mutual labels:  symfony
Inshop Crm Api
Inshop CRM / ERP API. It's powerful framework allows to build systems for business with different workflows. It has on board multi language support, clients management, projects & tasks, documents, simple accounting, inventory management, orders & invoice management, possibilities to integrate with third party software, REST API, and many other features.
Stars: ✭ 178 (-5.82%)
Mutual labels:  symfony
Adminltebundle
AdminLTE bundle for Symfony 4 - an backend/admin theme for easy integration with SF4. Its based on the AdminLTE Template and built with webpack-encore. Supports KNPMenuBundle and FOSUserBundle.
Stars: ✭ 178 (-5.82%)
Mutual labels:  symfony
Msgphp
Reusable domain layers. Shipped with industry standard infrastructure.
Stars: ✭ 182 (-3.7%)
Mutual labels:  symfony
Composer Service
Composer as a service
Stars: ✭ 175 (-7.41%)
Mutual labels:  symfony
Intl
A PHP replacement layer for the C intl extension that also provides access to the localization data of the ICU library.
Stars: ✭ 2,323 (+1129.1%)
Mutual labels:  symfony
Webauthn Framework
FIDO-U2F / FIDO2 / Webauthn Framework
Stars: ✭ 182 (-3.7%)
Mutual labels:  symfony
Hwioauthbundle
OAuth client integration for Symfony. Supports both OAuth1.0a and OAuth2.
Stars: ✭ 2,150 (+1037.57%)
Mutual labels:  symfony
Easy Log Handler
Human-friendly log files that make you more productive
Stars: ✭ 2,070 (+995.24%)
Mutual labels:  symfony
Syliuscmsplugin
Content management system for eCommerce apps created on Sylius platform. Built with Sylius code quality, flexibility, BDD.
Stars: ✭ 178 (-5.82%)
Mutual labels:  symfony
Contao
Contao Open Source CMS
Stars: ✭ 181 (-4.23%)
Mutual labels:  symfony
Fusioninventory Agent
FusionInventory Agent
Stars: ✭ 177 (-6.35%)
Mutual labels:  daemon
Grav
Modern, Crazy Fast, Ridiculously Easy and Amazingly Powerful Flat-File CMS powered by PHP, Markdown, Twig, and Symfony
Stars: ✭ 13,067 (+6813.76%)
Mutual labels:  symfony
Php Examples For Aws Lambda
Demo serverless applications, examples code snippets and resources for PHP
Stars: ✭ 177 (-6.35%)
Mutual labels:  symfony
Validator
The Validator component provides tools to validate values following the JSR-303 Bean Validation specification.
Stars: ✭ 2,238 (+1084.13%)
Mutual labels:  symfony
Sonatapagebundle
This bundle provides a Site and Page management through container and block services
Stars: ✭ 181 (-4.23%)
Mutual labels:  symfony
Polyfill Intl Icu
This component provides a collection of functions/classes using the symfony/intl package when the Intl extension is not installed.
Stars: ✭ 2,287 (+1110.05%)
Mutual labels:  symfony
Drush
Drush is a command-line shell and scripting interface for Drupal, a veritable Swiss Army knife designed to make life easier for those who spend their working hours hacking away at the command prompt.
Stars: ✭ 2,213 (+1070.9%)
Mutual labels:  symfony

Daemonizable Commands for Symfony Build Status

A small bundle to create endless running commands with Symfony.

These endless running commands are very easy to daemonize with something like Upstart or systemd.

Why do I need this?

Because you want to create long running PHP/Symfony processes! For example to send mails with large attachment, process (delayed) payments or generate large PDF reports. They query the database or read from a message queue and do their job. This bundle makes it very easy to create such processes as Symfony commands.

How to install?

Use composer to include it into your Symfony project:

composer require wrep/daemonizable-command

What version to use?

Symfony did make some breaking changes, so you should make sure to use a compatible bundle version:

  • Version 3.0.* for Symfony 4 and 5 and higher
  • Version 2.0.* for Symfony 3
  • Version 1.3.* for Symfony 2.8+

How to use?

Just create a Symfony command that extends from EndlessCommand and off you go. Here is a minimal example:

namespace Acme\DemoBundle\Command;

use Wrep\Daemonizable\Command\EndlessCommand;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputInterface;

class MinimalDemoCommand extends EndlessCommand
{
	// This is just a normal Command::configure() method
	protected function configure()
	{
		$this->setName('acme:minimaldemo')
		     ->setDescription('An EndlessCommand implementation example');
	}

	// Execute will be called in a endless loop
	protected function execute(InputInterface $input, OutputInterface $output)
	{
		// Tell the user what we're going to do.
		// This will be a NullOutput if the user doesn't want any output at all,
		//  so you don't have to do any checks, just always write to the output.
		$output->write('Updating timestamp... ');

		// Do some work
		file_put_contents( '/tmp/acme-timestamp.txt', time() );

		// Tell the user we're done
		$output->writeln('done');
	}
}

Run it with php app/console acme:minimaldemo.

An example with all the bells and whistles is also available and gives a good overview of best practices and how to do some basic things.

How to daemonize?

Alright, now we have an endless running command in the foreground. Usefull for debugging, useless in production! So how do we make this thing a real daemon?

You should use systemd to daemonize the command. They provide very robust daemonization, start your daemon on a reboot and also monitor the process so it will try to restart it in the case of a crash.

If you can't use Upstart or systemd, you can use .lock file with LockHandler with crontab wich start script every minute.

An example Upstart script is available, place your script in /etc/init/ and start the daemon with start example-daemon. The name of the .conf-file will be the name of the daemon. A systemd example is not yet available, but it shouldn't be that hard to figure out.

Command line switches

A few switches are available by default to make life somewhat easier:

  • Use -q to suppress all output
  • Use --run-once to only run the command once, usefull for debugging
  • Use --detect-leaks to print a memory usage report after each run, read more in the next section

Memory usage and leaks

Memory usage is very important for long running processes. Symfony is not the smallest framework around and if you leak some memory in your execute method your daemon will crash! The EndlessCommand classes have been checked for memory leaks, but you should also check your own code.

How to prevent leaks?

Always start your command with the -e prod --no-debug flags. This disables all debugging features of Symfony that will eat up more and more memory.

Make sure you cleanup in the execute-method, make sure you're not appending data to an array every iteration or leave sockets/file handles open for example.

In case you are using the fingers-crossed handler in Monolog, this will also be a source of memory leaks. The idea of this handler is to keep all below-threshold log entries in memory and only flush those in case of an above-threshold entry. You can still use the fingers-crossed handler as long as you manually flush it at the end of the execute-method:

foreach ($this->getContainer()->get('logger')->getHandlers() as $handler)
{
    if ($handler instanceof FingersCrossedHandler) {
        $handler->clear();
    }
}

Detecting memory leaks

Run your command with the --detect-leaks flag. Remember that debug mode will eat memory so you'll need to run with -e prod --no-debug --detect-leaks for accurate reports.

After each iteration a memory report like this is printed on your console:

== MEMORY USAGE ==
Peak: 30038.86 KByte stable (0.000 %)
Cur.: 29856.46 KByte stable (0.000 %)

The first 3 iterations may be unstable in terms of memory usage, but after that it should be stable. Even a slight increase of memory usage will crash your daemon over time!

If you see an increase/stable/decrease loop you're probably save. It could be the garabage collector not cleaning up, you can fix this by using unset on variables to cleanup the memory yourself.

Busting some myths

Calling gc_collect_cycles() will not help to resolve leaks. PHP will cleanup memory right in time all by itself, calling this method may slow down leaking memory, but will not solve it. Also it makes spotting leaks harder, so just don't use it.

If you run Symfony in production and non-debug mode it will not leak memory and you do not have to disable any SQL loggers. The only leak I runned into is the one in the MonologBundle mentioned above.

Working with Doctrine

For reasons EndlessContainerAwareCommand clears after each Iteration Doctrine's EntityManager. Be aware of that. You can override finishIteration() to avoid this behaviour but you have to handle the EM on your own then.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].