Skip to content

Commit

Permalink
Integrating Minion Tasks + Redis
Browse files Browse the repository at this point in the history
* Messages now queued instead of an immediate send
* Messages will then be popped out of the Redis queue to be dealt with individually
* Added multiple checks to prevent ping overload
  • Loading branch information
David Kobia committed Oct 7, 2013
1 parent d59da7f commit 21eac91
Show file tree
Hide file tree
Showing 11 changed files with 236 additions and 75 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ To install the platform on your computer/server, the target system must meet the
* An HTTP Server. PingApp is known to work with the following web servers:
- Apache 2.2+
- nginx
* Redis
- required for Message Queuing
* Unicode support in the operating system

### Downloading
Expand Down Expand Up @@ -63,9 +65,10 @@ To install the platform on your computer/server, the target system must meet the
6. Edit ```application/config/init.php``` and change base_url to point the the httpdocs directory in your deployment
7. ```cp application/config/auth.template application/config/auth.php```
8. ```cp application/config/modules.template application/config/modules.php```
9. ```cp httpdocs/template.htaccess httpdocs/.htaccess```
10. Edit ```httpdocs/.htaccess``` and change the RewriteBase value to match your deployment url
11. Create directories ```application/cache``` and ```application/logs``` and make them writable
9. ```cp application/config/redis.template application/config/redis.php```
10. ```cp httpdocs/template.htaccess httpdocs/.htaccess```
11. Edit ```httpdocs/.htaccess``` and change the RewriteBase value to match your deployment url
12. Create directories ```application/cache``` and ```application/logs``` and make them writable

### Upgrading

Expand Down
70 changes: 17 additions & 53 deletions application/classes/Controller/Messages.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,68 +87,32 @@ private function _broadcast_message()
}

// Create the message
$message = new Model_Message();
$message = ORM::factory('Message');
try
{
// Set values and save
$message->values(array(
'message' => $this->request->post('message'),
'user_id' => $this->user->id,
'type' => 'phone'
))
->save();

// Tracks the no. of pings sent out
$ping_count = 0;

$_columns = array('message_id', 'tracking_id', 'contact_id', 'provider', 'type', 'status', 'created');
$query = DB::insert('pings', $_columns);

// Ping!
'type' => 'sms'
));
$message->save();

