Answers.Body: <p>You are right about the Tasks running in the background. If the Task is just sending a few mails, it might be done before your site is loaded, thus creating this impression. </p>
  
  <p><strong>Check:</strong></p>
  
  <ul>
  <li>Change the Batch Size of the <a href="https://github.com/victor-in/Craft-Mailer" rel="nofollow">Mailer plugin</a> to <code>1</code> and the waiting time to <code>120</code> seconds.</li>
  <li>Change the <code>$user_criteria</code> to fetch 2 users.</li>
  <li>Run your controller</li>
  </ul>
  
  <p>It should now take about 2 minutes for the Task to finish, if your site loads faster it was just an impression.</p>
  
  <hr>
  
  <p><strong>Code:</strong></p>
  
  <p>You should however separate your code a bit more, because right now you are mixing <a href="http://buildwithcraft.com/docs/plugins/controllers" rel="nofollow">Controllers</a> and <a href="http://buildwithcraft.com/docs/plugins/services" rel="nofollow">Services</a>.</p>
  
  <p>Your Service shouldn't output anything, it should just return a value, (e.g. <a href="https://php.net/manual/en/language.types.boolean.php" rel="nofollow"><code>boolen</code></a>), and your Controller should then output the message:</p>
  
  <pre class="lang-php prettyprint-override"><code>Service {
      //Create Task etc...
  
      if ($itWorked == true) {
         return true;
      }
      else {
         return false;
      }
  }
  
  /* ------------------------ */
  
  Controller {
      if ( FunctionService() ) {
         echo 'It worked';
      }
      else {
         echo 'Something went wrong';
      }
  }
  </code></pre>
  
  <p>Also the "Make sure we kick the task off"-part, should go into your Service.</p>
  
  <p><strong>P.S.</strong> I see you are using my plugin :), if you need any help, create <a href="https://github.com/victor-in/Craft-Mailer/issues?state=closed" rel="nofollow">an issue over on github</a>.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-07-25T13:49:47.530Z
