SlideShare a Scribd company logo
0 to App faster with NodeJS and Ruby
Rebecca Mills @RebccaMills
Patrick McFadin @PatrickMcFadin
The situation
• REST interface to Cassandra data
• Support CRUD operations
• It’s Friday and…
2
Umm yeah, and I’m going to
need that by Monday morning.
Choose your language
• Support for all Cassandra features
• Easy to work with
• Performant
3
Fast prototype
4
5
Need to get this done now
6
DataStax NodeJS driver
• Works with current OSS Cassandra
• Apache Licensed
7
https://github.com/datastax/nodejs-driver
Based on node-cassandra-cql
by Jorge Bay
Get it!
8
> npm install cassandra-driver
DataStax Ruby driver
9
https://github.com/datastax/ruby-driver
• Works with current OSS Cassandra
• Apache Licensed
Based on cql-rb
by Theo Hultberg (@iconara)
Get it!
10
> gem install cassandra-driver
DataStax Cassandra Drivers
• Load Balancing Policies
• Retry Policies
• Asynchronous
• Prepared statements
• Connection and cluster management
11
A Cassandra Driver should have…
On to the code!
• RESTful web server
• Need a few helpers
12
+ +
REST methods
• Operates on the “USERS” table in Cassandra
13
POST Insert a user
GET Select a user
PUT Update a user
DELETE Delete a user
CREATE TABLE users (
firstname text,
lastname text,
age int,
email text,
city text,
PRIMARY KEY (lastname)
);
14
Connection for NodeJS
• Express as the web server
• body-parser to get POST data
15
var client = new cassandra.Client({

contactPoints: ['127.0.0.1'],

keyspace: 'demo',

policies: {

retry: new cassandra.policies.retry.RetryPolicy(),

loadBalancing: new cassandra.policies.loadBalancing.DCAwareRoundRobinPolicy('datacenter1')

}

}

);
var express = require('express')

var bodyParser = require('body-parser');

var cassandra = require('cassandra-driver');
var client = new cassandra.Client({

contactPoints: ['127.0.0.1'],

keyspace: 'demo',

policies: {

retry: new cassandra.policies.retry.RetryPolicy(),

loadBalancing: new cassandra.policies.loadBalancing.DCAwareRoundRobinPolicy('datacenter1')

}

}

);
Connection for NodeJS
• Express as the web server
• body-parser to get POST data
16
var express = require('express')

var bodyParser = require('body-parser');

var cassandra = require('cassandra-driver');
var client = new cassandra.Client({

contactPoints: ['127.0.0.1'],

keyspace: 'demo',

policies: {

retry: new cassandra.policies.retry.RetryPolicy(),

loadBalancing: new cassandra.policies.loadBalancing.DCAwareRoundRobinPolicy('datacenter1')

}

}

);
Connection for NodeJS
• Express as the web server
• body-parser to get POST data
17
var express = require('express')

var bodyParser = require('body-parser');

var cassandra = require('cassandra-driver');
var client = new cassandra.Client({

contactPoints: ['127.0.0.1'],

keyspace: 'demo',

policies: {

retry: new cassandra.policies.retry.RetryPolicy(),

loadBalancing: new cassandra.policies.loadBalancing.DCAwareRoundRobinPolicy('datacenter1')

}

}

);
Connection for NodeJS
• Express as the web server
• body-parser to get POST data
18
var express = require('express')

var bodyParser = require('body-parser');