// Save Ping
foreach ($contacts as $contact)
{
if (($tracking_id = $this->_provider->send($contact->contact, $message->message)) !== FALSE)
{
$query->values(array(
'message_id' => $message->id,
'tracking_id' => $tracking_id,
'contact_id' => $contact->id,
'provider' => strtolower(PingApp_SMS_Provider::$sms_provider),
'type' => 'phone',
'status' => 'pending',
'created' => date('Y-m-d H:i:s')
$ping = ORM::factory('Ping');
$ping->values(array(
'message_id' => $message->id,
'tracking_id' => '0',
'type' => 'sms',
'contact_id' => $contact->id,
'provider' => strtolower(PingApp_SMS_Provider::$sms_provider),
'status' => 'pending',
'sent' => 0
));
$ping_count++;
}
}

// Any pings go out?
if ($ping_count)
{
try
{
// Create the pings
$query->execute();
Kohana::$log->add(Log::INFO, __("Successfully dispatched :count pings", array(":count" => $ping_count)));
}
catch (Database_Exception $e)
{
// Rollback message creation
$messsage->delete();

Kohana::$log->add(Log::ERROR, $e->getMessage());

return FALSE;
}
}
else
{
// An error ocurred while trying to send the messages
// Rollback the message
$message->delete();
Kohana::$log->add(Log::INFO, "No messages sent");
}

$ping->save();
}
}
catch (ORM_Validation_Exception $e)
{
Expand Down
13 changes: 11 additions & 2 deletions application/classes/Model/Ping.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,26 @@
class Model_Ping extends ORM {
/**
* A ping belongs to a message, and a contact
* A ping also belongs to a parent ping (retries)
*/
protected $_belongs_to = array(
'message' => array(),
'contact' => array(),
'parent' => array(
'model' => 'Ping',
'foreign_key' => 'parent_id',
),
);

/**
* A ping has many pongs
* A ping has many pongs and children pings (retries)
*/
protected $_has_many = array(
'pongs' => array(),
'children' => array(
'model' => 'Ping',
'foreign_key' => 'parent_id',
),
);

// Insert/Update Timestamps
Expand All @@ -33,7 +42,7 @@ public function rules()
{
return array(
'status' => array(
array('in_array', array(':value', array('pending', 'sent', 'received', 'replied')) ),
array('in_array', array(':value', array('pending', 'received', 'expired', 'failed', 'cancelled')) ),
),
);
}
Expand Down
100 changes: 99 additions & 1 deletion application/classes/PingApp/Ping.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,103 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License Version 3 (GPLv3)
*/
class PingApp_Ping {


public static function process($ping_id = 0)
{
if ($ping_id)
{
// 1. Ping Exists, Is Pending and not Sent?
$ping = ORM::factory('Ping')
->where('id', '=', $ping_id)
->where('status', '=', 'pending')
->where('sent', '!=', 1)
->find();

if ( $ping->loaded() )
{
// Is this an old Ping? (> 24 hours old)
if ( ( time() - strtotime($ping->created) ) > 86400)
{
$ping->status = 'expired';
$ping->save();

return;
}

// 2. Contacts Exists?
$contact = $ping->contact;
if ( $contact->loaded() )
{
// How many times has this contact been pinged
// in the last 24 hours
$pings = $contact->pings
->where('sent', '=', 1)
->where('created', '>=', DB::expr('DATE_SUB(NOW(), INTERVAL 1 DAY)'))
->order_by('created', 'DESC')
->find_all();

// If less than 3, we can safely proceed
if ($pings->count() < 3)
{
// But we need to space the pings out
if ($pings->count() > 0)
{
// Get the last ping to this contact
foreach ($pings as $_ping)
{
// 10 minute spacer
if ( ( time() - strtotime($_ping->updated) ) < 600)
{
return;
}

break;
}
}

// Phew - Okay we can now send this ping
if ($ping->type == 'sms')
{
self::_sms($ping, $contact);
}
elseif ($ping->type == 'email')
{
self::_email($ping, $contact);
}
}
// Else its time to contact secondary folks
// or just STOP!!! No More Messages!
else
{

}
}
}
}
}

private static function _sms($ping, $contact)
{
// Get the SMS provider to use
try
{
$provider = PingApp_SMS_Provider::instance();
}
catch (PingApp_Exception $e)
{
Kohana::$log->add(Log::ERROR, $e->getMessage());
}

if (($tracking_id = $provider->send($contact->contact, $ping->message->message)) !== FALSE)
{
$ping->tracking_id = $tracking_id;
$ping->sent = 1;
$ping->save();
}
}

private static function _email($ping, $contact)
{

}
}
2 changes: 1 addition & 1 deletion application/classes/PingApp/Redis.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public static function factory()
if ( ! PingApp_Redis::$redis)
{
// No config file found
if (!Kohana::$config->load('redis'))
if ( ! Kohana::$config->load('redis'))
{
PingApp_Redis::$redis = new Predis\Client(array(
'scheme' => 'tcp',
Expand Down
11 changes: 3 additions & 8 deletions application/classes/Task/Ping.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ protected function _queue()

// Get All Unsent Pings
$pings = ORM::factory('Ping')
->where('pending', '=', 'pending')
->where('status', '=', 'pending')
->where('sent', '!=', 1)
->find_all();

foreach ($pings as $ping)
Expand Down Expand Up @@ -77,10 +78,7 @@ protected function _process()

if ( isset($item[1]) )
{
// Remove remaining dupes
$redis->lRem('searches', $item[1], 0);

PingApp_Ping::run($item[1]);
PingApp_Ping::process((int) $item[1]);
}
else
{
Expand All @@ -92,11 +90,8 @@ protected function _process()
}
catch (Exception $e)
{
//Log::instance()->add(Log::ERROR, 'SEARCHES TASK: '.Kohana_Exception::text($e));
break;
}
}

//echo View::factory('profiler/stats');
}
}
Loading

0 comments on commit 21eac91

Please sign in to comment.