├── .gitattributes ├── .gitignore ├── Complex-Routing ├── consumer.js ├── developerLog.js ├── fulfilmentLog.js ├── loggingService.js ├── operationsLog.js ├── orderService.js ├── producer.js ├── runLogger.js ├── sendEmail.js ├── updateInventory.js ├── updateRecommendations.js └── updateReporting.js ├── Hello-world ├── consumer.js └── producer.js ├── Installing-Node-js ├── greetings.js └── server.js ├── Message-Acknowledgment ├── consumer.js ├── orderService.js └── producer.js ├── Persistent-Messages ├── consumer.js ├── orderService.js └── producer.js ├── Publish-Subscribe ├── consumer.js ├── orderService.js ├── producer.js ├── sendEmail.js ├── updateInventory.js ├── updateRecommendations.js └── updateReporting.js ├── Publisher-Confirms ├── consumer.js ├── orderService.js └── producer.js ├── README.md ├── Shop ├── order.js ├── orderService.js └── server.js ├── Work-Queues ├── consumer.js ├── orderService.js └── producer.js ├── package.json └── setup.js /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # node 2 | node_modules/ 3 | node.exe 4 | npm.cmd 5 | 6 | # Numerous always-ignore extensions 7 | *.diff 8 | *.err 9 | *.orig 10 | *.log 11 | *.rej 12 | *.swo 13 | *.swp 14 | *.vi 15 | *~ 16 | *.sass-cache 17 | 18 | # OS or Editor folders 19 | .DS_Store 20 | Thumbs.db 21 | .cache 22 | .project 23 | .settings 24 | .tmproj 25 | *.esproj 26 | nbproject 27 | *.sublime-project 28 | *.sublime-workspace 29 | 30 | # Dreamweaver added files 31 | _notes 32 | dwsync.xml 33 | 34 | # Komodo 35 | *.komodoproject 36 | .komodotools 37 | 38 | # Folders to ignore 39 | .hg 40 | .svn 41 | .CVS 42 | intermediate 43 | publish 44 | .idea 45 | 46 | # build script local files 47 | build/buildinfo.properties 48 | build/config/buildinfo.properties -------------------------------------------------------------------------------- /Complex-Routing/consumer.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Complex Routing Consumer.'); 2 | var orderService = require('./orderService'); 3 | var connect = require('amqp').createConnection(); 4 | var logging = require('./loggingService'); 5 | var logger = new logging(); 6 | 7 | connect.on('ready', function() { 8 | var ex = connect.exchange('shop.exchange', {type: 'direct', confirm:true}); 9 | var q = connect.queue('shop.queue', {durable:true, autoDelete:false}); 10 | 11 | q.on('queueDeclareOk', function(args) { 12 | q.bind('shop.exchange', 'order.key'); 13 | q.on('queueBindOk', function() { 14 | q.subscribe({ack:true}, function(message) { 15 | console.log('subscribe'); 16 | var service = new orderService(unescape(message.data)); 17 | var status = service.ProcessOrder(); 18 | if (status === 'OrderComplete') { 19 | var exf = connect.exchange('shop.fanout.exchange', {type: 'fanout'}); 20 | exf.setMaxListeners(0); 21 | exf.publish('', JSON.stringify(service.Order)); 22 | } 23 | q.shift(); 24 | logger.Log("Consumer", "WARN", "Remove order from queue"); 25 | }); 26 | }); 27 | }); 28 | }); -------------------------------------------------------------------------------- /Complex-Routing/developerLog.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Complex Routing Developer Logger.'); 2 | var connect = require('amqp').createConnection(); 3 | 4 | connect.on('ready', function() { 5 | var ex = connect.exchange('logging.exchange', {type: 'topic'}); 6 | var q = connect.queue('developer.logging.queue'); 7 | q.on('queueDeclareOk', function(args) { 8 | q.bind('logging.exchange', '*.log.ERROR'); 9 | q.on('queueBindOk', function() { 10 | q.subscribe(function(message) { 11 | console.log(unescape(message.data)); 12 | }); 13 | }); 14 | }); 15 | }); -------------------------------------------------------------------------------- /Complex-Routing/fulfilmentLog.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Complex Routing Fulfilment Logger.'); 2 | var connect = require('amqp').createConnection(); 3 | 4 | connect.on('ready', function() { 5 | var ex = connect.exchange('logging.exchange', {type: 'topic'}); 6 | var q = connect.queue('fulfilment.logging.queue'); 7 | q.on('queueDeclareOk', function(args) { 8 | q.bind('logging.exchange', 'Order.log.ERROR'); 9 | q.on('queueBindOk', function() { 10 | q.subscribe(function(message) { 11 | console.log(unescape(message.data)); 12 | }); 13 | }); 14 | }); 15 | }); -------------------------------------------------------------------------------- /Complex-Routing/loggingService.js: -------------------------------------------------------------------------------- 1 | module.exports = function loggingService() { 2 | this.Log = function (location, level, message) { 3 | var connect = require('amqp').createConnection(); 4 | connect.on('ready', function() { 5 | var ex = connect.exchange('logging.exchange', {type: 'topic'}); 6 | var q = connect.queue('logging.queue'); 7 | q.on('queueDeclareOk', function(args) { 8 | q.bind('logging.exchange'); 9 | q.on('queueBindOk', function() { 10 | ex.publish(location + '.log.' + level, message); 11 | }); 12 | }); 13 | }); 14 | }; 15 | }; -------------------------------------------------------------------------------- /Complex-Routing/operationsLog.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Complex Routing Operations Logger.'); 2 | var connect = require('amqp').createConnection(); 3 | 4 | connect.on('ready', function() { 5 | var ex = connect.exchange('logging.exchange', {type: 'topic'}); 6 | var q = connect.queue('operations.logging.queue'); 7 | q.on('queueDeclareOk', function(args) { 8 | q.bind('logging.exchange', '*.log.*'); 9 | q.on('queueBindOk', function() { 10 | q.subscribe(function(message) { 11 | console.log(unescape(message.data)); 12 | }); 13 | }); 14 | }); 15 | }); -------------------------------------------------------------------------------- /Complex-Routing/orderService.js: -------------------------------------------------------------------------------- 1 | var loggingService = require('./loggingService'); 2 | var logger = new loggingService(); 3 | 4 | module.exports = function OrderService(order) { 5 | this.Order = order; 6 | this.Checkout = function() { 7 | logger.Log("Checkout", "INFO", "Placed order " + this.Order.OrderId); 8 | }; 9 | this.ProcessOrder = function() { 10 | this.PaymentGateway(); 11 | this.UpdateStatus(); 12 | logger.Log("ProcessOrder", "INFO", "Thank you for placing your order"); 13 | return this.Status; 14 | }; 15 | this.PaymentGateway = function() { 16 | logger.Log("PaymentGateway", "INFO", "Made payment"); 17 | this.Status = "OrderComplete"; 18 | }; 19 | this.UpdateStatus = function() { 20 | logger.Log("UpdateStatus", "INFO", "Updated status"); 21 | }; 22 | this.UpdateInventory = function() { 23 | logger.Log("UpdateInventory", "INFO", "Updated inventory"); 24 | }; 25 | this.SendEmail = function() { 26 | logger.Log("SendEmail", "INFO", "Sent email"); 27 | }; 28 | this.UpdateReporting = function() { 29 | logger.Log("UpdateReporting", "INFO", "Updated reporting"); 30 | }; 31 | this.UpdateRecommendations = function() { 32 | logger.Log("UpdateRecommendations", "INFO", "Updated recommendations"); 33 | }; 34 | }; -------------------------------------------------------------------------------- /Complex-Routing/producer.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Complex Routing Producer.'); 2 | var order = require('../Shop/order'); 3 | var orderService = require('./orderService'); 4 | var connect = require('amqp').createConnection(); 5 | var logging = require('./loggingService'); 6 | var logger = new logging(); 7 | var orderId = 0; 8 | 9 | connect.on('ready', function() { 10 | var ex = connect.exchange('shop.exchange', {type: 'direct', confirm:true}); 11 | ex.setMaxListeners(0); 12 | var q = connect.queue('shop.queue', {durable:true, autoDelete:false}); 13 | q.on('queueDeclareOk', function(args) { 14 | q.bind('shop.exchange', 'order.key'); 15 | q.on('queueBindOk', function() { 16 | console.log("Place your order"); 17 | setInterval(function(){ 18 | var newOrder = new order(++orderId); 19 | var service = new orderService(newOrder); 20 | service.Checkout(); 21 | 22 | if (orderId == 10) 23 | logger.Log("Order", "ERROR", "Unable to make payment for " + orderId); 24 | 25 | ex.publish('order.key', JSON.stringify(newOrder), {deliveryMode:2}, function(isError){ 26 | if (isError) 27 | logger.Log("Order", "ERROR", "Order has not been acknowledged"); 28 | }); 29 | }, 1000); 30 | }); 31 | }); 32 | }); -------------------------------------------------------------------------------- /Complex-Routing/runLogger.js: -------------------------------------------------------------------------------- 1 | var logging = require('./logging'); 2 | var logger = new logging(); 3 | logger.Log("SendEmail", "INFO", "Sent email"); 4 | logger.Log("Producer", "ERROR","Order has not been acknowledged"); 5 | logger.Log("Order", "ERROR","Payment was not accepted"); -------------------------------------------------------------------------------- /Complex-Routing/sendEmail.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Complex Routing Send Email.'); 2 | var orderService = require('./orderService'); 3 | var connect = require('amqp').createConnection(); 4 | 5 | connect.on('ready', function() { 6 | var ex = connect.exchange('shop.fanout.exchange', {type: 'fanout'}); 7 | var q = connect.queue('shop.email.queue'); 8 | q.on('queueDeclareOk', function(args) { 9 | q.bind('shop.fanout.exchange', ''); 10 | q.on('queueBindOk', function() { 11 | q.subscribe(function(message) { 12 | var service = new orderService(unescape(message.data)); 13 | service.SendEmail(); 14 | }); 15 | }); 16 | }); 17 | }); -------------------------------------------------------------------------------- /Complex-Routing/updateInventory.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Complex Routing Update Inventory.'); 2 | var orderService = require('./orderService'); 3 | var connect = require('amqp').createConnection(); 4 | 5 | connect.on('ready', function() { 6 | var ex = connect.exchange('shop.fanout.exchange', {type: 'fanout'}); 7 | var q = connect.queue('shop.inventory.queue'); 8 | q.on('queueDeclareOk', function(args) { 9 | q.bind('shop.fanout.exchange', ''); 10 | q.on('queueBindOk', function() { 11 | q.subscribe(function(message) { 12 | var service = new orderService(unescape(message.data)); 13 | service.UpdateInventory(); 14 | }); 15 | }); 16 | }); 17 | }); -------------------------------------------------------------------------------- /Complex-Routing/updateRecommendations.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Complex Routing Update Recommendations.'); 2 | var orderService = require('./orderService'); 3 | var connect = require('amqp').createConnection(); 4 | 5 | connect.on('ready', function() { 6 | var ex = connect.exchange('shop.fanout.exchange', {type: 'fanout'}); 7 | var q = connect.queue('shop.recommendations.queue'); 8 | q.on('queueDeclareOk', function(args) { 9 | q.bind('shop.fanout.exchange', ''); 10 | q.on('queueBindOk', function() { 11 | q.subscribe(function(message) { 12 | var service = new orderService(unescape(message.data)); 13 | service.UpdateRecommendations(); 14 | }); 15 | }); 16 | }); 17 | }); -------------------------------------------------------------------------------- /Complex-Routing/updateReporting.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Complex Routing Update Reporting.'); 2 | var orderService = require('./orderService'); 3 | var connect = require('amqp').createConnection(); 4 | 5 | connect.on('ready', function() { 6 | var ex = connect.exchange('shop.fanout.exchange', {type: 'fanout'}); 7 | var q = connect.queue('shop.reporting.queue'); 8 | q.on('queueDeclareOk', function(args) { 9 | q.bind('shop.fanout.exchange', ''); 10 | q.on('queueBindOk', function() { 11 | q.subscribe(function(message) { 12 | var service = new orderService(unescape(message.data)); 13 | service.UpdateReporting(); 14 | }); 15 | }); 16 | }); 17 | }); -------------------------------------------------------------------------------- /Hello-world/consumer.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Hello World.'); 2 | var connect = require('amqp').createConnection(); 3 | 4 | connect.on('ready', function() { 5 | var q = connect.queue('hello'); 6 | q.on('queueDeclareOk', function(args) { 7 | q.bind('#'); 8 | q.on('queueBindOk', function() { 9 | q.subscribe(function(message) { 10 | console.log(JSON.parse(message.data.toString())); 11 | }); 12 | }); 13 | }); 14 | }); -------------------------------------------------------------------------------- /Hello-world/producer.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Hello World.'); 2 | var connect = require('amqp').createConnection(); 3 | var messages = []; 4 | messages.push(' (\\-/)'); 5 | messages.push(" ('.') –> hello world"); 6 | messages.push('(") (")'); 7 | 8 | connect.on('ready', function() { 9 | var ex = connect.exchange(); 10 | var q = connect.queue('hello'); 11 | q.on('queueDeclareOk', function(args) { 12 | q.bind('#'); 13 | q.on('queueBindOk', function() { 14 | messages.forEach(function(message) { 15 | var data = JSON.stringify(message); 16 | ex.publish('hello', data, {}); 17 | }); 18 | }); 19 | }); 20 | }); -------------------------------------------------------------------------------- /Installing-Node-js/greetings.js: -------------------------------------------------------------------------------- 1 | var util = require('util'); 2 | 3 | exports.hello = function hello() { 4 | util.puts('Hello world'); 5 | } -------------------------------------------------------------------------------- /Installing-Node-js/server.js: -------------------------------------------------------------------------------- 1 | var greetings = require('./greetings'); 2 | greetings.hello(); -------------------------------------------------------------------------------- /Message-Acknowledgment/consumer.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Message Acknowledgement.'); 2 | var orderService = require('./orderService'); 3 | var connect = require('amqp').createConnection(); 4 | 5 | connect.on('ready', function() { 6 | var ex = connect.exchange('shop.exchange', {type: 'direct'}); 7 | var q = connect.queue('shop.queue', {durable:true, autoDelete:false}); 8 | q.on('queueDeclareOk', function(args) { 9 | q.bind('shop.exchange', 'order.key'); 10 | q.on('queueBindOk', function() { 11 | q.subscribe({ack:true}, function(message) { 12 | var service = new orderService(unescape(message.data)); 13 | service.ProcessOrder(); 14 | q.shift(); 15 | console.log('WARN, Remove order from queue.'); 16 | }); 17 | }); 18 | }); 19 | }); -------------------------------------------------------------------------------- /Message-Acknowledgment/orderService.js: -------------------------------------------------------------------------------- 1 | module.exports = function OrderService(order) { 2 | this.Order = order; 3 | this.Checkout = function() { 4 | console.log("INFO, Placed order " + this.Order.OrderId); 5 | }; 6 | this.ProcessOrder = function() { 7 | this.PaymentGateway(); 8 | this.UpdateStatus(); 9 | if (this.Status === 'OrderComplete') { 10 | this.UpdateInventory(); 11 | this.SendEmail(); 12 | this.UpdateReporting(); 13 | } 14 | console.log('INFO, Thank you for placing your order...'); 15 | }; 16 | this.PaymentGateway = function() { 17 | console.log('INFO, Made payment'); 18 | this.Status = "OrderComplete"; 19 | }; 20 | this.UpdateStatus = function() { 21 | console.log('INFO, Updated status'); 22 | }; 23 | this.UpdateInventory = function() { 24 | console.log('INFO, Updated inventory'); 25 | }; 26 | this.SendEmail = function() { 27 | console.log('INFO, Sent email'); 28 | }; 29 | this.UpdateReporting = function() { 30 | console.log('INFO, Updated reporting'); 31 | }; 32 | }; -------------------------------------------------------------------------------- /Message-Acknowledgment/producer.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Message Acknowledgement.'); 2 | var order = require('../Shop/order'); 3 | var orderService = require('./orderService'); 4 | var connect = require('amqp').createConnection(); 5 | var orderId = 0; 6 | 7 | connect.on('ready', function() { 8 | var ex = connect.exchange('shop.exchange', {type: 'direct'}); 9 | var q = connect.queue('shop.queue', {durable:true, autoDelete:false}); 10 | q.on('queueDeclareOk', function(args) { 11 | q.bind('shop.exchange', 'order.key'); 12 | q.on('queueBindOk', function() { 13 | console.log("Place your order"); 14 | setInterval(function(){ 15 | var newOrder = new order(++orderId); 16 | var service = new orderService(newOrder); 17 | service.Checkout(); 18 | ex.publish('order.key', JSON.stringify(newOrder), {deliveryMode:2}); 19 | }, 100); 20 | }); 21 | }); 22 | }); -------------------------------------------------------------------------------- /Persistent-Messages/consumer.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Persistent Messages.'); 2 | var orderService = require('./orderService'); 3 | var connect = require('amqp').createConnection(); 4 | 5 | connect.on('ready', function() { 6 | var ex = connect.exchange('shop.exchange', {type: 'direct'}); 7 | var q = connect.queue('shop.queue', {durable:true}); 8 | q.on('queueDeclareOk', function(args) { 9 | q.bind('shop.exchange', 'order.key'); 10 | q.on('queueBindOk', function() { 11 | q.subscribe(function(message) { 12 | var service = new orderService(unescape(message.data)); 13 | service.ProcessOrder(); 14 | }); 15 | }); 16 | }); 17 | }); -------------------------------------------------------------------------------- /Persistent-Messages/orderService.js: -------------------------------------------------------------------------------- 1 | module.exports = function OrderService(order) { 2 | this.Order = order; 3 | this.Checkout = function() { 4 | console.log("INFO, Placed order " + this.Order.OrderId); 5 | }; 6 | this.ProcessOrder = function() { 7 | this.PaymentGateway(); 8 | this.UpdateStatus(); 9 | if (this.Status === 'OrderComplete') { 10 | this.UpdateInventory(); 11 | this.SendEmail(); 12 | this.UpdateReporting(); 13 | } 14 | console.log('INFO, Thank you for placing your order...'); 15 | }; 16 | this.PaymentGateway = function() { 17 | console.log('INFO, Made payment'); 18 | this.Status = "OrderComplete"; 19 | }; 20 | this.UpdateStatus = function() { 21 | console.log('INFO, Updated status'); 22 | }; 23 | this.UpdateInventory = function() { 24 | console.log('INFO, Updated inventory'); 25 | }; 26 | this.SendEmail = function() { 27 | console.log('INFO, Sent email'); 28 | }; 29 | this.UpdateReporting = function() { 30 | console.log('INFO, Updated reporting'); 31 | }; 32 | }; -------------------------------------------------------------------------------- /Persistent-Messages/producer.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Persistent Messages.'); 2 | var order = require('../Shop/order'); 3 | var orderService = require('./orderService'); 4 | var connect = require('amqp').createConnection(); 5 | var orderId = 0; 6 | connect.on('ready', function() { 7 | var ex = connect.exchange('shop.exchange', {type: 'direct'}); 8 | var q = connect.queue('shop.queue', {durable:true}); 9 | q.on('queueDeclareOk', function(args) { 10 | q.bind('shop.exchange', 'order.key'); 11 | q.on('queueBindOk', function() { 12 | console.log("Place your order"); 13 | setInterval(function(){ 14 | var newOrder = new order(++orderId); 15 | var service = new orderService(newOrder); 16 | service.Checkout(); 17 | ex.publish('order.key', JSON.stringify(newOrder), {deliveryMode:2}); 18 | }, 100); 19 | }); 20 | }); 21 | }); -------------------------------------------------------------------------------- /Publish-Subscribe/consumer.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Publish Subscribe Consumer.'); 2 | var orderService = require('./orderService'); 3 | var connect = require('amqp').createConnection(); 4 | 5 | connect.on('ready', function() { 6 | var ex = connect.exchange('shop.exchange', {type: 'direct', confirm:true}); 7 | var q = connect.queue('shop.queue', {durable:true, autoDelete:false}); 8 | 9 | q.on('queueDeclareOk', function(args) { 10 | q.bind('shop.exchange', 'order.key'); 11 | q.on('queueBindOk', function() { 12 | q.subscribe({ack:true}, function(message) { 13 | var service = new orderService(unescape(message.data)); 14 | var status = service.ProcessOrder(); 15 | if (status === 'OrderComplete') { 16 | var exf = connect.exchange('shop.fanout.exchange', {type: 'fanout'}); 17 | exf.setMaxListeners(0); 18 | exf.publish('', JSON.stringify(service.Order)); 19 | } 20 | q.shift(); 21 | console.log('INFO, Remove order from queue.'); 22 | }); 23 | }); 24 | }); 25 | }); -------------------------------------------------------------------------------- /Publish-Subscribe/orderService.js: -------------------------------------------------------------------------------- 1 | module.exports = function OrderService(order) { 2 | this.Order = order; 3 | this.Checkout = function() { 4 | console.log("INFO, Placed order " + this.Order.OrderId); 5 | }; 6 | this.ProcessOrder = function() { 7 | this.PaymentGateway(); 8 | this.UpdateStatus(); 9 | console.log('INFO, Thank you for placing your order...'); 10 | return this.Status; 11 | }; 12 | this.PaymentGateway = function() { 13 | console.log('INFO, Made payment'); 14 | this.Status = "OrderComplete"; 15 | }; 16 | this.UpdateStatus = function() { 17 | console.log('INFO, Updated status'); 18 | }; 19 | this.UpdateInventory = function() { 20 | console.log('INFO, Updated inventory'); 21 | }; 22 | this.SendEmail = function() { 23 | console.log('INFO, Sent email'); 24 | }; 25 | this.UpdateReporting = function() { 26 | console.log('INFO, Updated reporting'); 27 | }; 28 | this.UpdateRecommendations = function() { 29 | console.log('INFO, Updated recommendations'); 30 | }; 31 | }; -------------------------------------------------------------------------------- /Publish-Subscribe/producer.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Publish Subscribe Producer.'); 2 | var order = require('../Shop/order'); 3 | var orderService = require('./orderService'); 4 | var connect = require('amqp').createConnection(); 5 | var orderId = 0; 6 | 7 | connect.on('ready', function() { 8 | var ex = connect.exchange('shop.exchange', {type: 'direct', confirm:true}); 9 | ex.setMaxListeners(0); 10 | var q = connect.queue('shop.queue', {durable:true, autoDelete:false}); 11 | q.on('queueDeclareOk', function(args) { 12 | q.bind('shop.exchange', 'order.key'); 13 | q.on('queueBindOk', function() { 14 | console.log("Place your order"); 15 | setInterval(function(){ 16 | var newOrder = new order(++orderId); 17 | var service = new orderService(newOrder); 18 | service.Checkout(); 19 | ex.publish('order.key', JSON.stringify(newOrder), {deliveryMode:2}, function(isError){ 20 | if (isError) 21 | console.log('ERROR, Order has not been acknowledged.'); 22 | }); 23 | }, 1000); 24 | }); 25 | }); 26 | }); -------------------------------------------------------------------------------- /Publish-Subscribe/sendEmail.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Publish Subscribe Send Email.'); 2 | var orderService = require('./orderService'); 3 | var connect = require('amqp').createConnection(); 4 | 5 | connect.on('ready', function() { 6 | var ex = connect.exchange('shop.fanout.exchange', {type: 'fanout'}); 7 | var q = connect.queue('shop.email.queue'); 8 | q.on('queueDeclareOk', function(args) { 9 | q.bind('shop.fanout.exchange', ''); 10 | q.on('queueBindOk', function() { 11 | q.subscribe(function(message) { 12 | var service = new orderService(unescape(message.data)); 13 | service.SendEmail(); 14 | }); 15 | }); 16 | }); 17 | }); -------------------------------------------------------------------------------- /Publish-Subscribe/updateInventory.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Publish Subscribe Update Inventory.'); 2 | var orderService = require('./orderService'); 3 | var connect = require('amqp').createConnection(); 4 | 5 | connect.on('ready', function() { 6 | var ex = connect.exchange('shop.fanout.exchange', {type: 'fanout'}); 7 | var q = connect.queue('shop.inventory.queue'); 8 | q.on('queueDeclareOk', function(args) { 9 | q.bind('shop.fanout.exchange', ''); 10 | q.on('queueBindOk', function() { 11 | q.subscribe(function(message) { 12 | var service = new orderService(unescape(message.data)); 13 | service.UpdateInventory(); 14 | }); 15 | }); 16 | }); 17 | }); -------------------------------------------------------------------------------- /Publish-Subscribe/updateRecommendations.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Publish Subscribe Update Recommendations.'); 2 | var orderService = require('./orderService'); 3 | var connect = require('amqp').createConnection(); 4 | 5 | connect.on('ready', function() { 6 | var ex = connect.exchange('shop.fanout.exchange', {type: 'fanout'}); 7 | var q = connect.queue('shop.recommendations.queue'); 8 | q.on('queueDeclareOk', function(args) { 9 | q.bind('shop.fanout.exchange', ''); 10 | q.on('queueBindOk', function() { 11 | q.subscribe(function(message) { 12 | var service = new orderService(unescape(message.data)); 13 | service.UpdateRecommendations(); 14 | }); 15 | }); 16 | }); 17 | }); -------------------------------------------------------------------------------- /Publish-Subscribe/updateReporting.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Publish Subscribe Update Reporting.'); 2 | var orderService = require('./orderService'); 3 | var connect = require('amqp').createConnection(); 4 | 5 | connect.on('ready', function() { 6 | var ex = connect.exchange('shop.fanout.exchange', {type: 'fanout'}); 7 | var q = connect.queue('shop.reporting.queue'); 8 | q.on('queueDeclareOk', function(args) { 9 | q.bind('shop.fanout.exchange', ''); 10 | q.on('queueBindOk', function() { 11 | q.subscribe(function(message) { 12 | var service = new orderService(unescape(message.data)); 13 | service.UpdateReporting(); 14 | }); 15 | }); 16 | }); 17 | }); -------------------------------------------------------------------------------- /Publisher-Confirms/consumer.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Producer Consumer.'); 2 | var orderService = require('./orderService'); 3 | var connect = require('amqp').createConnection(); 4 | 5 | connect.on('ready', function() { 6 | var ex = connect.exchange('shop.exchange', {type: 'direct', confirm:true}); 7 | var q = connect.queue('shop.queue', {durable:true, autoDelete:false}); 8 | q.on('queueDeclareOk', function(args) { 9 | q.bind('shop.exchange', 'order.key'); 10 | q.on('queueBindOk', function() { 11 | q.subscribe({ack:true}, function(message) { 12 | var service = new orderService(unescape(message.data)); 13 | service.ProcessOrder(); 14 | q.shift(); 15 | console.log('INFO, Remove order from queue.'); 16 | }); 17 | }); 18 | }); 19 | }); -------------------------------------------------------------------------------- /Publisher-Confirms/orderService.js: -------------------------------------------------------------------------------- 1 | module.exports = function OrderService(order) { 2 | this.Order = order; 3 | this.Checkout = function() { 4 | console.log("INFO, Placed order " + this.Order.OrderId); 5 | }; 6 | this.ProcessOrder = function() { 7 | this.PaymentGateway(); 8 | this.UpdateStatus(); 9 | if (this.Status === 'OrderComplete') { 10 | this.UpdateInventory(); 11 | this.SendEmail(); 12 | this.UpdateReporting(); 13 | } 14 | console.log('INFO, Thank you for placing your order...'); 15 | }; 16 | this.PaymentGateway = function() { 17 | console.log('INFO, Made payment'); 18 | this.Status = "OrderComplete"; 19 | }; 20 | this.UpdateStatus = function() { 21 | console.log('INFO, Updated status'); 22 | }; 23 | this.UpdateInventory = function() { 24 | console.log('INFO, Updated inventory'); 25 | }; 26 | this.SendEmail = function() { 27 | console.log('INFO, Sent email'); 28 | }; 29 | this.UpdateReporting = function() { 30 | console.log('INFO, Updated reporting'); 31 | }; 32 | }; -------------------------------------------------------------------------------- /Publisher-Confirms/producer.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Producer Consumer.'); 2 | var order = require('../Shop/order'); 3 | var orderService = require('./orderService'); 4 | var connect = require('amqp').createConnection(); 5 | var orderId = 0; 6 | 7 | connect.on('ready', function() { 8 | var ex = connect.exchange('shop.exchange', {type: 'direct', confirm:true}); 9 | var q = connect.queue('shop.queue', {durable:true, autoDelete:false}); 10 | q.on('queueDeclareOk', function(args) { 11 | q.bind('shop.exchange', 'order.key'); 12 | q.on('queueBindOk', function() { 13 | console.log("Place your order"); 14 | setInterval(function(){ 15 | var newOrder = new order(++orderId); 16 | var service = new orderService(newOrder); 17 | service.ProcessOrder(); 18 | ex.publish('order.key', JSON.stringify(newOrder), {deliveryMode:2}, function(isError){ 19 | if (isError) 20 | console.log('ERROR, Order has not been acknowledged.'); 21 | }); 22 | }, 1000); 23 | }); 24 | }); 25 | }); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | - Understand best practices for RabbitMQ application development 2 | - Distribute time consuming tasks with work queues 3 | - Decouple your application with the publish subscribe pattern 4 | - Explore complex routing techniques 5 | - Reliable message delivery with acknowledgements, persistence and publisher confirms 6 | 7 | 8 | 9 | RabbitMQ is an open source message-broker that implements the Advanced Message Queuing Protocol (AMQP) standard. This book will enable you to take advantage of RabbitMQ to create scalable, message-based applications. 10 | 11 | In "Instant RabbitMQ Messaging Application Development How-to" you start by understanding the reasons for using an AMQP message broker; you will then implement a simple messaging application. 12 | 13 | You will then be guided through the process of decoupling an existing highly-coupled e-commerce application using messaging patterns and look at RabbitMQ options for reliable message delivery. You’ll finish your journey by exploring more advanced routing patterns. This book takes a highly practical approach we will offer numerous hints and tips for successful application development along the way. 14 | 15 | Filled with practical, step-by-step instructions and clear explanations for the most important and useful tasks. Written in a practical, concise style, this book is complete with hands-on examples and the right amount of theory to get you started developing messaging applications with RabbitMQ. 16 | 17 | Although the examples in this book are written in Node.js, a server side JavaScript platform for building fast scalable network applications no knowledge of RabbitMQ or Node.js is required. If you want to build scalable message based applications using RabbitMQ, then this book is for you! 18 | -------------------------------------------------------------------------------- /Shop/order.js: -------------------------------------------------------------------------------- 1 | module.exports = function order(orderId) { 2 | this.OrderId = orderId; 3 | this.Status = "Processing"; 4 | }; 5 | -------------------------------------------------------------------------------- /Shop/orderService.js: -------------------------------------------------------------------------------- 1 | module.exports = function OrderService(order) { 2 | this.Order = order; 3 | this.Checkout = function() { 4 | console.log("INFO, Placed order " + this.Order.OrderId); 5 | this.ProcessOrder(); 6 | }; 7 | this.ProcessOrder = function() { 8 | this.PaymentGateway(); 9 | this.UpdateStatus(); 10 | if (this.Status === 'OrderComplete') { 11 | this.UpdateInventory(); 12 | this.SendEmail(); 13 | this.UpdateReporting(); 14 | } 15 | console.log('INFO, Thank you for placing your order...'); 16 | }; 17 | this.PaymentGateway = function() { 18 | console.log('INFO, Made payment'); 19 | this.Status = "OrderComplete"; 20 | }; 21 | this.UpdateStatus = function() { 22 | console.log('INFO, Updated status'); 23 | }; 24 | this.UpdateInventory = function() { 25 | console.log('INFO, Updated inventory'); 26 | }; 27 | this.SendEmail = function() { 28 | console.log('INFO, Sent email'); 29 | }; 30 | this.UpdateReporting = function() { 31 | console.log('INFO, Updated reporting'); 32 | }; 33 | }; -------------------------------------------------------------------------------- /Shop/server.js: -------------------------------------------------------------------------------- 1 | var order = require('./order'); 2 | var orderService = require('./orderService'); 3 | var service = new orderService(new order(1)); 4 | service.Checkout(); -------------------------------------------------------------------------------- /Work-Queues/consumer.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Work Queues.'); 2 | var orderService = require('./orderService'); 3 | var connect = require('amqp').createConnection(); 4 | 5 | connect.on('ready', function() { 6 | var ex = connect.exchange('shop.exchange', {type: 'direct'}); 7 | var q = connect.queue('shop.queue'); 8 | q.on('queueDeclareOk', function(args) { 9 | q.bind('shop.exchange', 'order.key'); 10 | q.on('queueBindOk', function() { 11 | q.subscribe(function(message) { 12 | var service = new orderService(unescape(message.data)); 13 | service.ProcessOrder(); 14 | }); 15 | }); 16 | }); 17 | }); -------------------------------------------------------------------------------- /Work-Queues/orderService.js: -------------------------------------------------------------------------------- 1 | module.exports = function OrderService(order) { 2 | this.Order = order; 3 | this.Checkout = function() { 4 | console.log("INFO, Placed order " + this.Order.OrderId); 5 | }; 6 | this.ProcessOrder = function() { 7 | this.PaymentGateway(); 8 | this.UpdateStatus(); 9 | if (this.Status === 'OrderComplete') { 10 | this.UpdateInventory(); 11 | this.SendEmail(); 12 | this.UpdateReporting(); 13 | } 14 | console.log('INFO, Thank you for placing your order...'); 15 | }; 16 | this.PaymentGateway = function() { 17 | console.log('INFO, Made payment'); 18 | this.Status = "OrderComplete"; 19 | }; 20 | this.UpdateStatus = function() { 21 | console.log('INFO, Updated status'); 22 | }; 23 | this.UpdateInventory = function() { 24 | console.log('INFO, Updated inventory'); 25 | }; 26 | this.SendEmail = function() { 27 | console.log('INFO, Sent email'); 28 | }; 29 | this.UpdateReporting = function() { 30 | console.log('INFO, Updated reporting'); 31 | }; 32 | }; -------------------------------------------------------------------------------- /Work-Queues/producer.js: -------------------------------------------------------------------------------- 1 | require('../setup').Init('Work Queues.'); 2 | var order = require('../Shop/order'); 3 | var orderService = require('./orderService'); 4 | var connect = require('amqp').createConnection(); 5 | var orderId = 0; 6 | 7 | connect.on('ready', function() { 8 | var ex = connect.exchange('shop.exchange', {type: 'direct'}); 9 | var q = connect.queue('shop.queue'); 10 | q.on('queueDeclareOk', function(args) { 11 | q.bind('shop.exchange', 'order.key'); 12 | q.on('queueBindOk', function() { 13 | console.log("Place your order"); 14 | setInterval(function(){ 15 | var newOrder = new order(++orderId); 16 | var service = new orderService(newOrder); 17 | service.Checkout(); 18 | ex.publish('order.key', JSON.stringify(newOrder)); 19 | ex.close(); 20 | q.close(); 21 | }, 100); 22 | }); 23 | }); 24 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "packt-instant-rabbitmq" 3 | , "description": "Instant RabbitMQ Messaging Application Development How-to" 4 | , "version": "0.0.1" 5 | , "dependencies": { 6 | "amqp": ">= 0.1.5" 7 | } 8 | } -------------------------------------------------------------------------------- /setup.js: -------------------------------------------------------------------------------- 1 | module.exports.Init = function(example){ 2 | console.log(''); 3 | console.log(''); 4 | console.log('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'); 5 | console.log('- Instant RabbitMQ Messaging Application Development How-to. -'); 6 | console.log('- Packt Publishing. -'); 7 | console.log('- Author: Andrew Keig. -'); 8 | console.log('- ' + example +' -'); 9 | console.log('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'); 10 | console.log(''); 11 | 12 | console.log("+---+ +---+"); 13 | console.log("| | | |"); 14 | console.log("| | | |"); 15 | console.log("| | | |"); 16 | console.log("| +---+ +-------+"); 17 | console.log("| |"); 18 | console.log("| RabbitMQ +---+ |"); 19 | console.log("| | | |"); 20 | console.log("| +---+ |"); 21 | console.log("| |"); 22 | console.log("+-------------------+"); 23 | 24 | process.on('SIGINT', function() { 25 | process.exit(1); 26 | }); 27 | 28 | process.on('SIGTSTP', function() { 29 | process.exit(1); 30 | }); 31 | 32 | process.on('SIGTERM', function(){ 33 | process.exit(1); 34 | }); 35 | }; --------------------------------------------------------------------------------