0

I am developing a project, and there is a two process.

  1. Sending mail.
  2. Sending response back to the user.

I need to do this all, but it takes a lot of time. So now I am thinking to use multithreading. Can anyone help how to achieve this in php?

I just need to send a response as soon as possible. Here is my code I make a function to send mail and after success full mail delivery i am sending a response to the user using JSON encode.

/mail function/

public function emailSent($booking_id, $mailHeading, $smallHeading, $subject, $smallHeadingcustomer ,$status, $senttoestimator = true, $senttocustomer = true, $mailSent = false){
        if(!empty($booking_id)){
             $bookingData = $this->Cnc_model->getData('bookings', array('*'), array('id'=>$booking_id));

            if(!empty($bookingData)){
                if(!empty($bookingData[0]['estimator_id']) && $bookingData[0]['estimator_id'] != 0){
                    $name = $this->Cnc_model->getData('users',array('username', 'email'), array('user_id'=> $bookingData[0]['estimator_id']));   
                    $estimator_name = $name[0]['username'];
                    $estimator_mail = $name[0]['email']; 
                    }
                if($bookingData[0]['customer_id'] != 0){
                    $cname = $this->Cnc_model->getData('customers',array('name', 'office_contact_email'), array('id'=> $bookingData[0]['customer_id']));   
                    $customer_name = $cname[0]['name'];
                    $customer_mail = $cname[0]['office_contact_email'];
                }

                $fromEmail = FROM;
                $emailData = array(
                        "customeName" => $customer_name,
                        "estimator_name"=>$estimator_name,
                        "booking_title" => !empty($bookingData[0]['booking_title']) ? $bookingData[0]['booking_title']: 'No Title',
                        "booking_date" => date("d-m-Y",strtotime($bookingData[0]['booking_date'])),
                        "start_time" => date("h:i a",strtotime($bookingData[0]['start_time'])),
                        "end_time" => date("h:i a",strtotime($bookingData[0]['end_time'])),
                        "address" =>isset($bookingData[0]['location']) ? $bookingData[0]['location']: '',
                        "notes" => isset($bookingData[0]['notes']) && !empty($bookingData[0]['notes'])?$bookingData['notes']:'No Notes For this booking',
                        "status" => isset($status) && !empty($status)? $status:'',
                        "bookingId" => $bookingData[0]['id'],
                        'mainHeading'=> isset($mailHeading) && !empty($mailHeading)?$mailHeading:'',
                        'smallHeading'=>isset($smallHeading) && !empty($smallHeading)?$smallHeading:'',
                        'smallHeadingcustomer' => isset($smallHeadingcustomer) && !empty($smallHeadingcustomer)?$smallHeadingcustomer: '',
                    );
                if($bookingData[0]['status']!=3 && $bookingData[0]['status']!=0 || $mailSent == true ){
                  if(!empty($emailData) && $senttocustomer){   
                        $newBooking= $this->load->view('templates/email-template/new_booking', $emailData, TRUE);
                        $this->email->from($fromEmail); 
                        $this->email->to($customer_mail);  
                        $this->email->subject($subject);
                        $this->email->message($newBooking);
                        $this->email->send();
                    }
                    if(!empty($estimator_mail) && $senttoestimator){
                        $newEstimatorBooking = $this->load->view('templates/email-template/new_booking_estimator', $emailData, TRUE);
                        $this->email->from($fromEmail); 
                        $this->email->to($estimator_mail);  
                        $this->email->subject($subject);
                        $this->email->message($newEstimatorBooking);
                        $this->email->send();
                    }  
                }  
            }
        }
        else{
            return false;
        }
        return true;
    }  

/function to delete booking/

