Tuesday 12 July 2011

jQuery's .html() and Internet Explorer 8

Sometimes it's easy to blame IE for unwanted behaviour. This case is a bit different, in the sense that I think IE's behaviour is understandable, or even correct. I was trying to fix a bug where the contents of an overlay screen would not load in IE8. The contents were fetched using an ajax GET request, after which this piece of code would be executed:

show: function(html) {
  var box = $("#dialog_box");  
  box.html(html);
  box.show();
}

In Firefox or Chrome, this works fine. I verified that the show method was actually called with the html from the GET request. The box.show() call was executed correctly, but somehow the box.html(html) was not. But the method didn't fail either.

After much fiddling around, I've found out that:

Internet Explorer will only insert a HTML string using jQuery's .html() method if every tag in the HTML string is opened and closed properly.

The response from the GET request wasn't valid, it contained one closing div tag too many. IE then refuses to insert the HTML into the DOM. Other browsers seem to have no problem inserting the invalid HTML. So IE8 is correct? Remarkable.

Friday 8 July 2011

Redis and Phusion Passenger: reconnect on fork

We're nearly ready for a new Coconut production release. Of course, this is the moment when bugs start coming in from the beta stage that are difficult to reproduce. One bug report stated: "sometimes, my widgets do not load". I couldn't reproduce this bug, but it was in the back of my mind the whole week. Suddenly, this afternoon, when I was clicking through a review build, the widgets didn't load. So I immediately pulled the log files and found this Redis error:

Got '1' as initial reply byte. If you're running in a multi-threaded environment, make sure you pass the :thread_safe option when initializing the connection. If you're in a forking environment, such as Unicorn, you need to connect to Redis after forking.

After some research, I've found out that the error was caused by the combination of using Redis and Phusion Passenger. We use Redis as a chained backend store for i18n (see Railscast 256 for  our inspiration), so we can have custom translations for each Coconut instance. Which is a very cool feature, because every customer has his own domain language and we can tweak the translation messages accordingly.

As the error states, Phusion Passenger is a "forking environment" like Unicorn. Phusion Passenger spawns new worker processes when it thinks more processes are needed, it uses what they call a "smart spawning method". Basically, it forks a new thread to increase capacity to handle requests. Normally, the newly created thread will try to use the same Redis connection, which causes problems. What you need to do, is create a new connection when the current process is forked.This is done by creating a new Rails initializer and adding some code for handling Phusion Passenger fork events.

Adding a new Rails initializer is simple: just add an .rb file to config/initializers. Our initializer looks like this:

if defined?(PhusionPassenger)
  PhusionPassenger.on_event(:starting_worker_process) do |forked|
    if forked
      # We're in smart spawning mode. If we're not, we do not need to do anything
      Rails.cache.reset
      I18nRedisBackend.connect
    end
  end
end

You might recognize the Rails.cache.reset from Dalli, which has the same issue if used with Phusion Passenger. The I18nRedisBackend.connect creates a new connection with Redis, like this (note: this code was simplified, to make it more readable):

module I18nRedisBackend
  @@default_i18n_backend = I18n.backend

  def self.connect
    redis = Redis.new
    I18n.backend = I18n::Backend::Chain.new(I18n::Backend::KeyValue.new(redis), @@default_i18n_backend)
  end 
end

To summarize, when Phusion Passenger forks a process to create a new worker thread, it automatically creates a new Redis connection. Problem solved!

thanx to the Phusion Passenger users guide, Appendix C which provided me with the correct code example

Ruby on Rails 3: chaining scopes with lambda's

Today we ran into a really strange bug: the bugreport stated that a blog post was shown in the blog list approximately 15 minutes after creation. Which is really weird, because we've dealt with time zone misery before, but that always applies to hours, not a quarter of an hour. After analysis, we've found out that a chained scope caused the trouble (note: the scopes were simplified for better readability):

class Blog::Post
  scope :published_posts, lambda { where("publication_time < ?", DateTime.now) }
  scope :published_non_rotator_posts, published_posts.where("rotator_position IS NULL")
end
Scopes are evaluated at the moment you call them. The published_posts scope uses a lambda to ensure that DateTime.now is evaluated on each call, instead of being evaluated to the same DateTime value for every call. For the published_non_rotator_posts it's the same. This scope is also evaluated on the first call. Since it doesn't use a lambda expression, the outcome of the chained published_posts scope will have the same value on every next call! The correct code is:
class Blog::Post
  scope :published_posts, lambda { where("publication_time < ?", DateTime.now) }
  scope :published_non_rotator_posts, lambda { published_posts.where("rotator_position IS NULL") }
end
So: when chaining a lambda scope you must also wrap it with a lambda! thanx to this slash dot dash article.

Friday 1 July 2011

Software has a new quality standard: ISO 25010

You might have missed the news that the ISO 9126 quality standard has been replaced recently by the ISO 25010 quality standard. Since the ISO/IEC wants at least 110 euro's for a PDF containing the new standard (WTF????), I thought I'd summarize the new standard and compare it to the old one.

