Tuesday, September 17, 2013
In order to run your capybara test server under ssl, you will need to generate a self signed certificate.
You'll want to check the certificate and private key into your project. I added them to my spec/support directory.
Now that the certificate is all set, start capybara with ssl enabled using your certificates. Hint: If you are using rspec, the following snippets can be pasted into your spec_helper.rb.
Next tell capybara, to make requests using https:
Now you'll need to instruct your web driver to automatically accepted your self signed certificate even though you are running from localhost.
Finally, add the following monkey patch capybara to make http with ssl enabled:
I am not proud of the last step, and jnicklas indicated in this closed issue that this should not be needed, but not sure how else to get it done. Plan on following up with him and updating the post.
Tuesday, July 9, 2013
Long Running Web Requests
At View The Space, many of our pages deliver real time data over extended time periods. The database queries producing this data can take significant time to run and since the reporting is meant to be real time, caching is not an option. Our application servers consist of a bunch of single threaded unicorn processes sitting on top of Heroku. Tying up our web requests with long running heavy queries would be a bad idea as all other web requests would queue up causing bad performance for our entire app.
Push it in the Background with Sidekiq
Instead of performing long queries during the course of the rails web request, we push that heavy lifting to the background with Sidekiq. Sidekiq is a multi-threaded background job queueing library built on top of redis and by default each Sidekiq process leverages 25 threads. When a request is made to our building traffic dashboard, a simple html page is quickly rendered to the user followed by an ajax json request. That second ajax json request simply pushes a critical job onto a sidekiq queue:
That first job pushes another critical query job for each query to be performed for the dashboard. Since sidekiq is multi-threaded, each query should be performed in parallel.
Once the query is complete, the job pushes the result to the browser using Pusher and the pusher-gem. As a side note, Pusher is a service that makes using websockets easy and it supports all major browsers including Internet Explorer.
Pusher publishes the result to a unique user channel based on the user's database id and rails session id. The query result should be some simple raw data within a hash or an array that can easily be converted into json.
Rendering the Data within the Browser
Thursday, March 14, 2013
I had no way of deciding which one to pick. Yeah yeah, i could have done some research, but my existing redis instance was just flat out not working and parts of our app was down. I was in a hurry. In the end, like the seasoned engineer I am, I picked the one with the prettiest logo. My point is, why doesn't Heroku have some type of transparency within their add ons section? It should look like the itunes store. When choosing between heroku add-ons, I should be able to see how many other projects are using the add-on and some reviews would also be nice. Can anyone think of a reason why it doesn't work this way today?
Tuesday, March 12, 2013
At VTS we have lots of reports and charts that group data by the day. These reports should look different based on the user's configured timezone. I did not want to force all of our users to configure their timezone within our app when they already configured it within their operating system and hence their browser. The only problem... the browser does not pass the timezone to the server by default. You have to take care of it yourself.
The solution is pretty straight forward:
- Set each users timezone as a cookie
- Each request sets the Rails timezone to the value of that cookie
The above coffee script code uses jsTimezoneDetect to set the browsers timezone within a cookie that will live for the next 365 days. All that is left is setting the timezone during each request.
The above code would go into your ApplicationController. Simple around filter for each request that sets the timezone if it's present. Notice that it sets the Time.zone back to the original default timezone after each request and, yes, the Time.zone method is actually thread safe.
Slight CaveatThe timezone is set after each page request on document ready. That means the very first request will not have the cookie set for the server side around_filter and will not set the timezone. I have seen some people out there getting fancy with ajax redirects but this is probably a bit overkill for most use cases. I start to have nightmares involving infinite redirects.
Since I extracted all of the above into a Rails Engine, you can ignore all of my rambling and just install the browser-timezone-rails gem.
Tuesday, May 8, 2012
I am a nerd. This and my kids is what keeps me up at night. This post is about how I find a way to get to sleep without over-medicating.
This probably isn't that enlightening, but when an error happens in your app, you should probably know about it. Airbrake takes care of this for you in a smart way.
There are plenty of services out there that ping your site but what does that prove? Is your site doing what it's supposed to be doing? Still Alive is like Cucumber for your live app. Here's what we have running every minute:
Still not satisfied? This is what we have running every 15 minutes:
Notice this is actually shares stuff which sends emails, but are we sure our emails are actually being delivered?
Email Monitoring Job
Every 15 minutes we run a resque job that checks our test email account to see if it's received an email in the last 30 minutes.
If no recent email is found, it raises an error. That error gets picked up by airbrake since we have this within our resque initializer:
How did those emails get there you ask? Remember our Still Alive script sends email every 15 minutes during it's test run.
I'm getting alerts, what's going on?
I'm not going to pretend that 99% of you reading this post don't know about newrelic, but this is our go to tool to diagnose any kind of performance related issues. It also pings your website every minute which is a nice addition to stillalive. After all, if two alerting systems are reporting errors, it's a real sign that there is definitely an issue.
You have invalid ActiveRecord objects lurking in your database
Yes I am trying to scare you into reading this, but let's face it, you probably do. There are a bunch of ways it can happen.
- That cowboy sitting next to you saved a bunch of objects with validation turned off
- Code changes - new validations that haven't always been there
- Faulty logic in your code that let's invalid stuff through
So you be saying, is this a big deal? The answer in many cases is yes. Suppose you add some new code that validates a new presence of a new field on your user object but you forget to update all of your existing user profiles. If any page within your app updates a user object, your customers may be in for a 500 page.
This is where active_sanity come in which checks all of the objects in your database for validity. For each object that is invalid, it inserts an entry into an InvalidRecord table. Again, we have a resque job that runs active sanity once a night:
You're probably noticing a pattern here. If there are any invalid records, an error is raised, which fires off an airbrake alert. This alert has a link to the rails_admin page which shows a list of all invalid records:
It's important for your sanity and general well being to be the first one to know that your app isn't functioning properly. At View the Space, we are constantly trying to think of new ways to improve upon our monitoring. Let us know what you do? Drop us a comment.
Thursday, December 8, 2011
Instead of creating new properties, users, and contacts each time a space is created, by default all spaces share the same nested objects. Most often this is not at all a problem in any of our tests. If we do require spaces do not share the same property, we specify it the Given section of our test.
Tuesday, December 6, 2011
In order to get this working, we defined @selenium tag hooks within the features/support/custom.rb (could be any file in the support directory).
Before each @selenium scenario, change to selenium. After the scenario, we change back to the previous driver.