public function deleteBooking($id){
     $where = array('id'=>$id); 
     $bookingData = $this->Cnc_model->getData('bookings', array('*'), array('id'=>$id)); 
     if(!empty($bookingData)){
        if(!empty($bookingData[0]['estimator_id']) && $bookingData[0]['estimator_id'] != 0){
                    $name = $this->Cnc_model->getData('users',array('username', 'email'), array('user_id'=> $bookingData[0]['estimator_id']));   
                    $estimator_name = $name[0]['username'];
                    $estimator_mail = $name[0]['email']; 
                    }

                if($bookingData[0]['customer_id'] != 0){
                    $cname = $this->Cnc_model->getData('customers',array('name', 'office_contact_email'), array('id'=> $bookingData[0]['customer_id']));   
                    $customer_name = $cname[0]['name'];
                    $customer_mail = $cname[0]['office_contact_email'];
                }
                $mailHeading = 'Booking Deleted';
                $smallHeading = 'Your Booking with '.$customer_name.' on '.$bookingData[0]['booking_date'].' has been deleted by admin.';
                $subject = 'Booking Deleted';
                $smallHeadingcustomer = 'Your Booking with '.$estimator_name.' on '.$bookingData[0]['booking_date'].' has been deleted by admin.';
                $status = 5;

/*Here i am calling send email function */

                $result = $this->emailSent($id, $mailHeading, $smallHeading, $subject, $smallHeadingcustomer,$status);

/*After getting a response I send a response to ajax request */

              if($result){
                    $deleteBooking = $this->Cnc_model->rowsDelete('bookings', $where);
                    if($deleteBooking){
                        $this->logThis('Deleted', 'Booking', 'Booking Deleted', array('id' => $id));
                        $this->Cnc_model->addNotification($id,22,$this->auth_user_id,$bookingData[0]['estimator_id'],'Booking Deleted',$bookingData[0]['booking_title'].' deleted on '.date("m/d/Y").' at '.date('H:i a'));
                        $where = '';
                        $data['success'] = true; 
                        $data['message'] = 'Booking deleted successfully.';
                        echo json_encode($data);
                        die;     
                    }else{
                        $where = '';
                        $data['success'] = false; 
                        $data['message'] = 'Error while deleting booking.';
                        echo json_encode($data);
                       die;
                    }
               }  
            }
     else{
        $data['success'] = false; 
        $data['message'] = 'Error while deleting booking.';
        echo json_encode($data);
        die;  
     }
}
Akshay
  • 35
  • 8

2 Answers2

0

It depends how deep you want to go. The ideal way would be to run a RabbitMQ or Gearman server and set up a 'send mail' job for them to process. Submitting a job is very quick and would allow the script to complete and send the response back to the user, but of course that would involve setting up more infrastructure, writing/maintaining more code to process the job and handling the retry/error states.

Probably the least-problematic way would be to run a local mail server which will relay the mail. The hand-off should be very quick, would give a better 'valid' response (at least the user would know the mail had been handed to the local mail server) and allow the script to continue. Should the email fail then it's dealt by the local mail server as a bounce to admin or the 'from' user.

One way outlined here would mean sending the response first, then processing the email - which means it could never report a failure to the user. Not ideal, but it depends on your situation - maybe an admin handles failed messages and can re-send?

0

You can use ignore_user_abort(true); Sets whether a client disconnect should cause a script to be aborted. This will disconnect the current connection from your side and then sends the response to front-end, but still executes the rest of the code.

 ignore_user_abort(true);

    ob_start();
    echo "success";

    $serverProtocole = filter_input(INPUT_SERVER, 'SERVER_PROTOCOL', FILTER_SANITIZE_STRING);
    header($serverProtocole.' 200 OK');
    header('Content-Encoding: none');
    header('Content-Length: '.ob_get_length());
    header('Connection: close');

    ob_end_flush();
    ob_flush();
    flush();

Initially use backend validation for your API, then use the above code to send response after which you can write code to email your users, this way the front-end will get the response and the script will execute till it encounters a return or die; the issue with this method is that you cannot send a response to frontend if there is an error while sending email.

Otherwise You can use a mail queuein your code to do the jobe later

Arun P
  • 541
  • 4
  • 11
  • thank you for the response. ButIi can't understand how do I implement this in my code, can you please tell me. – Akshay Jul 02 '19 at 11:28
  • for this to work split the deleteBooking() into 2 sections 1. for Doing all the DB operations and 2. Sending Email to the client no after completing section 1 Implement the code so, it will send a response and still keeps executing the code – Arun P Jul 02 '19 at 12:07
  • Sir, if you look at my code then you see, I have made two functions one for sending an email and rest for delete booking. I am calling send email function in delete booking function. – Akshay Jul 02 '19 at 13:32