203

HTTP code 203: Non-Authoritative Information

Rails: Shadow Facets of Concurrency

This is my talk at Rocky Mountain Ruby 2013. Slides are available here.

Rails is a framework well known for ease of development. This ease is achieved by a lot of ‘magic’ that happens behind the scenes. One of pitfalls of such magic is a false sense of safety it gives, including sense of safety from concurrency issues for single-threaded environments. You may never discover any problems before the launch, or even after, while your site traffic is pretty sparse. But here comes a glorious moment of popularity - and together with more traffic it brings more and more concurrency-related problems.

In this talk we will look at different aspects of concurrency, from simple ones that are even mentioned in Rails documentation, to more complex problems that even seasoned developers tend to miss or fail to pay sufficient attention to.

Videos to Watch

Good presentations, deserve watching:

  • Deconstructing the Framework by Gary Bernhardt
  • Agile is the new black by Fred George
  • Confident Code by Avdi Grimm
  • Delicious Controversy: Docs & Tests by Thomas Meeks
  • Boundaries by Gary Bernhardt

Numeric Fun

Today I was browsing Rails codebase (sometimes people do weird things for fun), and found an interesting piece of code:

https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/time/calculations.rb#L105
1
options[:days], partial_days = options[:days].divmod(1)

This sparkled my interest: what is divmod, especially - its pretty harsh form divmod(1)? Quick search through documentation - and it starts to make perfect sense: Returns an array containing the quotient and modulus obtained by dividing num by numeric; especially if you instantly remember what is quotient and modulus. Looks like example table in documentation is designed to confuse (including expected output of multiple methods), but for the special case of a positive float.divmod(1) there is much simpler explanation: it just splits a positive floating point number to its integer and fractional parts (+/- error).

Curious First

(first_last.rb) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ActiveRecord::Schema.define do
  drop_table :records if table_exists? :records
  create_table :records do |t|
    t.timestamps
  end
end

class Record < ActiveRecord::Base
end

class CuriousFirstTest < MiniTest::Unit::TestCase
  def test_first_last
    r = Record.create
    Record.create
    r.touch
    assert_equal 2, Record.count
    assert Record.first != Record.last, 'The first of 2 records is also the last!'
  end
end

What are we doing here? We create two records, touching first (this updates the record timestamps), and making sure that the first record is not the same as the last one. Perfectly valid assumption, that almost works.

The test succeeds on SQLite and MySQL (latter - with various engines), but fails on PostgreSQL.