Answers.Text: Thanks victor for the reply and for explaining to me about the best practices for controllers and services. Another piece of the puzzle just clicked into place :) Also, thanks for a great plugin, it works like a charm, very pleased with it. I'll be sure to head over github if I run into any issues in the future. Thanks again.
Answers.UserDisplayName: Dave Coggins
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-07-25T14:06:22.090Z
Answers.Text: Hi Victor, I've just tried out the settings you suggested and you are right, the emails are being sent as a background process as they should be, what I was experiencing was just an impression. I have noticed though the when I hit the controller I get a 504 Gateway Time-out before the controller returns with "emails sent". I guess this is not a massive deal because I'm going to be hitting this from a CRON job so as long as the task is triggered all should be well. I was wondering, do you know if it is possible to trigger the task from the command line rather than through the browser?
Answers.UserDisplayName: Dave Coggins
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-07-25T14:11:54.150Z
Answers.Text: I don't know why you get the time-out, maybe the output in the service causes this, but I'm not sure. I haven't used CRON yet, but the best way would be to trigger the Controller which then starts the Service and Task.
Answers.UserDisplayName: Victor
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-07-26T00:51:11.977Z
Answers.Text: I tracked down 504 gateway time-out to be to do with my nginx config. I fixed it by adding fastcgi_read_timeout 300; to the config.
Answers.UserDisplayName: Dave Coggins
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-07-25T13:33:11.860Z
Answers.LastActivityDate: 2014-07-25T13:49:00.980Z
Answers.LastEditDate: 2014-07-25T13:49:00.980Z
Answers.UserDisplayName: Victor
Body: <p>I have my plugin working now so that I can email users who's accounts will expire in 7 days time. The users are being selected correctly and the emails are being sent as expected. However, the tasks don't seem to be running in the background. I was expecting that when I hit the controller the task will be triggered and the page would immediately return saying "emails sent". Instead it seems it waits until the emails are sent before returning "emails sent". I'm worried that if the number of emails is large the page will timeout before it completes. It was my understanding that tasks run as a background process but may I have miss understood. Can anyone explain them to me in more detail?</p>
  
  <p>For reference here is the controller and the service of my plugin:</p>
  
  <pre><code>class AcmeNotifications_NotificationsController extends BaseController
  {
  
  // let anyone run the controller actions
  protected $allowAnonymous = array('actionSendEmail');
  
  public function actionSendEmail()
  {
      craft()-&gt;acmeNotifications_notifications-&gt;sendReminderEmail();
  
      //Make sure we kick the task off
  
      if (!craft()-&gt;tasks-&gt;isTaskRunning())
      {
          $task = craft()-&gt;tasks-&gt;getNextPendingTask();
  
          if ($task)
          {
              craft()-&gt;tasks-&gt;runPendingTasks();
          }
      }
  
      craft()-&gt;end();
  }
  }
  </code></pre>
  
  <p>and:</p>
  
  <pre><code>class AcmeNotifications_NotificationsService extends BaseApplicationComponent
  {
  public function sendReminderEmail()
  {
      //Get all users whos account will expire in 7 days
      $user_criteria = craft()-&gt;elements-&gt;getCriteria(ElementType::User);
  
      $user_criteria-&gt;userExpiryDate = date('Y-m-d',strtotime("+7 days"));
  
      $users = $user_criteria-&gt;find();
  
  
  
      if($users){
          //Create array of user email addresses
          $user_emails = array();
          foreach ($users as $user) {
              $user_emails[] = array("to" =&gt; $user-&gt;email);
          }
  
          //Create an EmailModel
          $email = new EmailModel;
  
          //Set the global attributes 
          $email-&gt;fromName = 'Joe Blogs';
          $email-&gt;fromEmail = 'joe.blogs@example.com';
          $email-&gt;subject     = 'Your account will expire in 7 days';
          $email-&gt;htmlBody    = 'The message';
  
          //Create the RecipientsModel and add the user emails
          $recipients = new Mailer_RecipientsModel();
          $recipients-&gt;recipients = $user_emails;
  
          if( $recipients-&gt;validate()){
              //Create mailer task
              craft()-&gt;mailer_main-&gt;newMailer($recipients, $email); 
          }
  
          echo "emails sent";
      }
      else{
          echo "no emails to send";
      }
  }
  
  
  } 
  </code></pre>
  
