revolutionizing enterprise web development

50
Revolutionizin g enterprise web development \ Drupal Queue API: Built In Procrastination

Upload: tatum-vaughan

Post on 31-Dec-2015

34 views

Category:

Documents


1 download

DESCRIPTION

Drupal Queue API : Built In Procrastination. \. Revolutionizing enterprise web development. Overview. What is a queue? When do you want to queue? Drupal Queue 7 Classes and Methods Batch API Implementing Batch Summary. What is a Queue?. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Revolutionizing enterprise web development

Revolutionizingenterprise web development

\

Drupal Queue API:Built In Procrastination

Page 2: Revolutionizing enterprise web development

Overview

• What is a queue?• When do you want to queue?• Drupal Queue 7 Classes and Methods• Batch API• Implementing Batch• Summary

Page 3: Revolutionizing enterprise web development

What is a Queue?

• Queue: A line or sequence of people or vehicles awaiting their turn to be attended to or to proceed.

What does this mean to developers?• Queue: A sequence of items awaiting

their turn to be processed.

Page 4: Revolutionizing enterprise web development

Presentation Problem

• Client Wants a Drupal site where user interactions need to be processed.– User updates a title -> gets put into a queue

to be processed.– User changes a field -> gets put into a queue

to be processed.– User publishes a node -> gets put into a

queue to be processed.• Requests are programmatically

moderated. • Moderating AI can be slow, likes to take

lunch breaks, has a mind of it’s own.

Page 5: Revolutionizing enterprise web development

Very Simple Queue Example

User Requests: A sequence* of requests from a user.

* These items must be done in order. FIFO

item_id data

1 {'uid' => 100, 'request' => 'Publish My Blog Post'}

2 {'uid' => 100, 'request' => 'Update My Blog Title'}

3 {'uid' => 100, 'request' => 'Publish Latest Blogs To Drupal Planet'}

Page 6: Revolutionizing enterprise web development

FIFO

Page 7: Revolutionizing enterprise web development

What is a Queue (again) ?

• Queue: A sequence of items awaiting their turn to be processed.

• Do items always need to be processed in a sequence? – No.

• Queue: A set of items awaiting their turn to be processed.

Page 8: Revolutionizing enterprise web development

Very Simple Queue Example 2

User Requests: A set* of requests from a user.

* These items don’t need to be done in order.

item_id data

1 {'uid' => 100, 'request' => 'Up vote Blog-A'}

2 {'uid' => 200, 'request' => 'Down vote Blog-A'}

3 {'uid' => 300, 'request' => 'Up vote Blog-B'}

Page 9: Revolutionizing enterprise web development

Set

Page 10: Revolutionizing enterprise web development

Multiple Workers

Page 11: Revolutionizing enterprise web development

When do you want a queue?

Queues work best when you have a lot of items which eventually need to be processed.

Some examples:

• Mass Email

• Content Indexing

• Order Processing

• Third Party Service Requests (Saleforce, MailChimp, etc.)

Page 12: Revolutionizing enterprise web development

When do you want a queue?

// When you are doing way too much$query = selectQuery('user_requests', 'ur');

$res = $query->fields('ur')->execute();while ($req = $res->fetchObject()) { if (user_requests_process_request($req)) {

user_requests_delete_request($req); }}

Page 13: Revolutionizing enterprise web development

Queue Basics• Create a Queue

o Gotta start somewhere

• Add item to the Queueo Put something into the queue for later.

• Claim an item from the Queueo Get me the next Item that needs to be

done.

• Release the item from the Queueo Leave the item back in the queue because

it couldn't be processed yet.

• Remove the item from the Queue

• Count how many items are left in the Queue.

Page 14: Revolutionizing enterprise web development

DrupalQueueInterface::

createQueue() - Create a queuecreateItem() - Add an item to the queueclaimItem() - Claim next queue item. Lock.releaseItem() - Leave the item in the queuedeleteItem() - Delete the item from the

queue.numberOffItems() - Retrieve the number of

items in the queue.

More@ http://dgo.to/a/DrupalQueueInterface

Page 15: Revolutionizing enterprise web development

Drupal Core Queues

Storage: Database

• SystemQueue

• BatchQueue extends SystemQueue

Storage: Memory

• MemoryQueue

• BatchMemoryQueue extends MemoryQueue

Page 16: Revolutionizing enterprise web development

Adding Items to SystemQueue$queue = DrupalQueue::get('user_requests');$queue->createQueue();$requests = array();$requests[]= array('uid' => 100, 'request' => 'upvote node 1');$requests[]= array('uid' => 200, 'request' => 'downvote node 2');$requests[]= array('uid' => 300, 'request' => 'upvote node 1');

