Chilling concurrency with frozen middleware

Freezing the middleware can prevent thread safety issues in runtime. In a multi-threaded web-server, unprotected mutation of internal state will lead to undefined behavior.

Lets take an example of a counting the number of requests received on a webserver.

As the webserver receives the request it increments the counter.
In case of a single threaded server the value of the counter at the end of 5 request is 5.

But in case of multi threaded server like puma, the value of the counter will be 1 since all the  5 requests finish at the same time.

why did this happen ? Its because we didn’t ensure thread-safety.

Lets take a look at non thread safe code —

# Non Thread safe code
class Counter
def initialize
@counter = 0
end
def call(_env)
counter = @counter
sleep 1
counter += 1
@counter = counter
[200, { 'Content-Type' => 'text/html' }, ["#{@counter}"]]
end
end

Lets enhance ActionCable

I am sure that after the release of rails 5 some of you have tried to build a chat app or notifications app using actioncable. Lets learn how actioncable works with the help of following diagram.

actioncable-works

We have a rails server which accepts only http requests and an ActionCable server to accept WebSocket requests from browser. The ActionCable server subscribes to channels and broadcasts from channels with the help of redis.

Lets assume that we have deployed this solution to production and our users have started using our app. Now the number of users have started growing. We are having about 20K users using our chat / notification functionality. Is this scalable solution which we have built ? Well in my opinion ruby is not the technology which we should use for building scalable concurrent application. There are WebSocket servers built in other programming languages which have achieved success for scalability and concurrency. Those programming languages are Golang and Erlang.

screen-shot-2017-02-01-at-12-13-08-am

How about if we could make use of the WebSocket servers built in Golang or Erlang in our rails application to achieve scalability ? Yes we can do that with the help of Anycable gem.

screen-shot-2017-02-01-at-12-15-08-am

AnyCable is not a replacement over ActionCable but it is an enhancement over ActionCable. AnyCable is available at rubygems.org and github Let see how AnyCable works –

screen-shot-2017-02-01-at-12-16-55-am

As shown in the diagram we have a rails server which accepts http requests, WebSocket server which accepts WebSocket requests and an AnyCable server for our business logic. The AnyCable server performs the same functionality as ActionCable server with help of redis.

So we have learnt that we can build scalable concurrent applications in rails and AnyCable is not a replacement but an enhancement over ActionCable.

 

find vs exists in rails

When want want to find a record/document using our favorite ORM’s like ActiveRecord or Mongoid, we make use of the find method.

find()
In ActiveRecord, find returns the record if found else it returns nil

2.3.1 :005 > User.find_by(email: 'a@b.com')
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "a@b.com"], ["LIMIT", 1]]
=> #
2.3.1 :006 > User.find_by(email: 'b@b.com')
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "b@b.com"], ["LIMIT", 1]]
=> nil

In Mongoid, find returns a record if found else it raises Mongoid::Errors::DocumentNotFound


:003 > User.find_by(email: 'a@b.com')
=> #
:004 > User.find_by(email: 'b@b.com')
Mongoid::Errors::DocumentNotFound:
message:
Document not found for class User with attributes {:email=>"b@b.com"}.
summary:
When calling User.find_by with a hash of attributes, all attributes provided must match a document in the database or this error will be raised.
resolution:
Search for attributes that are in the database or set the Mongoid.raise_not_found_error configuration option to false, which will cause a nil to be returned instead of raising this error.

When you get this error, if you want the similar behavior of find as its in ActiveRecord i.e. find should return nil if document is not found `please do not set raise_not_found_error to false` in mongoid.yml, instead change your query.

exists?()

In ActiveRecord and Mongoid, exists? returns true if record/ document is found and returns false else wise.

ActiveRecord –

2.3.1 :007 > User.exists?(email: 'b@b.com')
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "b@b.com"], ["LIMIT", 1]]
=> false
2.3.1 :008 > User.exists?(email: 'a@b.com')
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "a@b.com"], ["LIMIT", 1]]
=> true

Mongoid –


:002 > User.where(email: 'a@b.com').exists?
=> true
:003 > User.where(email: 'b@b.com').exists?
=> false

In Mongoid when we want to check if the document exist with the given conditions and we do not want to our query to raise Mongoid::Errors::DocumentNotFound we should use exists?() method, which returns true if document found and returns false else wise.

Set your priorities straight with rails 5 activejob

Priotities!!! All of us set priorities everyday to complete important tasks. There is proverb by Mahatma Gandhi

actionexpresses

it means that people take action on the things most important to them.

We need priorities to complete the important things first.

In rails 5 there is new module QueuePriority which has been added in the rails 5 beta 1 release.

So how do we set our priorities in rails 5 ActiveJob

In the job class add

queue_with_priority 1

1 is to set the high priority for the job object of the Job class

Now when we call the Job in the controller, irrespective of the Job which gets added to the queue first it will get executed on the basis of the priority set in the job class

class BooksController < ApplicationController
def index
ResizeJob.perform_later(Book.first)
DownloadJob.perform_later(Book.first)
UploadJob.perform_later(Book.first)
@books = Book.all
end
end

priority3

In rails log we get the priority set on the job object.

I have made use of delayed_job_activerecord in this example.

delayed_job_work

Following is the list of queue adapters with how do they prioritize

job_table.jpeg

Priorities :

The order in which jobs are processed can be configured differently depending on the adapter.

Job: Any class inheriting from the adapter may set the priority on the job object relative to other jobs.

Queue: The adapter can set the priority for job queues, when setting a queue with Active Job this will be respected.

Yes: Allows the priority to be set on the job object, at the queue level or as default configuration option.