var cassandra = require('cassandra-driver');
Load balancing
19
Client 10.0.0.1
00-25
10.0.0.4
76-100
10.0.0.2
26-50
10.0.0.3
51-75
SELECT firstName
FROM users
WHERE lastname = ‘mills’;
datacenter1
datacenter1
Node Primary Replica Replica
10.0.0.1 00-25 76-100 51-75
10.0.0.2 26-50 00-25 76-100
10.0.0.3 51-75 26-50 00-25
10.0.0.4 76-100 51-75 26-50
loadBalancing: new DCAwareRoundRobinPolicy('datacenter1')
Insert a user with a POST
20
app.post('/users', function (req, res) {

var lastname = req.body.lastname;

var age = req.body.age;

var city = req.body.city;

var email = req.body.email;

var firstname = req.body.firstname;





var query = "INSERT INTO users (lastname, age, city, email, firstname) VALUES ( ?,?,?,?,?)";

var params = [lastname, age, city, email, firstname];



client.execute(query, params, {prepare: true}, function (err, result) {

if (!err) {

res.send("Inserted");

} else {

res.sendStatus(404)

}

})

})
Insert a user with a POST
21
app.post('/users', function (req, res) {

var lastname = req.body.lastname;

var age = req.body.age;

var city = req.body.city;

var email = req.body.email;

var firstname = req.body.firstname;





var query = "INSERT INTO users (lastname, age, city, email, firstname) VALUES ( ?,?,?,?,?)";

var params = [lastname, age, city, email, firstname];



client.execute(query, params, {prepare: true}, function (err, result) {

if (!err) {

res.send("Inserted");

} else {

res.sendStatus(404)

}

})

})
Insert a user with a POST
22
app.post('/users', function (req, res) {

var lastname = req.body.lastname;

var age = req.body.age;

var city = req.body.city;

var email = req.body.email;

var firstname = req.body.firstname;





var query = "INSERT INTO users (lastname, age, city, email, firstname) VALUES ( ?,?,?,?,?)";

var params = [lastname, age, city, email, firstname];



client.execute(query, params, {prepare: true}, function (err, result) {

if (!err) {

res.send("Inserted");

} else {

res.sendStatus(404)

}

})

})
Insert a user with a POST
23
app.post('/users', function (req, res) {

var lastname = req.body.lastname;

var age = req.body.age;

var city = req.body.city;

var email = req.body.email;

var firstname = req.body.firstname;





var query = "INSERT INTO users (lastname, age, city, email, firstname) VALUES ( ?,?,?,?,?)";

var params = [lastname, age, city, email, firstname];



client.execute(query, params, {prepare: true}, function (err, result) {

if (!err) {

res.send("Inserted");

} else {

res.sendStatus(404)

}

})

})
Select user with GET
24
app.get('/users/:lastname',function (req, res) {



var query = "SELECT lastname, age, city, email, firstname FROM users WHERE lastname= ?";

var params = [req.params.lastname];

client.execute(query, params, {prepare: true}, function (err, result) {

if (!err){

if ( result.rows.length > 0 ) {

var user = result.rows[0];

console.log("name = %s, age = %d", user.firstname, user.age);

res.send(user)

} else {

res.sendStatus(404);

}

}

});

})
Select user with GET
25
app.get('/users/:lastname',function (req, res) {



var query = "SELECT lastname, age, city, email, firstname FROM users WHERE lastname= ?";

var params = [req.params.lastname];

client.execute(query, params, {prepare: true}, function (err, result) {

if (!err){

if ( result.rows.length > 0 ) {

var user = result.rows[0];

console.log("name = %s, age = %d", user.firstname, user.age);

res.send(user)

} else {

res.sendStatus(404);

}

}

});

})
Select user with GET
26
app.get('/users/:lastname',function (req, res) {



var query = "SELECT lastname, age, city, email, firstname FROM users WHERE lastname= ?";

var params = [req.params.lastname];

client.execute(query, params, {prepare: true}, function (err, result) {

if (!err){

if ( result.rows.length > 0 ) {

var user = result.rows[0];

console.log("name = %s, age = %d", user.firstname, user.age);

res.send(user)

} else {

res.sendStatus(404);

}

}

});

})
Select user with GET
27
app.get('/users/:lastname',function (req, res) {



var query = "SELECT lastname, age, city, email, firstname FROM users WHERE lastname= ?";

var params = [req.params.lastname];

client.execute(query, params, {prepare: true}, function (err, result) {

if (!err){

if ( result.rows.length > 0 ) {

var user = result.rows[0];

console.log("name = %s, age = %d", user.firstname, user.age);

res.send(user)

} else {

res.sendStatus(404);

}

}

});

})
Select user with GET
28
app.get('/users/:lastname',function (req, res) {



var query = "SELECT lastname, age, city, email, firstname FROM users WHERE lastname= ?";

var params = [req.params.lastname];

client.execute(query, params, {prepare: true}, function (err, result) {

if (!err){

if ( result.rows.length > 0 ) {

var user = result.rows[0];

console.log("name = %s, age = %d", user.firstname, user.age);

res.send(user)

} else {

res.sendStatus(404);

}

}

});

})
Update a user with PUT
29
app.put('/users/:lastname', function (req, res) {

var age = req.body.age;



console.log("lastname = " + req.params.lastname + ", age= " + age);



var query = "UPDATE users SET age = ? WHERE lastname = ?";

var params = [age, req.params.lastname];



client.execute(query, params, {prepare: true}, function (err, result) {

if (!err) {

res.send("Updated");

} else {

res.sendStatus(404)

}

});

})
Remove a user with DELETE
30
app.delete('/users/:lastname', function (req, res) {

var query = "DELETE FROM users WHERE lastname = ?";

var params = [req.params.lastname];



client.execute(query, params, {prepare: true}, function (err, result) {



if (!err) {

res.send("Deleted");

} else {

res.sendStatus(404)

}

});

})
31
Connection with Ruby
• Sinatra as the web server
• JSON for returning formatted results
32
cluster = Cassandra.cluster(

:hosts => ['127.0.01'],

:load_balancing_policy => Cassandra::LoadBalancing::Policies::RoundRobin.new,

:retry_policy => Cassandra::Retry::Policies::Default.new,

logger: log)



keyspace = 'demo'

session = cluster.connect(keyspace)
require 'sinatra'

require 'JSON'

require 'cassandra'

require 'logger'
Connection with Ruby
• Sinatra as the web server
• JSON for returning formatted results
33
cluster = Cassandra.cluster(

:hosts => ['127.0.01'],

:load_balancing_policy => Cassandra::LoadBalancing::Policies::RoundRobin.new,

:retry_policy => Cassandra::Retry::Policies::Default.new,

logger: log)



keyspace = 'demo'

session = cluster.connect(keyspace)
require 'sinatra'

require 'JSON'

require 'cassandra'

require 'logger'
Connection with Ruby
• Sinatra as the web server
• JSON for returning formatted results
34
cluster = Cassandra.cluster(

:hosts => ['127.0.01'],

:load_balancing_policy => Cassandra::LoadBalancing::Policies::RoundRobin.new,

:retry_policy => Cassandra::Retry::Policies::Default.new,

logger: log)



keyspace = 'demo'

session = cluster.connect(keyspace)
require 'sinatra'

require 'JSON'

require 'cassandra'

require 'logger'
Retry Policies
• Retry requests on server errors
• Write Timeout
• Read Timeout
• Unavailable
35
Connection with Ruby
• Sinatra as the web server
• JSON for returning formatted results
36
cluster = Cassandra.cluster(

:hosts => ['127.0.01'],

:load_balancing_policy => Cassandra::LoadBalancing::Policies::RoundRobin.new,

:retry_policy => Cassandra::Retry::Policies::Default.new,

logger: log)



keyspace = 'demo'

session = cluster.connect(keyspace)
require 'sinatra'

require 'JSON'

require 'cassandra'

require 'logger'
Insert a user with a POST
37
post '/users' do



begin

session.execute(userInsertStatement, :arguments => [params[:firstname], params[:lastname],
params[:age].to_i, params[:city], params[:email]])



"Inserted"



rescue Exception => e

