Requests that take more than 60s to complete fails – ElasticBeanstalk

This short post specifically targets:
– RoR as web development environment – Can be ignored as this is closely related to nginx configuration settings
Nginx as web server


While working with ElasticBeanstalk environments, one of my requirement was to send a heavy job to Worker App that takes > 1 min (60 seconds) to complete and I had no configuration in place. The way beanstalk-app was handling that job was disappointing. That job never finishes within a minute and another job (duplicate) gets triggered by the app and this goes on till it reaches the max retry count.

I tried googling the solution and found that we have to increase the timeout for the web server which is handling the request. In my case it was `nginx`.

So I decided to write a config file under `.ebextensions/02_nginx_proxy.config` — I am not going into the details of `ebextensions` here as this is out of scope of this article.

Here’s how my config file looks like:

files:
/etc/nginx/conf.d/proxy.conf:
mode: "000755"
owner: root
group: root
content: |
client_max_body_size 20M;
proxy_send_timeout 600;
proxy_read_timeout 1h;
send_timeout 600;
server_names_hash_bucket_size 128;
upstream backend {
server unix:///var/run/puma/my_app.sock;
}
map $uri $preferred_proto {
default "https";
~^/(assets|public|packs)/ "none";
~^/health_check "http";
}
server {
listen 80;
if ($preferred_proto = "http") {
set $http_x_forwarded_proto $preferred_proto;
}
if ($preferred_proto = "none") {
set $preferred_proto $http_x_forwarded_proto;
}
if ($preferred_proto != $http_x_forwarded_proto) {
rewrite ^(.*) $preferred_proto://$host$request_uri redirect;
}
location / {
proxy_pass http://backend;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-NginX-Proxy true;
location /packs {
root /var/app/current/public;
gzip_static on;
gzip on;
expires max;
add_header Cache-Control public;
}
}
location /assets {
alias /var/app/current/public/assets;
gzip_static on;
gzip on;
expires max;
add_header Cache-Control public;
}
location /public {
alias /var/app/current/public;
gzip_static on;
gzip on;
expires max;
add_header Cache-Control public;
}
}

view raw
nginx_proxy.config
hosted with ❤ by GitHub

Here if you focus on lines:
`proxy_send_timeout 600;`
`proxy_read_timeout 1h;`
`send_timeout 600;`

This will prevent sending multiple requests of same job type until the current one finishes in 1h.

If you need any inputs on what other lines are all about/doing, then leave your comment.

Happy Coding!

Learning RSPEC with Rails 4 (Alpha)

Hi Folks,

Hope you all are fine and doing good! I am sure most of you, are using TDD for years now. And, once we think of TDD, the first thing comes into our mind is, RSPEC. We all agree that Rspec is a great framework of Test-Driven-Development and its integration with other libraries (like fixtures etc.) is seamless.

With rapid revolution happening in Rails community, Rspec too has evolved over the years, and my motto is to bring this newly developed RSPEC framework in such a way so that, those who are eager to learn TDD can take tips and take this as a learning material. And those, who are planning to migrate can refer to this!

Environments I am using:

  • Ruby 2.1.2
  • Rails 4.2.1
  • Rspec 3.2.0

Idea is to share small code snippets while learning these changes, where we see: what is new. So let’s explore this now:

1. In Rspec 3, the support for ‘should‘ (e.g. foo.should == bar) is deprecated and is no longer supported. Instead of ‘should’, rspec encourages us to use ‘expect‘. Let’s see how it works:

require 'spec_helper'
class User
def initialize(args = {}); end
def email
'someone@example.com'
end
def mobile
12021679918
end
end
describe User do
describe "#initialize with old should way" do
it "should set the email and mobile for user" do
u = User.new email: 'someone@example.com', mobile: 12021679918
u.email.should == 'someone@example.com'
u.mobile.should == 12021679918
end
end
describe "#initialize with new expect way" do
it "expects email and mobile param for user" do
u = User.new email: 'someone@example.com', mobile: 12021679918
expect(u.email).to eq('someone@example.com')
expect(u.mobile).to eq(12021679918)
end
end
end

view raw
user_spec.rb
hosted with ❤ by GitHub

If you try running this example, you’ll get this deprecation warning message:

Deprecation Warnings:

Using `should` from rspec-expectations‘ old `:should` syntax without explicitly enabling the syntax is deprecated. Use the new `:expect` syntax or explicitly enable `:should` with `config.expect_with(:rspec) { |c| c.syntax = :should }` instead

 

Now, let’s take an example of controller spec. Create a controller with scaffold and write the spec as below:

# Controller /app/controllers/posts_controller.rb
def index
@posts = Post.all
end
# Spec /spec/controllers/posts_controller_spec.rb
describe "GET #index" do
it "responds successfully with a HTTP 200 status code" do
get :index
expect(response).to be_success
expect(response).to have_http_status(200)
end
it "should render index template" do
get :index
expect(response).to render_template('index')
end
end
# Controller /app/controllers/posts_controller.rb
def create
@post = Post.new post_params
respond_to do |format|
if @post.save
format.html { redirect_to @post }
else
format.html { render action: :new }
end
end
end
# Spec /spec/controllers/posts_controller_spec.rb
describe "POST #create" do
it "should create new post with valid params" do
post :create, post: { title: 'My First Post', description: 'My first post description' }
expect(Post.count).to eq(1)
end
it "redirects to show page once the post is created successfully" do
post :create, post: { title: 'My First Post', description: 'My first post description' }
expect(response).to redirect_to(Post.first)
end
it "does not allow to create post without title" do
post :create, post: { description: 'My first post description' }
expect(Post.count).to eq(0) # This make sure validates :title, presence: true in post.rb
end
it "renders new template if failed to create post" do
post :create, post: { description: 'My first post description' }
expect(response).to render_template('new')
end
end
# Controller /app/controllers/posts_controller.rb
def update
@post = Post.find params[:id]
respond_to do |format|
if @post.update_attributes(post_params)
format.html { redirect_to @post }
else
format.html { render action: :edit }
end
end
end
# Spec /spec/controllers/posts_controller_spec.rb
describe "PUT update/:id" do
before(:each) do
@post = FactoryGirl.create(:post)
end
it "should render edit template if unable to create post" do
@attr = { title: nil, description: 'My first post description' }
put :update, id: @post.id, post: @attr
expect(response).to render_template('edit')
end
it "redirects user on show post page" do
@attr = { title: 'My First Post', description: 'My first post description' }
put :update, id: @post.id, post: @attr
expect(response).to have_http_status(302)
expect(response).to redirect_to(@post)
end
it "validates the title and description of post after updation" do
@attr = { title: 'My 1st Post', description: 'My 1st post description updated' }
put :update, id: @post.id, post: @attr
@post.reload
expect(@post.title).to eql(@attr[:title])
expect(@post.description).to eql(@attr[:description])
end
end

view raw
controller_spec.rb
hosted with ❤ by GitHub

I’ll cover model, helper and view spec very soon.

Happy Coding 🙂