foreach ($requests as $request) { // Adds the item as a serialized string to the queue table $queue->createItem($request);}

Page 17: Revolutionizing enterprise web development

SystemQueue Queue Table

Page 18: Revolutionizing enterprise web development

Work is lined up, now what?

Data processing strategy:

• Does the work have to be done in order it was queued?

• Do we have a limit of items we're allowed to process per day?

• Do we have the resources to run multiple processing workers in parallel?

Page 19: Revolutionizing enterprise web development

Simple Queue processor

function user_requests_processor_1() { $queue = DrupalQueue::get('user_requests'); while($queue->numberOfItems()) { $request = $queue->claimItem(); user_requests_process_request($request); $queue->deleteItem($item); // Done, remove it from queue }}

Page 20: Revolutionizing enterprise web development

Feedback on Worker

Worker: user_requests_processor_1

• Still times out

• Potential headaches depending on the success rate of user_request_process_request()

• Potential headaches if running multiple workers.

• Better memory footprint.

• Overall a positive change

Page 21: Revolutionizing enterprise web development

Working with a Queuefunction user_requests_processor_2() { $queue = DrupalQueue::get('user_requests'); $ops = array('%count' => $queue->numberOfItems()); drupal_set_message("Processing user requests. %count Items in

queue.", $ops); while ($request = $queue->claimItem()) { if (user_requests_process_request($request)) { $queue->deleteItem($item); // Done, remove it from queue } else { // Couldn't process this. Leave it in the queue $queue->releaseItem($item); } }}

Page 22: Revolutionizing enterprise web development

Feedback on Worker

Worker: user_requests_processor_2

• Both will time out... but....

• Can run in scaled up or down as needed. Big win.

Page 23: Revolutionizing enterprise web development

Need a better Queue?

• Store items in a different location?• Want to notify somebody when you

create a Queue?• Don’t want to allow locking of items?

Page 24: Revolutionizing enterprise web development

Subclass SystemQueueclass BatchQueue extends SystemQueue { public function claimItem($lease_time = 0) { // Ignores lease time. Forces sequential processing. $item = db_query_range('SELECT data, item_id FROM {queue} q WHERE name = :name ORDER BY item_id

ASC', 0, 1, array(':name' => $this->name))->fetchObject(); if ($item) { $item->data = unserialize($item->data); return $item; } return FALSE; }

public function getAllItems() { $result = array(); $items = db_query('SELECT data FROM {queue} q WHERE name = :name ORDER BY item_id ASC',

array(':name' => $this->name))->fetchAll(); foreach ($items as $item) { $result[] = unserialize($item->data); } return $result; }}

Page 25: Revolutionizing enterprise web development

Subclass SystemQueueclass AwesomeQueue extends SystemQueue { public function releaseMultipleItems($items) { // Release multiple items }}

Page 26: Revolutionizing enterprise web development

Extending SystemQueue

DrupalQueue::get('user_requests');new SystemQueue('user_requests');

// But we need an AwesomeQueuenew AwesomeQueue('user_requests');

Page 27: Revolutionizing enterprise web development

Need a better Queue?Changing our Queue Classvariable_set('queue_class_user_request', 'AwesomeQueue');

Change Queue Class by Queuevariable_get('queue_class_' . $name, NULL);

Additionally…

Change Default Queue Classvariable_get('queue_default_class', 'SystemQueue');

Page 28: Revolutionizing enterprise web development

What about MemoryQueue?

• MemoryQueue implements the same base interface as SystemQueue.

• Items you put into a MemoryQueue need to be processed within the same request.

• Use it for small queues you know you can take care off in one page request. Otherwise, stick to the SystemQueue.

Page 29: Revolutionizing enterprise web development

Helpful Links/Debugging

Interactive Queuedhttp://tinyurl.com/cyk9qch

Views Queuehttp://dgo.to/views_queue

Queue UIhttp://dgo.to/queue_ui

Page 30: Revolutionizing enterprise web development

Simple Queue process in chunks

function user_requests_processor_3() { $queue = DrupalQueue::get('user_requests'); while($queue->numberOfItems()) { $limit = 1000; $chunk = array(); while ($limit && $request = $queue->claimItem()) { $limit--; $chunk[] = $request; $queue->deleteItem($item); // Done, remove it from queue } user_requests_process_requests($chunk); }}

Page 31: Revolutionizing enterprise web development

Batch API

Built In Procrastination

Page 32: Revolutionizing enterprise web development

What is Batch?

• Another tool for getting a lot of work done.

• Built to help fight off issues with hitting max_execution_time

Page 33: Revolutionizing enterprise web development

When to use Batch

• When you have a lot of tasks that need to be done.

• When you want inform the user of progress on the work.

Page 34: Revolutionizing enterprise web development

You've seen Batch at work

Familiar Cases:Drupal InstallRebuild Node AccessDrupal UpdatePretty much whenever you see a progress

bar

Page 35: Revolutionizing enterprise web development

How does batch fight off timeout?

Batch Form Submit

Batch Engine

How much work is there to do? Where are we at?Batch

EngineDo SOME of the work.

Are we finishe

d?No

New HTTP RequestReset the

clock! yey!

YesBatch Engine

Complete

Page 36: Revolutionizing enterprise web development

Lets get to it!function user_requests_batch_form($form, &$form_state) { $form['submit'] = array( '#type' => 'submit', '#value' => t('Process User Requests'), ); return $form;}function user_requests_batch_form_submit($form, &$form_state) { $batch = array( 'operations' => array( array(user_requests_process_batch_requests', array()), ), ); batch_set($batch);}

Page 37: Revolutionizing enterprise web development

Multiple Operationsfunction user_requests_batch_form_submit($form, &$form_state) { $batch = array( 'operations' => array( array( 'user_requests_preprocess_requests', array() ), array( 'user_requests_process_requests', array('argument_1', 'argument2') ), ), ); batch_set($batch);}

Page 38: Revolutionizing enterprise web development

Batch variables $batch = array( 'init_message' => t('Getting ready to Process User Requests'), 'title' => t('Processing User Requests'), 'progress_message' => t('Processed @current of @total User

Requests'), 'error_message' => t('An Error occurred while processing User

Request'), 'finished' => 'user_requests_finished_batch_work', 'operations' => array( array( 'user_requests_preprocess_requests',array()), ), ), );

Page 39: Revolutionizing enterprise web development

$batch['progess_message']

@current - current operation@remaining - remaining operations@total - total operations@percentage - percentage complete@elapsed - Time elapsed

Defaults to t('Completed @current of @total.').

Page 40: Revolutionizing enterprise web development

Batch Operation Callbacks

Operation callbacks need to accept $context variable.

function user_requests_preprocess_requests(&$context);

function user_requests_process_requests($arg1, $arg2, &$context);

Page 41: Revolutionizing enterprise web development

Batch $context

// Operations can tell Batch what they have done$context['results'][];// The message to display on the progress page$context['message'];// Sandbox is primary means of communication between

Iterations$context['sandbox']; // A float between 0 and 1 the tells the batch engine is the

batch work is done. Defaults to 1.// Moves the progress bar forward.$context['finished'] = 0;

Page 42: Revolutionizing enterprise web development

Back to our user requestsuser_requests_process_batch_requests(&$context) { if (empty($context['sandbox'])) { $context['sandbox']['max'] = count_db_items(); $context['sandbox']['current'] = 0; } // Fetch next item $context['sandbox']['current']++; user_requests_process_request($request); $context['message'] = 'Processed request ' . $request-

>id $max = $context['sandbox']['max']; $context['finished'] =

$context['sandbox']['current']/$max;}

Page 43: Revolutionizing enterprise web development

User Requests Demo

Page 44: Revolutionizing enterprise web development

Bringing it together

• DrupalQueue and Batch work great as Complementary Systems.– DrupalQueue set tasks up.– Batch knocks them down.

Page 45: Revolutionizing enterprise web development

DrupalQueue in Batch Operation #1

user_requests_process_batch_requests(&$context) { $queue = DrupalQueue::get('user_requests'); if (empty($context['sandbox'])) { $context['sandbox']['max']=$queue->numberOfItems(); $context['sandbox']['current']=0; } $request=$queue->claimItem(); $context['sandbox']['current']++; user_requests_process_request($request); $queue->deleteItem($request); $max = $context['sandbox']['max']; $context['finished'] = $context['sandbox']['current']/$max;

}

Page 46: Revolutionizing enterprise web development

DrupalQueue in Batch Operation #2user_requests_process_batch_requests(&$context) { $queue = DrupalQueue::get('user_requests'); if (empty($context['sandbox'])) { $context['sandbox']['max'] = $queue->numberOfItems(); $context['sandbox']['current'] = 0; } for ($i = 1; $i < 20; $i++) { // Process 20 items on each request. if ($request = $queue->claimItem()){ $context['sandbox']['current']++; user_requests_process_request($request); $queue->deleteItem($request); } } $max = $context['sandbox']['max']; $context['finished'] = $context['sandbox']['current']/$max;}

Page 47: Revolutionizing enterprise web development

Further Reading

Batch Operations Pagehttp://tinyurl.com/7asc4p8

Batch Example Module in Examples projecthttp://dgo.to/examples

Page 48: Revolutionizing enterprise web development

Summary

DrupalQueue - SystemQueue• Great for saving work you can do later.• Simple tool with big implications.

– Great way to bring distributed processing of data to you Drupal projects.

DrupalQueue - MemoryQueue• Use it for lining up tasks that can be

handled in one request.

Page 49: Revolutionizing enterprise web development

Summary

Batch API• Drupal's goto solution for getting past

max_execution_time limits• Great for processing a large amount of in

chunks at a time.• Really shines when users need to be

notified of progress on the work being completed.

• Compliments DrupalQueue very well.

Page 50: Revolutionizing enterprise web development

Thank YouDagoberto Aceves

www.achieveinternet.comdago.aceves