The 'old' ISO 9126 model described six main characteristics, with a set of subcharacteristics:
  1. Functionality - A set of attributes that bear on the existence of a set of functions and their specified properties. The functions are those that satisfy stated or implied needs.
    • Suitability
    • Accuracy
    • Interoperability
    • Security
    • Functionality Compliance
  2. Reliability - A set of attributes that bear on the capability of software to maintain its level of performance under stated conditions for a stated period of time.
    • Maturity
    • Fault Tolerance
    • Recoverability
    • Reliability Compliance
  3. Usability - A set of attributes that bear on the effort needed for use, and on the individual assessment of such use, by a stated or implied set of users.
    • Understandability
    • Learnability
    • Operability
    • Attractiveness
    • Usability Compliance
  4. Efficiency - A set of attributes that bear on the relationship between the level of performance of the software and the amount of resources used, under stated conditions.
    • Time Behaviour
    • Resource Utilisation
    • Efficiency Compliance
  5. Maintainability - A set of attributes that bear on the effort needed to make specified modifications.
    • Analyzability
    • Changeability
    • Stability
    • Testability
    • Maintainability Compliance
  6. Maintainability - A set of attributes that bear on the effort needed to make specified modifications.
    • Analyzability
    • Changeability
    • Stability
    • Testability
    • Maintainability Compliance
  7. Portability - A set of attributes that bear on the ability of software to be transferred from one environment to another.
    • Adaptability
    • Installability
    • Co-Existence
    • Replaceability
    • Portability Compliance
    The new model has eight characteristics, instead of six, which are quite similar to the old model:

    1. Functional suitability - The degree to which the product provides functions that meet stated and implied needs when the product is used under specified conditions
      • Suitability
      • Accuracy
      • Interoperability
      • Security
      • Compliance
    2. Reliability - The degree to which a system or component performs specified functions under specified conditions for a specified period of time.
      • Maturity
      • Fault Tolerance
      • Recoverability
      • Compliance
    3. Operability - The degree to which the product has attributes that enable it to be understood, learned, used and attractive to the user, when used under specified conditions
      • Appropriateness
      • Recognisability
      • Ease of use
      • Learnability
      • Attractiveness
      • Technical accessibility
      • Compliance
    4. Performance efficiency - The performance relative to the amount of resources used under stated conditions
      • Time Behaviour
      • Resource Utilisation
      • Compliance
    5. Security - The degree of protection of information and data so that unauthorized persons or systems cannot read or modify them and authorized persons or systems are not denied access to them
      • Confidentiality
      • Integrity
      • Non-repudiation
      • Accountability
      • Authenticity
      • Compliance
    6. Compatibility - The degree to which two or more systems or components can exchange information and/or perform their required functions while sharing the same hardware or software environment
      • Replaceability
      • Co-existence
      • Interoperability
      • Compliance
    7. Maintainability - The degree of effectiveness and efficiency with which the product can be modified
      • Modularity
      • Reusability
      • Analyzability
      • Changeability
      • Modification stability
      • Testability
      • Compliance
    8. Transferability - The degree to which a system or component can be effectively and efficiently transferred from one hardware, software or other operational or usage environment to another
      • Portability
      • Adaptability
      • Installability
      • Compliance

      In the new model, security and compatibility were added as main characteristics. I've always wondered why security wasn't that important for software quality measurement, but now it is. Some subcharacterics were added to the model and a number of them were renamed to more accurate terms. The 25010 quality standard also works a bit different than the 9126 standard. The software product quality model describes the internal and external measures of software quality. Internal measures describe a set of static internal attributes that can be measured. The external measures focuses more on software as a black box and describes external attributes that can be measured.
      Besides the software product quality model, the 25010 standard also describes another model, the model of software quality in use:

      1. Effectiveness - The accuracy and completeness with which users achieve specified goals
        • Effectiveness
      2. Efficiency- The resources expended in relation to the accuracy and completeness with which users achieve goals
        • Efficiency
      3. Satisfaction- The degree to which users are satisfied with the experience of using a product in a specified context of use
        • Likability
        • Pleasure
        • Comfort
        • Trust
      4. Safety - The degree to which a product or system does not, under specified conditions, lead to a state in which human life, health, property, or the environment is endangered
        • Economic damage risk
        • Health and safety risk
        • Environmental harm risk
      5. Usability- The extent to which a product can be used by specified users to achieve specified goals with effectiveness, efficiency and satisfaction in a specified context of use
        • Learnability
        • Flexibility
        • Accessability
        • Context conformity
      I like the fact they've created a seperate model to emphasize how important quality in use is for a software product. Their motivation to do so might be different, they probably assume the characteristics in this model are "in the eye of the beholder" and thus harder to measure. And harder to agree on a common standard for these characteristics.

      To summon it up, the new model has a broader range and is more accurate. I believe this is an improvement to the old model, but why someone would pay more than 100 euro's to be able to study the new model is beyond me.