log.error 'Error in insert a user'

log.error(e)

halt(404)

end



end
userInsertStatement = session.prepare("INSERT INTO users (firstname, lastname, age, city, email)
VALUES (?,?,?,?,?)")
Insert a user with a POST
38
post '/users' do



begin

session.execute(userInsertStatement, :arguments => [params[:firstname], params[:lastname],
params[:age].to_i, params[:city], params[:email]])



"Inserted"



rescue Exception => e

log.error 'Error in insert a user'

log.error(e)

halt(404)

end



end
userInsertStatement = session.prepare("INSERT INTO users (firstname, lastname, age, city, email)
VALUES (?,?,?,?,?)")
…
Insert a user with a POST
39
post '/users' do



begin

session.execute(userInsertStatement, :arguments => [params[:firstname], params[:lastname],
params[:age].to_i, params[:city], params[:email]])



"Inserted"



rescue Exception => e

log.error 'Error in insert a user'

log.error(e)

halt(404)

end



end
userInsertStatement = session.prepare("INSERT INTO users (firstname, lastname, age, city, email)
VALUES (?,?,?,?,?)")
…
Select user with GET
40
get '/users/:lastname' do



begin

result = session.execute(userSelectStatement, :arguments => [params[:lastname]])



if result.size < 1

halt(404)

end



result.first.to_json

rescue Exception => e

log.error 'Error in select a user'

log.error(e)

halt(404)

end



end
userSelectStatement = session.prepare("SELECT firstname,lastname, age, email, city
FROM users where lastname = ?")
Select user with GET
41
get '/users/:lastname' do



begin

result = session.execute(userSelectStatement, :arguments => [params[:lastname]])



if result.size < 1

halt(404)

end



result.first.to_json

rescue Exception => e

log.error 'Error in select a user'

log.error(e)

halt(404)

end



end
userSelectStatement = session.prepare("SELECT firstname,lastname, age, email, city
FROM users where lastname = ?")…
Select user with GET
42
get '/users/:lastname' do



begin

result = session.execute(userSelectStatement, :arguments => [params[:lastname]])



if result.size < 1

halt(404)

end



result.first.to_json

rescue Exception => e

log.error 'Error in select a user'

log.error(e)

halt(404)

end



end
userSelectStatement = session.prepare("SELECT firstname,lastname, age, email, city
FROM users where lastname = ?")
…
Select user with GET
43
get '/users/:lastname' do



begin

result = session.execute(userSelectStatement, :arguments => [params[:lastname]])



if result.size < 1

halt(404)

end



result.first.to_json

rescue Exception => e

log.error 'Error in select a user'

log.error(e)

halt(404)

end



end
userSelectStatement = session.prepare("SELECT firstname,lastname, age, email, city
FROM users where lastname = ?")
…
Quick note on Async
• Generates a Future
• Non-blocking until get
44
future = session.execute_async(statement)



# register success listener

future.on_success do |rows|

rows.each do |row|

puts "#{row["artist"]}: #{row["title"]} / #{row["album"]}"

end

end
Quick note on Async
• Generates a Future
• Non-blocking until get
45
future = session.execute_async(statement)



# register success listener

future.on_success do |rows|

rows.each do |row|

puts "#{row["artist"]}: #{row["title"]} / #{row["album"]}"

end

end
Quick note on Async
• Generates a Future
• Non-blocking until get
46
future = session.execute_async(statement)



# register success listener

future.on_success do |rows|

rows.each do |row|

puts "#{row["artist"]}: #{row["title"]} / #{row["album"]}"

end

end
Update a user with PUT
47
put '/users' do



begin

session.execute(userUpdateStatement, :arguments => [params[:age].to_i, params[:lastname]])



"Updated"



rescue Exception => e

log.error 'Error in update a user'

log.error(e)

halt(404)

end



end
userUpdateStatement = session.prepare("UPDATE users SET age = ? WHERE lastname = ?")
Remove a user with DELETE
48
delete '/users/:lastname' do



begin

session.execute(userDeleteStatement, :arguments => [params[:lastname]])



"Deleted"



rescue Exception => e

log.error 'Error in delete a user'

log.error(e)

halt(404)

end



end
userDeleteStatement = session.prepare("DELETE FROM users WHERE lastname = ?")
Made it!
49
Nice code.
Have a beer.
Get the code! Try yourself!
50
https://github.com/beccam/rest_server_ruby
https://github.com/beccam/rest_server_nodejs
NodeJS Code
Ruby Code
Questions?
Don’t forget to follow us on Twitter for more:
@RebccaMills
@PatrickMcFadin

More Related Content

What's hot

From Node to Go
From Node to GoFrom Node to Go
From Node to Go
John Maxwell
 
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
Codemotion
 
Cassandra Community Webinar | In Case of Emergency Break Glass
Cassandra Community Webinar | In Case of Emergency Break GlassCassandra Community Webinar | In Case of Emergency Break Glass
Cassandra Community Webinar | In Case of Emergency Break Glass
DataStax
 
LinkRest at JeeConf 2017
LinkRest at JeeConf 2017LinkRest at JeeConf 2017
LinkRest at JeeConf 2017
Andrus Adamchik
 
Cassandra 2.1
Cassandra 2.1Cassandra 2.1
Cassandra 2.1jbellis
 
Cassandra 2.0 better, faster, stronger
Cassandra 2.0   better, faster, strongerCassandra 2.0   better, faster, stronger
Cassandra 2.0 better, faster, stronger
Patrick McFadin
 
Kick Your Database to the Curb
Kick Your Database to the CurbKick Your Database to the Curb
Kick Your Database to the Curb
Bill Bejeck
 
Cassandra EU - Data model on fire
Cassandra EU - Data model on fireCassandra EU - Data model on fire
Cassandra EU - Data model on fire
Patrick McFadin
 
Observability with Consul Connect
Observability with Consul ConnectObservability with Consul Connect
Observability with Consul Connect
Bram Vogelaar
 
Tokyo cassandra conference 2014
Tokyo cassandra conference 2014Tokyo cassandra conference 2014
Tokyo cassandra conference 2014jbellis
 
Cassandra Summit 2013 Keynote
Cassandra Summit 2013 KeynoteCassandra Summit 2013 Keynote
Cassandra Summit 2013 Keynotejbellis
 
Cassandra 3.0 - JSON at scale - StampedeCon 2015
Cassandra 3.0 - JSON at scale - StampedeCon 2015Cassandra 3.0 - JSON at scale - StampedeCon 2015
Cassandra 3.0 - JSON at scale - StampedeCon 2015
StampedeCon
 
CQL3 in depth
CQL3 in depthCQL3 in depth
CQL3 in depth
Yuki Morishita
 
Cassandra 2.2 & 3.0
Cassandra 2.2 & 3.0Cassandra 2.2 & 3.0
Cassandra 2.2 & 3.0
Victor Coustenoble
 
Integrate Solr with real-time stream processing applications
Integrate Solr with real-time stream processing applicationsIntegrate Solr with real-time stream processing applications
Integrate Solr with real-time stream processing applications
lucenerevolution
 
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
Codemotion
 
MySQL under the siege
MySQL under the siegeMySQL under the siege
MySQL under the siege
Source Ministry
 
Time series databases
Time series databasesTime series databases
Time series databases
Source Ministry
 
Advanced Apache Cassandra Operations with JMX
Advanced Apache Cassandra Operations with JMXAdvanced Apache Cassandra Operations with JMX
Advanced Apache Cassandra Operations with JMX
zznate
 
PostgreSQL High-Availability and Geographic Locality using consul
PostgreSQL High-Availability and Geographic Locality using consulPostgreSQL High-Availability and Geographic Locality using consul
PostgreSQL High-Availability and Geographic Locality using consul
Sean Chittenden
 

What's hot (20)

From Node to Go
From Node to GoFrom Node to Go
From Node to Go
 
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
 
Cassandra Community Webinar | In Case of Emergency Break Glass
Cassandra Community Webinar | In Case of Emergency Break GlassCassandra Community Webinar | In Case of Emergency Break Glass
Cassandra Community Webinar | In Case of Emergency Break Glass
 
LinkRest at JeeConf 2017
LinkRest at JeeConf 2017LinkRest at JeeConf 2017
LinkRest at JeeConf 2017
 
Cassandra 2.1
Cassandra 2.1Cassandra 2.1
Cassandra 2.1
 
Cassandra 2.0 better, faster, stronger
Cassandra 2.0   better, faster, strongerCassandra 2.0   better, faster, stronger
Cassandra 2.0 better, faster, stronger
 
Kick Your Database to the Curb
Kick Your Database to the CurbKick Your Database to the Curb
Kick Your Database to the Curb
 
Cassandra EU - Data model on fire
Cassandra EU - Data model on fireCassandra EU - Data model on fire
Cassandra EU - Data model on fire
 
Observability with Consul Connect
Observability with Consul ConnectObservability with Consul Connect
Observability with Consul Connect
 
Tokyo cassandra conference 2014
Tokyo cassandra conference 2014Tokyo cassandra conference 2014
Tokyo cassandra conference 2014
 
Cassandra Summit 2013 Keynote
Cassandra Summit 2013 KeynoteCassandra Summit 2013 Keynote
Cassandra Summit 2013 Keynote
 
Cassandra 3.0 - JSON at scale - StampedeCon 2015
Cassandra 3.0 - JSON at scale - StampedeCon 2015Cassandra 3.0 - JSON at scale - StampedeCon 2015
Cassandra 3.0 - JSON at scale - StampedeCon 2015
 
CQL3 in depth
CQL3 in depthCQL3 in depth
CQL3 in depth
 
Cassandra 2.2 & 3.0
Cassandra 2.2 & 3.0Cassandra 2.2 & 3.0
Cassandra 2.2 & 3.0
 
Integrate Solr with real-time stream processing applications
Integrate Solr with real-time stream processing applicationsIntegrate Solr with real-time stream processing applications
Integrate Solr with real-time stream processing applications
 
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
Going fullstack React(ive) - Paulo Lopes - Codemotion Amsterdam 2017
 
MySQL under the siege
MySQL under the siegeMySQL under the siege
MySQL under the siege
 
Time series databases
Time series databasesTime series databases
Time series databases
 
Advanced Apache Cassandra Operations with JMX
Advanced Apache Cassandra Operations with JMXAdvanced Apache Cassandra Operations with JMX
Advanced Apache Cassandra Operations with JMX
 
PostgreSQL High-Availability and Geographic Locality using consul
PostgreSQL High-Availability and Geographic Locality using consulPostgreSQL High-Availability and Geographic Locality using consul
PostgreSQL High-Availability and Geographic Locality using consul
 

Similar to 0 to App faster with NodeJS and Ruby

DataStax: 0 to App faster with Ruby and NodeJS
DataStax: 0 to App faster with Ruby and NodeJSDataStax: 0 to App faster with Ruby and NodeJS
DataStax: 0 to App faster with Ruby and NodeJS
DataStax Academy
 
Developing web-apps like it's 2013
Developing web-apps like it's 2013Developing web-apps like it's 2013
Developing web-apps like it's 2013
Laurent_VB
 
Express JS
Express JSExpress JS
Express JS
Alok Guha
 
RESTful API In Node Js using Express
RESTful API In Node Js using Express RESTful API In Node Js using Express
RESTful API In Node Js using Express
Jeetendra singh
 
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
NoSQLmatters
 
NoSQL meets Microservices
NoSQL meets MicroservicesNoSQL meets Microservices
NoSQL meets Microservices
ArangoDB Database
 
NoSQL meets Microservices - Michael Hackstein
NoSQL meets Microservices - Michael HacksteinNoSQL meets Microservices - Michael Hackstein
NoSQL meets Microservices - Michael Hackstein
distributed matters
 
Unit Testing Express and Koa Middleware in ES2015
Unit Testing Express and Koa Middleware in ES2015Unit Testing Express and Koa Middleware in ES2015
Unit Testing Express and Koa Middleware in ES2015
Morris Singer
 
Writing RESTful web services using Node.js
Writing RESTful web services using Node.jsWriting RESTful web services using Node.js
Writing RESTful web services using Node.js
FDConf
 
FwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsFwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.js
Timur Shemsedinov
 
GraphQL Bangkok Meetup 2.0
GraphQL Bangkok Meetup 2.0GraphQL Bangkok Meetup 2.0
GraphQL Bangkok Meetup 2.0
Tobias Meixner
 
Building Web Apps with Express
Building Web Apps with ExpressBuilding Web Apps with Express
Building Web Apps with Express
Aaron Stannard
 
node.js and the AR.Drone: building a real-time dashboard using socket.io
node.js and the AR.Drone: building a real-time dashboard using socket.ionode.js and the AR.Drone: building a real-time dashboard using socket.io
node.js and the AR.Drone: building a real-time dashboard using socket.io
Steven Beeckman
 
Building your first Node app with Connect & Express
Building your first Node app with Connect & ExpressBuilding your first Node app with Connect & Express
Building your first Node app with Connect & Express
Christian Joudrey
 
Reduxing like a pro
Reduxing like a proReduxing like a pro
Reduxing like a pro
Boris Dinkevich
 
Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019
Joe Keeley
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
Francois Zaninotto
 
Intro to Ember.JS 2016
Intro to Ember.JS 2016Intro to Ember.JS 2016
Intro to Ember.JS 2016
Sandino Núñez
 
Node js introduction
Node js introductionNode js introduction
Node js introductionAlex Su
 
Microservices using Node.js and RabbitMQ
Microservices using Node.js and RabbitMQMicroservices using Node.js and RabbitMQ
Microservices using Node.js and RabbitMQ
Carolina Pascale Campos
 

Similar to 0 to App faster with NodeJS and Ruby (20)

DataStax: 0 to App faster with Ruby and NodeJS
DataStax: 0 to App faster with Ruby and NodeJSDataStax: 0 to App faster with Ruby and NodeJS
DataStax: 0 to App faster with Ruby and NodeJS
 
Developing web-apps like it's 2013
Developing web-apps like it's 2013Developing web-apps like it's 2013
Developing web-apps like it's 2013
 
Express JS
Express JSExpress JS
Express JS
 
RESTful API In Node Js using Express
RESTful API In Node Js using Express RESTful API In Node Js using Express
RESTful API In Node Js using Express
 
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
Michael Hackstein - NoSQL meets Microservices - NoSQL matters Dublin 2015
 
NoSQL meets Microservices
NoSQL meets MicroservicesNoSQL meets Microservices
NoSQL meets Microservices
 
NoSQL meets Microservices - Michael Hackstein
NoSQL meets Microservices - Michael HacksteinNoSQL meets Microservices - Michael Hackstein
NoSQL meets Microservices - Michael Hackstein
 
Unit Testing Express and Koa Middleware in ES2015
Unit Testing Express and Koa Middleware in ES2015Unit Testing Express and Koa Middleware in ES2015
Unit Testing Express and Koa Middleware in ES2015
 
Writing RESTful web services using Node.js
Writing RESTful web services using Node.jsWriting RESTful web services using Node.js
Writing RESTful web services using Node.js
 
FwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsFwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.js
 
GraphQL Bangkok Meetup 2.0
GraphQL Bangkok Meetup 2.0GraphQL Bangkok Meetup 2.0
GraphQL Bangkok Meetup 2.0
 
Building Web Apps with Express
Building Web Apps with ExpressBuilding Web Apps with Express
Building Web Apps with Express
 
node.js and the AR.Drone: building a real-time dashboard using socket.io
node.js and the AR.Drone: building a real-time dashboard using socket.ionode.js and the AR.Drone: building a real-time dashboard using socket.io
node.js and the AR.Drone: building a real-time dashboard using socket.io
 
Building your first Node app with Connect & Express
Building your first Node app with Connect & ExpressBuilding your first Node app with Connect & Express
Building your first Node app with Connect & Express
 
Reduxing like a pro
Reduxing like a proReduxing like a pro
Reduxing like a pro
 
Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
Intro to Ember.JS 2016
Intro to Ember.JS 2016Intro to Ember.JS 2016
Intro to Ember.JS 2016
 
Node js introduction
Node js introductionNode js introduction
Node js introduction
 
Microservices using Node.js and RabbitMQ
Microservices using Node.js and RabbitMQMicroservices using Node.js and RabbitMQ
Microservices using Node.js and RabbitMQ
 

Recently uploaded

20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
Matthew Sinclair
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Aggregage
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
Alex Pruden
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
DianaGray10
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
danishmna97
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
Quotidiano Piemontese
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
Kari Kakkonen
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
SOFTTECHHUB
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
KAMESHS29
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptxSecstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
nkrafacyberclub
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
Pierluigi Pugliese
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
Mind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AIMind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AI
Kumud Singh
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 

Recently uploaded (20)

20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptxSecstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
Mind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AIMind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AI
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 

0 to App faster with NodeJS and Ruby

  • 1. 0 to App faster with NodeJS and Ruby Rebecca Mills @RebccaMills Patrick McFadin @PatrickMcFadin
  • 2. The situation • REST interface to Cassandra data • Support CRUD operations • It’s Friday and… 2 Umm yeah, and I’m going to need that by Monday morning.
  • 3. Choose your language • Support for all Cassandra features • Easy to work with • Performant 3
  • 5. 5
  • 6. Need to get this done now 6
  • 7. DataStax NodeJS driver • Works with current OSS Cassandra • Apache Licensed 7 https://github.com/datastax/nodejs-driver Based on node-cassandra-cql by Jorge Bay
  • 8. Get it! 8 > npm install cassandra-driver
  • 9. DataStax Ruby driver 9 https://github.com/datastax/ruby-driver • Works with current OSS Cassandra • Apache Licensed Based on cql-rb by Theo Hultberg (@iconara)
  • 10. Get it! 10 > gem install cassandra-driver
  • 11. DataStax Cassandra Drivers • Load Balancing Policies • Retry Policies • Asynchronous • Prepared statements • Connection and cluster management 11 A Cassandra Driver should have…
  • 12. On to the code! • RESTful web server • Need a few helpers 12 + +
  • 13. REST methods • Operates on the “USERS” table in Cassandra 13 POST Insert a user GET Select a user PUT Update a user DELETE Delete a user CREATE TABLE users ( firstname text, lastname text, age int, email text, city text, PRIMARY KEY (lastname) );
  • 14. 14
  • 15. Connection for NodeJS • Express as the web server • body-parser to get POST data 15 var client = new cassandra.Client({
 contactPoints: ['127.0.0.1'],
 keyspace: 'demo',
 policies: {
 retry: new cassandra.policies.retry.RetryPolicy(),
 loadBalancing: new cassandra.policies.loadBalancing.DCAwareRoundRobinPolicy('datacenter1')
 }
 }
 ); var express = require('express')
 var bodyParser = require('body-parser');
 var cassandra = require('cassandra-driver');
  • 16. var client = new cassandra.Client({
 contactPoints: ['127.0.0.1'],
 keyspace: 'demo',
 policies: {
 retry: new cassandra.policies.retry.RetryPolicy(),
 loadBalancing: new cassandra.policies.loadBalancing.DCAwareRoundRobinPolicy('datacenter1')
 }
 }
 ); Connection for NodeJS • Express as the web server • body-parser to get POST data 16 var express = require('express')
 var bodyParser = require('body-parser');
 var cassandra = require('cassandra-driver');
  • 17. var client = new cassandra.Client({
 contactPoints: ['127.0.0.1'],
 keyspace: 'demo',
 policies: {
 retry: new cassandra.policies.retry.RetryPolicy(),
 loadBalancing: new cassandra.policies.loadBalancing.DCAwareRoundRobinPolicy('datacenter1')
 }
 }
 ); Connection for NodeJS • Express as the web server • body-parser to get POST data 17 var express = require('express')
 var bodyParser = require('body-parser');
 var cassandra = require('cassandra-driver');
  • 18. var client = new cassandra.Client({
 contactPoints: ['127.0.0.1'],
 keyspace: 'demo',
 policies: {
 retry: new cassandra.policies.retry.RetryPolicy(),
 loadBalancing: new cassandra.policies.loadBalancing.DCAwareRoundRobinPolicy('datacenter1')
 }
 }
 ); Connection for NodeJS • Express as the web server • body-parser to get POST data 18 var express = require('express')
 var bodyParser = require('body-parser');
 var cassandra = require('cassandra-driver');
  • 19. Load balancing 19 Client 10.0.0.1 00-25 10.0.0.4 76-100 10.0.0.2 26-50 10.0.0.3 51-75 SELECT firstName FROM users WHERE lastname = ‘mills’; datacenter1 datacenter1 Node Primary Replica Replica 10.0.0.1 00-25 76-100 51-75 10.0.0.2 26-50 00-25 76-100 10.0.0.3 51-75 26-50 00-25 10.0.0.4 76-100 51-75 26-50 loadBalancing: new DCAwareRoundRobinPolicy('datacenter1')
  • 20. Insert a user with a POST 20 app.post('/users', function (req, res) {
 var lastname = req.body.lastname;
 var age = req.body.age;
 var city = req.body.city;
 var email = req.body.email;
 var firstname = req.body.firstname;
 
 
 var query = "INSERT INTO users (lastname, age, city, email, firstname) VALUES ( ?,?,?,?,?)";
 var params = [lastname, age, city, email, firstname];
 
 client.execute(query, params, {prepare: true}, function (err, result) {
 if (!err) {
 res.send("Inserted");
 } else {
 res.sendStatus(404)
 }
 })
 })
  • 21. Insert a user with a POST 21 app.post('/users', function (req, res) {
 var lastname = req.body.lastname;
 var age = req.body.age;
 var city = req.body.city;
 var email = req.body.email;
 var firstname = req.body.firstname;
 
 
 var query = "INSERT INTO users (lastname, age, city, email, firstname) VALUES ( ?,?,?,?,?)";
 var params = [lastname, age, city, email, firstname];
 
 client.execute(query, params, {prepare: true}, function (err, result) {
 if (!err) {
 res.send("Inserted");
 } else {
 res.sendStatus(404)
 }
 })
 })
  • 22. Insert a user with a POST 22 app.post('/users', function (req, res) {
 var lastname = req.body.lastname;
 var age = req.body.age;
 var city = req.body.city;
 var email = req.body.email;
 var firstname = req.body.firstname;
 
 
 var query = "INSERT INTO users (lastname, age, city, email, firstname) VALUES ( ?,?,?,?,?)";
 var params = [lastname, age, city, email, firstname];
 
 client.execute(query, params, {prepare: true}, function (err, result) {
 if (!err) {
 res.send("Inserted");
 } else {
 res.sendStatus(404)
 }
 })
 })
  • 23. Insert a user with a POST 23 app.post('/users', function (req, res) {
 var lastname = req.body.lastname;
 var age = req.body.age;
 var city = req.body.city;
 var email = req.body.email;
 var firstname = req.body.firstname;
 
 
 var query = "INSERT INTO users (lastname, age, city, email, firstname) VALUES ( ?,?,?,?,?)";
 var params = [lastname, age, city, email, firstname];
 
 client.execute(query, params, {prepare: true}, function (err, result) {
 if (!err) {
 res.send("Inserted");
 } else {
 res.sendStatus(404)
 }
 })
 })
  • 24. Select user with GET 24 app.get('/users/:lastname',function (req, res) {
 
 var query = "SELECT lastname, age, city, email, firstname FROM users WHERE lastname= ?";
 var params = [req.params.lastname];
 client.execute(query, params, {prepare: true}, function (err, result) {
 if (!err){
 if ( result.rows.length > 0 ) {
 var user = result.rows[0];
 console.log("name = %s, age = %d", user.firstname, user.age);
 res.send(user)
 } else {
 res.sendStatus(404);
 }
 }
 });
 })
  • 25. Select user with GET 25 app.get('/users/:lastname',function (req, res) {
 
 var query = "SELECT lastname, age, city, email, firstname FROM users WHERE lastname= ?";
 var params = [req.params.lastname];
 client.execute(query, params, {prepare: true}, function (err, result) {
 if (!err){
 if ( result.rows.length > 0 ) {
 var user = result.rows[0];
 console.log("name = %s, age = %d", user.firstname, user.age);
 res.send(user)
 } else {
 res.sendStatus(404);
 }
 }
 });
 })
  • 26. Select user with GET 26 app.get('/users/:lastname',function (req, res) {
 
 var query = "SELECT lastname, age, city, email, firstname FROM users WHERE lastname= ?";
 var params = [req.params.lastname];
 client.execute(query, params, {prepare: true}, function (err, result) {
 if (!err){
 if ( result.rows.length > 0 ) {
 var user = result.rows[0];
 console.log("name = %s, age = %d", user.firstname, user.age);
 res.send(user)
 } else {
 res.sendStatus(404);
 }
 }
 });
 })
  • 27. Select user with GET 27 app.get('/users/:lastname',function (req, res) {
 
 var query = "SELECT lastname, age, city, email, firstname FROM users WHERE lastname= ?";
 var params = [req.params.lastname];
 client.execute(query, params, {prepare: true}, function (err, result) {
 if (!err){
 if ( result.rows.length > 0 ) {
 var user = result.rows[0];
 console.log("name = %s, age = %d", user.firstname, user.age);
 res.send(user)
 } else {
 res.sendStatus(404);
 }
 }
 });
 })
  • 28. Select user with GET 28 app.get('/users/:lastname',function (req, res) {
 
 var query = "SELECT lastname, age, city, email, firstname FROM users WHERE lastname= ?";
 var params = [req.params.lastname];
 client.execute(query, params, {prepare: true}, function (err, result) {
 if (!err){
 if ( result.rows.length > 0 ) {
 var user = result.rows[0];
 console.log("name = %s, age = %d", user.firstname, user.age);
 res.send(user)
 } else {
 res.sendStatus(404);
 }
 }
 });
 })
  • 29. Update a user with PUT 29 app.put('/users/:lastname', function (req, res) {
 var age = req.body.age;
 
 console.log("lastname = " + req.params.lastname + ", age= " + age);
 
 var query = "UPDATE users SET age = ? WHERE lastname = ?";
 var params = [age, req.params.lastname];
 
 client.execute(query, params, {prepare: true}, function (err, result) {
 if (!err) {
 res.send("Updated");
 } else {
 res.sendStatus(404)
 }
 });
 })
  • 30. Remove a user with DELETE 30 app.delete('/users/:lastname', function (req, res) {
 var query = "DELETE FROM users WHERE lastname = ?";
 var params = [req.params.lastname];
 
 client.execute(query, params, {prepare: true}, function (err, result) {
 
 if (!err) {
 res.send("Deleted");
 } else {
 res.sendStatus(404)
 }
 });
 })
  • 31. 31
  • 32. Connection with Ruby • Sinatra as the web server • JSON for returning formatted results 32 cluster = Cassandra.cluster(
 :hosts => ['127.0.01'],
 :load_balancing_policy => Cassandra::LoadBalancing::Policies::RoundRobin.new,
 :retry_policy => Cassandra::Retry::Policies::Default.new,
 logger: log)
 
 keyspace = 'demo'
 session = cluster.connect(keyspace) require 'sinatra'
 require 'JSON'
 require 'cassandra'
 require 'logger'
  • 33. Connection with Ruby • Sinatra as the web server • JSON for returning formatted results 33 cluster = Cassandra.cluster(
 :hosts => ['127.0.01'],
 :load_balancing_policy => Cassandra::LoadBalancing::Policies::RoundRobin.new,
 :retry_policy => Cassandra::Retry::Policies::Default.new,
 logger: log)
 
 keyspace = 'demo'
 session = cluster.connect(keyspace) require 'sinatra'
 require 'JSON'
 require 'cassandra'
 require 'logger'
  • 34. Connection with Ruby • Sinatra as the web server • JSON for returning formatted results 34 cluster = Cassandra.cluster(
 :hosts => ['127.0.01'],
 :load_balancing_policy => Cassandra::LoadBalancing::Policies::RoundRobin.new,
 :retry_policy => Cassandra::Retry::Policies::Default.new,
 logger: log)
 
 keyspace = 'demo'
 session = cluster.connect(keyspace) require 'sinatra'
 require 'JSON'
 require 'cassandra'
 require 'logger'
  • 35. Retry Policies • Retry requests on server errors • Write Timeout • Read Timeout • Unavailable 35
  • 36. Connection with Ruby • Sinatra as the web server • JSON for returning formatted results 36 cluster = Cassandra.cluster(
 :hosts => ['127.0.01'],
 :load_balancing_policy => Cassandra::LoadBalancing::Policies::RoundRobin.new,
 :retry_policy => Cassandra::Retry::Policies::Default.new,
 logger: log)
 
 keyspace = 'demo'
 session = cluster.connect(keyspace) require 'sinatra'
 require 'JSON'
 require 'cassandra'
 require 'logger'
  • 37. Insert a user with a POST 37 post '/users' do
 
 begin
 session.execute(userInsertStatement, :arguments => [params[:firstname], params[:lastname], params[:age].to_i, params[:city], params[:email]])
 
 "Inserted"
 
 rescue Exception => e
 log.error 'Error in insert a user'
 log.error(e)
 halt(404)
 end
 
 end userInsertStatement = session.prepare("INSERT INTO users (firstname, lastname, age, city, email) VALUES (?,?,?,?,?)")
  • 38. Insert a user with a POST 38 post '/users' do
 
 begin
 session.execute(userInsertStatement, :arguments => [params[:firstname], params[:lastname], params[:age].to_i, params[:city], params[:email]])
 
 "Inserted"
 
 rescue Exception => e
 log.error 'Error in insert a user'
 log.error(e)
 halt(404)
 end
 
 end userInsertStatement = session.prepare("INSERT INTO users (firstname, lastname, age, city, email) VALUES (?,?,?,?,?)") …
  • 39. Insert a user with a POST 39 post '/users' do
 
 begin
 session.execute(userInsertStatement, :arguments => [params[:firstname], params[:lastname], params[:age].to_i, params[:city], params[:email]])
 
 "Inserted"
 
 rescue Exception => e
 log.error 'Error in insert a user'
 log.error(e)
 halt(404)
 end
 
 end userInsertStatement = session.prepare("INSERT INTO users (firstname, lastname, age, city, email) VALUES (?,?,?,?,?)") …
  • 40. Select user with GET 40 get '/users/:lastname' do
 
 begin
 result = session.execute(userSelectStatement, :arguments => [params[:lastname]])
 
 if result.size < 1
 halt(404)
 end
 
 result.first.to_json
 rescue Exception => e
 log.error 'Error in select a user'
 log.error(e)
 halt(404)
 end
 
 end userSelectStatement = session.prepare("SELECT firstname,lastname, age, email, city FROM users where lastname = ?")
  • 41. Select user with GET 41 get '/users/:lastname' do
 
 begin
 result = session.execute(userSelectStatement, :arguments => [params[:lastname]])
 
 if result.size < 1
 halt(404)
 end
 
 result.first.to_json
 rescue Exception => e
 log.error 'Error in select a user'
 log.error(e)
 halt(404)
 end
 
 end userSelectStatement = session.prepare("SELECT firstname,lastname, age, email, city FROM users where lastname = ?")…
  • 42. Select user with GET 42 get '/users/:lastname' do
 
 begin
 result = session.execute(userSelectStatement, :arguments => [params[:lastname]])
 
 if result.size < 1
 halt(404)
 end
 
 result.first.to_json
 rescue Exception => e
 log.error 'Error in select a user'
 log.error(e)
 halt(404)
 end
 
 end userSelectStatement = session.prepare("SELECT firstname,lastname, age, email, city FROM users where lastname = ?") …
  • 43. Select user with GET 43 get '/users/:lastname' do
 
 begin
 result = session.execute(userSelectStatement, :arguments => [params[:lastname]])
 
 if result.size < 1
 halt(404)
 end
 
 result.first.to_json
 rescue Exception => e
 log.error 'Error in select a user'
 log.error(e)
 halt(404)
 end
 
 end userSelectStatement = session.prepare("SELECT firstname,lastname, age, email, city FROM users where lastname = ?") …
  • 44. Quick note on Async • Generates a Future • Non-blocking until get 44 future = session.execute_async(statement)
 
 # register success listener
 future.on_success do |rows|
 rows.each do |row|
 puts "#{row["artist"]}: #{row["title"]} / #{row["album"]}"
 end
 end
  • 45. Quick note on Async • Generates a Future • Non-blocking until get 45 future = session.execute_async(statement)
 
 # register success listener
 future.on_success do |rows|
 rows.each do |row|
 puts "#{row["artist"]}: #{row["title"]} / #{row["album"]}"
 end
 end
  • 46. Quick note on Async • Generates a Future • Non-blocking until get 46 future = session.execute_async(statement)
 
 # register success listener
 future.on_success do |rows|
 rows.each do |row|
 puts "#{row["artist"]}: #{row["title"]} / #{row["album"]}"
 end
 end
  • 47. Update a user with PUT 47 put '/users' do
 
 begin
 session.execute(userUpdateStatement, :arguments => [params[:age].to_i, params[:lastname]])
 
 "Updated"
 
 rescue Exception => e
 log.error 'Error in update a user'
 log.error(e)
 halt(404)
 end
 
 end userUpdateStatement = session.prepare("UPDATE users SET age = ? WHERE lastname = ?")
  • 48. Remove a user with DELETE 48 delete '/users/:lastname' do
 
 begin
 session.execute(userDeleteStatement, :arguments => [params[:lastname]])
 
 "Deleted"
 
 rescue Exception => e
 log.error 'Error in delete a user'
 log.error(e)
 halt(404)
 end
 
 end userDeleteStatement = session.prepare("DELETE FROM users WHERE lastname = ?")
  • 50. Get the code! Try yourself! 50 https://github.com/beccam/rest_server_ruby https://github.com/beccam/rest_server_nodejs NodeJS Code Ruby Code
  • 51. Questions? Don’t forget to follow us on Twitter for more: @RebccaMills @PatrickMcFadin