No: Does not allow the priority of jobs to be configured.

N/A: The adapter does not support queuing, and therefore sorting them.

Beautilful global models

2.1.5 :004 > person = Individual.find(1)
=> #<Individual id: 1, name: “Mark”, created_at: “2015-05-09 03:51:50”, updated_at: “2015-05-09 03:51:50”>
2.1.5 :005 > company = Company.find(1)
=> #<Company id: 1, name: “Facebook”, created_at: “2015-05-09 03:51:49”, updated_at: “2015-05-09 03:51:49”>
2.1.5 :006 > person.id == company.id
=> true

In the above example the id of the two different model instance’s are equal.

How about we want our model instances to be uniquely identified?

We can do it with global_id gem.

Installing postgres 9.5 on Ubuntu 14 with pg gem for rails

Postgres has released the latest version of postgresql i.e. 9.5 on 07-01-2016 with major enhancements (http://www.postgresql.org/docs/9.5/static/release-9-5.html)  Lets learn how to install it.

Installation: Ubuntu’s default repository contain Postgres packages so we can install them without a hassle using the apt packaging system.

Apt stores a list of repositories or software channels in the file

/etc/apt/sources.list

and in any file with the suffix .list under the directory

/etc/apt/sources.list.d/

We will create postgresql.list file under sources.list.d directory

postgres1

Add the following to the file postgresql.list

postgres2

wget, which is network downloader can be used to get the key file with extension .asc for ubuntu installation. Files that contain the .asc file extension are script files that have been written in the ActionScript programming language.

postgres3

To turn off wget’s output we make use of the flag –quiet or -q. Flag -o is used to log all messages to logfile. | is a pipelinewhich takes the output of a command and runs it through another.

apt-key add adds a key

So it basically downloads the key and then adds it in one command.

To test whether it added the key or not use :

aptkeypostgres

Now update the sources with:

postgres4

and install postgresql 9.5

postgres5

postgres6

We now install pg gem for our rails application

postgres7

What is lib-pq ?

is this a Pure Go Postgres driver for database/sql https://github.com/lib/pq ?

No.

libpq is the C application programmer’s interface to PostgreSQL. libpq is a set of library functions that allow client programs to pass queries to the PostgreSQL backend server and to receive the results of these queries.

We need to install libpq-dev library so that pg gem can pass queries to PostgreSQL server and also receive these queries.

libpq_pg

Its done. We have successfully installed Postgresql 9.5 and now we can query postgresql and from rails application.

 

Rails 5 Application

Hello everyone. Rails 5 beta has been released. Lets learn. Rails 5 has not yet been released. But we can start learning to build a rails 5 application by cloning the rails repository and installing with bundle install. I have installed ruby 2.3.0.

rails51.jpeg

Create a rails 5 application by executing the following command :

bundle exec railties/exe/rails new ~/projects/sample_rails_5

rails52

Add ruby ‘2.3.0’ to your Gemfile.

 

rails53

From rails 5 your application will by default start with puma web server.

rails54.jpeg

Starting from Rails 5, all models will inherit from ApplicationRecord

post2

Rails : Learning Heroku App Deployment

Lets learn to deploy a sample rails application using Heroku.

  1. Create a heroku account
  2. Create a new rails app- ‘rails new sample’
  3. Install heroku on your machine(Ubuntu -wget -O- https://toolbelt.heroku.com/install-ubuntu.sh | sh)
  4. Enter command – ‘heroku login’
  5. Enter the credentials
  6. Do a ‘git init’ in your repository.
  7. heroku create – This command will create a heroku app and add the link to git remote. We can view the remote url with the help of ‘git remote -v ‘git_remote
  8. Heroku supports postgres, hence add “gem ‘pg’ ” in your gem file, instead of the default sqlite3.
  9. Add an index page for your app, set the route and commit your changes and push them to git.
  10. Do a ‘git push heroku master’ to publish your application.

Program to check if a number is an armstrong number.

A positive integer is called an Armstrong number if the sum of cubes of individual digit is equal to that number itself. For example:

153 = 1*1*1 + 5*5*5 + 3*3*3 // 153 is an Armstrong number.
12 is not equal to 1*1*1+2*2*2 // 12 is not an Armstrong number.

Go program :
package main

import “fmt”

func main() {
var a int
var num int
fmt.Println(“Program to find if the number is an armstrong number.\nEnter a number:”)
fmt.Scanf(“%d”, &a)
n := a //storing the value of a in another variable
for {
if n != 0 {
rem := n % 10 //rem is for the remainder. % is used for modulus of a number. It returns the last digit
num += rem * rem * rem //multiplying the remainder thrice and then adding
n = n / 10 //reduce n to 2 digits
} else {
break
}
}
if num == a {
fmt.Println(“It is an armstong number”)
} else {
fmt.Println(“It is not an armstrong number”)
}
}

Output :

prince@prince-Aspire-V3-571:~/files/goprog$ go run checkarmstrong.go
Program to find if the number is an armstrong number.
Enter a number:
153
It is an armstong number
prince@prince-Aspire-V3-571:~/files/goprog$ go run checkarmstrong.go
Program to find if the number is an armstrong number.
Enter a number:
12
It is not an armstrong number

Set PATH variable permanently

I had to set the PATH variable every time I opened up a new terminal. We should do the following:

$ sudo -s 

(-s is superuser)

$ vim ~/.bashrc

This will open up the .bashrc file. Go to the end of the file. Type i to edit and paste the path 

eg : export PATH=”$PATH:$HOME/.rvm/bin”

Press Esc key. Type :wq to save the changes made and its done. Now we have permanently saved the environment variable.