Tags: <plugin-development><tasks>
Title: My tasks don't seem to be running as a background process
ThreadText: # My tasks don't seem to be running as a background process
  
  (Asked by: username_0 on 2014-07-25)
  
  I have my plugin working now so that I can email users who's accounts will expire in 7 days time. The users are being selected correctly and the emails are being sent as expected. However, the tasks don't seem to be running in the background. I was expecting that when I hit the controller the task will be triggered and the page would immediately return saying "emails sent". Instead it seems it waits until the emails are sent before returning "emails sent". I'm worried that if the number of emails is large the page will timeout before it completes. It was my understanding that tasks run as a background process but may I have miss understood. Can anyone explain them to me in more detail?
  
  For reference here is the controller and the service of my plugin:
  
  ```
  class AcmeNotifications_NotificationsController extends BaseController
  {
  
  // let anyone run the controller actions
  protected $allowAnonymous = array('actionSendEmail');
  
  public function actionSendEmail()
  {
      craft()->acmeNotifications_notifications->sendReminderEmail();
  
      //Make sure we kick the task off
  
      if (!craft()->tasks->isTaskRunning())
      {
          $task = craft()->tasks->getNextPendingTask();
  
          if ($task)
          {
              craft()->tasks->runPendingTasks();
          }
      }
  
      craft()->end();
  }
  }
  
  ```
  
  and:
  
  ```
  class AcmeNotifications_NotificationsService extends BaseApplicationComponent
  {
  public function sendReminderEmail()
  {
      //Get all users whos account will expire in 7 days
      $user_criteria = craft()->elements->getCriteria(ElementType::User);
  
      $user_criteria->userExpiryDate = date('Y-m-d',strtotime("+7 days"));
  
      $users = $user_criteria->find();
  
      if($users){
          //Create array of user email addresses
          $user_emails = array();
          foreach ($users as $user) {
              $user_emails[] = array("to" => $user->email);
          }
  
          //Create an EmailModel
          $email = new EmailModel;
  
          //Set the global attributes 
          $email->fromName = 'Joe Blogs';
          $email->fromEmail = 'joe.blogs@example.com';
          $email->subject     = 'Your account will expire in 7 days';
          $email->htmlBody    = 'The message';
  
          //Create the RecipientsModel and add the user emails
          $recipients = new Mailer_RecipientsModel();
          $recipients->recipients = $user_emails;
  
          if( $recipients->validate()){
              //Create mailer task
              craft()->mailer_main->newMailer($recipients, $email); 
          }
  
          echo "emails sent";
      }
      else{
          echo "no emails to send";
      }
  }
  
  } 
  
  ```
  
  **Tags:** plugin-development, tasks
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2014-07-25. Score: 2 | Accepted answer
  
  You are right about the Tasks running in the background. If the Task is just sending a few mails, it might be done before your site is loaded, thus creating this impression.
  
  **Check:**
  
  * Change the Batch Size of the [Mailer plugin](https://github.com/username_1-in/Craft-Mailer) to `1` and the waiting time to `120` seconds.
  * Change the `$user_criteria` to fetch 2 users.
  * Run your controller
  
  It should now take about 2 minutes for the Task to finish, if your site loads faster it was just an impression.
  
  ---
  
  **Code:**
  
  You should however separate your code a bit more, because right now you are mixing [Controllers](http://buildwithcraft.com/docs/plugins/controllers) and [Services](http://buildwithcraft.com/docs/plugins/services).
  
  Your Service shouldn't output anything, it should just return a value, (e.g. [`boolen`](https://php.net/manual/en/language.types.boolean.php)), and your Controller should then output the message:
  
  ```php
  Service {
      //Create Task etc...
  
      if ($itWorked == true) {
         return true;
      }
      else {
         return false;
      }
  }
  
  /* ------------------------ */
  
  Controller {
      if ( FunctionService() ) {
         echo 'It worked';
      }
      else {
         echo 'Something went wrong';
      }
  }
  
  ```
  
  Also the "Make sure we kick the task off"-part, should go into your Service.
  
  **P.S.** I see you are using my plugin :), if you need any help, create [an issue over on github](https://github.com/username_1-in/Craft-Mailer/issues?state=closed).
  
  > **Comments:**
  > **username_0**: Thanks username_1 for the reply and for explaining to me about the best practices for controllers and services. Another piece of the puzzle just clicked into place :) Also, thanks for a great plugin, it works like a charm, very pleased with it. I'll be sure to head over github if I run into any issues in the future. Thanks again.  
  > **username_0**: Hi username_1, I've just tried out the settings you suggested and you are right, the emails are being sent as a background process as they should be, what I was experiencing was just an impression. I have noticed though the when I hit the controller I get a 504 Gateway Time-out before the controller returns with "emails sent". I guess this is not a massive deal because I'm going to be hitting this from a CRON job so as long as the task is triggered all should be well. I was wondering, do you know if it is possible to trigger the task from the command line rather than through the browser?  
  > **username_1**: I don't know why you get the time-out, maybe the output in the service causes this, but I'm not sure. I haven't used CRON yet, but the best way would be to trigger the Controller which then starts the Service and Task.  
  > **username_0**: I tracked down 504 gateway time-out to be to do with my nginx config. I fixed it by adding fastcgi_read_timeout 300; to the config.  
  
  ---
  
  