Skip to content

Commit

Permalink
Hard won improvements
Browse files Browse the repository at this point in the history
* Sleep for 5 seconds on update to ensure queue has finished restarting and that supervisord has actually stopped
* Use correct user to start workers -- don't use sudo in command and instead specify webapp user
* Make queue option optional based on queue_driver (beanstalk or no)
* Supply environment variables via supervisord for a cleaner experience
  * Pass vars to program building method to the environment parameter as key-value IE KEY1="value1"
  * Quote values if they are not alphanumeric
  * Remove step in deploy script to copy env vars to .env file
  • Loading branch information
FoxxMD committed Sep 20, 2018
1 parent 55612e4 commit b1e6558
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 22 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,17 @@ IS_WORKER = true

### Set Queue Driver

Set the [driver](https://laravel.com/docs/5.1/queues#introduction) in your your EB envronmental variables:
Set the [driver](https://laravel.com/docs/5.1/queues#introduction) in your your EB environmental variables:

```
QUEUE_DRIVER = [driver]
```

**Note: If no `QUEUE_DRIVER` key is present in your EB envronmental variables then `beanstalkd` will be used.**
**Note: If no `QUEUE_DRIVER` key is present in your EB environmental variables then `beanstalkd` will be used.**

### Add Queues

All queues are configured using EB envronmental variables with the following syntax:
All queues are configured using EB environmental variables with the following syntax:

**Note**: brackets are placeholders only, do not use them in your actual configuration

Expand Down Expand Up @@ -131,17 +131,19 @@ Supervisor requires port 9001 to be open if you want to access its web monitor.

`parseConfig.php` looks for either a user-supplied `supervisord.conf` file specified in configuration. If one exists then it is used.

Otherwise `parseConfig.php` looks for a json file generated earlier that contains all of the environmental variables configured for elastic beanstalk. It then parses out any queue configurations found (see `Add Queues`) section above and generates a supervisor program for each. The program to be generated looks like this:
Otherwise `parseConfig.php` looks for a json file generated earlier that contains all of the environmental variables configured for elastic beanstalk. It then parses out any queue configurations found (see `Add Queues`) section above and generates a supervisor program for each as well as supplying each program with all the environmental variables set for EB. The program to be generated looks like this:

```
[program:$queue]
command=sudo php artisan queue:work $connection --queue=$queue --tries=$tries --sleep=$sleep --daemon
command=php artisan queue:work $connection --queue=$queue --tries=$tries --sleep=$sleep --daemon
directory=/var/app/current/
autostart=true
autorestart=true
process_name=$queue-%(process_num)s
numprocs=$numProcs
startsecs=$startSecs
user=webapp
environment=$environmentVal
```

After parsing all queues it then appends the programs to a clean `supervisord.conf` file in the same directory.
Expand Down Expand Up @@ -169,7 +171,6 @@ Now a bash script `workerDeploy.sh` checks for `IS_WORKER=TRUE` in the EB enviro
This is almost verbatim how I have things setup for another project so some usage is limited because of how it was originally written:

* Queue driver defaults to beanstalkd if not explicitly set
* There is no way to generate a supervisor program without `--queue=[queue]` right now

All of these are simple fixes though! Check out issues to see these and more and if you need them please make a PR!

Expand Down
52 changes: 38 additions & 14 deletions src/.ebextensions/parseConfig.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
<?php

function generateProgram($connection, $queue, $tries, $sleep, $numProcs, $delay, $startSecs)
function generateProgram($connection, $queue, $tries, $sleep, $numProcs, $delay, $startSecs, $environmentVal)
{
$queueVal = $queue !== null ? " --queue=$queue ": '';
$program = <<<EOT
[program:$queue]
command=sudo php artisan queue:work $connection --queue=$queue --tries=$tries --sleep=$sleep --delay=$delay --daemon
process_name=%(program_name)s_%(process_num)02d
command=php artisan queue:work $connection$queueVal--tries=$tries --sleep=$sleep --delay=$delay --daemon

This comment has been minimized.

Copy link
@MbahDjoe

MbahDjoe Oct 10, 2018

Collaborator

hi, please either add space between $queueVal and --tries=$tries or on the line 5 "else" part, this is causing the process can not run and make fatal error if not using beanstalkd for the queue, thank you

This comment has been minimized.

Copy link
@FoxxMD

FoxxMD Oct 10, 2018

Author Owner

oops you're right i missed the space in the false value for $queueVal

directory=/var/app/current/
autostart=true
autorestart=true
process_name=$queue-%(process_num)s
numprocs=$numProcs
startsecs=$startSecs
user=webapp
environment=$environmentVal
EOT;

Expand Down Expand Up @@ -101,13 +104,28 @@ function getEBWorkerConfig($path)
echo 'No user-supplied supervisord.conf found. Generating one from environmental variables.' . PHP_EOL;
}

$envLocation = $deployDirectory . '/jsonEnv';
$vars = json_decode(file_get_contents($envLocation), true);
$envVars = array_change_key_case($vars); // convert keys to lower case so environmental variables don't have to be case-sensitive
$envLocation = $deployDirectory . '/jsonEnv';
$envVars = json_decode(file_get_contents($envLocation), true);
$lowerEnvVars = array_change_key_case($envVars); // convert keys to lower case so environmental variables don't have to be case-sensitive

$envKvArray = [];
foreach ($envVars as $key => $val) {
if(ctype_alnum($val) // alphanumeric doesn't need quotes
|| (strpos($val, '"') === 0 && strrpos($val, '"') === count($val) -1)) // if the value is already quoted don't double-quote it
{
$formattedVal = $val;
} else { // otherwise put everything in quotes for environment param http://supervisord.org/configuration.html#program-x-section-values
$formattedVal = "\"{$val}\"";
}
$envKvArray[] = "{$key}={$formattedVal}";
}
$envKv = implode(',', $envKvArray);

$programs = '';

foreach ($envVars as $key => $val)
$isBeanstalk = $lowerEnvVars['queue_driver'] === 'beanstalkd';

foreach ($lowerEnvVars as $key => $val)
{
if (strpos($key, 'queue') !== false && strpos($key, 'queue_driver') === false)
{
Expand All @@ -117,13 +135,19 @@ function getEBWorkerConfig($path)
$startSecsKey = substr($key, 5) . 'startsecs'; //get queue $key + number of seconds the process should stay up
$delayKey = substr($key, 5) . 'delay'; //get queue $key + delay in seconds before a job should re-enter the ready queue

$tries = isset($envVars[ $tryKey ]) ? $envVars[ $tryKey ] : 5;
$sleep = isset($envVars[ $sleepKey ]) ? $envVars[ $sleepKey ] : 5;
$numProcs = isset($envVars[ $numProcKey ]) ? $envVars[ $numProcKey ] : 1;
$startSecs = isset($envVars[ $startSecsKey ]) ? $envVars[ $startSecsKey ] : 1;
$delay = isset($envVars[ $delayKey]) ? $envVars[ $delayKey ] : 0;
$connection = isset($envVars['queue_driver']) ? $envVars['queue_driver'] : 'beanstalkd';
$programs .= generateProgram($connection, $val, $tries, $sleep, $numProcs, $delay, $startSecs);
$tries = isset($lowerEnvVars[ $tryKey ]) ? $lowerEnvVars[ $tryKey ] : 5;
$sleep = isset($lowerEnvVars[ $sleepKey ]) ? $lowerEnvVars[ $sleepKey ] : 5;
$numProcs = isset($lowerEnvVars[ $numProcKey ]) ? $lowerEnvVars[ $numProcKey ] : 1;
$startSecs = isset($lowerEnvVars[ $startSecsKey ]) ? $lowerEnvVars[ $startSecsKey ] : 1;
$delay = isset($lowerEnvVars[ $delayKey ]) ? $lowerEnvVars[ $delayKey ] : 0;
// if using beanstalk connection should always be beanstalkd and specify tube in queue, otherwise us queue name as connection
$connection = $isBeanstalk ? 'beanstalkd' : $val;
// if not using beanstalk we don't need queue probably
$queue = $isBeanstalk ? $val : null;
$programEnvArray = $envKvArray;
// if any vars need to be specific per worker this is where to put them
// $programEnvArray[] =
$programs .= generateProgram($connection, $queue, $tries, $sleep, $numProcs, $delay, $startSecs, implode(',', $programEnvArray));
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/.ebextensions/workerDeploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ updateSupervisor(){
cp .ebextensions/supervisord.conf /etc/supervisord.conf
sudo service supervisord stop
php /var/app/current/artisan queue:restart # If this worker is running in daemon mode (most likely) we need to restart it with the new build
echo "Sleeping a few seconds to make sure supervisor shuts down..." # https://github.com/Supervisor/supervisor/issues/48#issuecomment-2684400
sleep 5
sudo service supervisord start
}

Expand Down Expand Up @@ -42,8 +44,6 @@ if test "${ary['IS_WORKER']+isset}" #if key exists
if [ ${ary['IS_WORKER']} == "'true'" ] #if the value is true
then
echo "Found worker key!"
echo "Copying environmental variables to dotenv"
cp bashEnv .env
echo "Starting worker deploy process...";

if [ -f /etc/init.d/supervisord ];
Expand Down

0 comments on commit b1e6558

Please sign in to comment.