Archive for January, 2008

Socket output progress in AIR

Thursday, January 17th, 2008

Currently when using the flash.net.Socket api, there is no way to
determine that buffered data has been written to the socket. (The flush method is non-blocking and applies only to the actionscript socket buffer).

This is a follow-up to a previous post.

This issue does not arise when using the new File api (and writing to
files), since an event has been included in
flash.filesystem.FileStream: OutputProgressEvent.OUTPUT_PROGRESS

If this (or a similar) event could be added to the Socket api, it
would allow us to:

  • Send large amounts of data on a socket (without causing large memory
    usage as data buffers in memory).
  • Measure the current progress of data being sent on the socket.

We came upon this limitation from using our AS3 http client library, and trying to send large
files as part of a multipart upload. However this issue would arise
when sending any significant amounts of data on a socket. For example, an FTP or bittorrent client would be impossible.

This issue has been discussed in other places, but is probably more
pressing now with the AIR releases.

Update: Vote on this bug (FP-6)

require

Monday, January 14th, 2008

Here are some different ways to require stuff in ruby. The funny ones courtesy of why the lucky stiff.

require "rubygems"
require "open-uri"
require "yaml"
[ "rubygems", "open-uri", "yaml" ].each { |s| require s }
%w[rubygems open-uri yaml].map(&method(:require))

File.dirname(__FILE__)

What got me looking at require was how annoying it is to use the File.dirname(__FILE__) syntax all the time in init.rb’s, like:

require File.dirname(__FILE__) + "/parser/black_cat"
require File.dirname(__FILE__) + "/parser/dar"
require File.dirname(__FILE__) + "/parser/dc_nine"
require File.dirname(__FILE__) + "/parser/iota"
require File.dirname(__FILE__) + "/parser/jammin_java"

I am always just verbose with requires, I don’t know why. It gets even less readable if you start using File.join(...). I was poking around in the rails source to see how they do requires and they use $::

$:.unshift(File.dirname(__FILE__)) unless
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
 
require 'action_controller/base'
require 'action_controller/request'
require 'action_controller/rescue'
...

$:

What is $:?

irb(main):001:0> $:
=> ["/usr/local/lib/ruby/site_ruby/1.8", "/usr/local/lib/ruby/site_ruby/universal-darwin8.0", 
"/usr/local/lib/ruby/site_ruby/1.8/universal-darwin8.0", "/usr/local/lib/ruby/site_ruby", 
"/usr/local/lib/ruby/1.8", "/usr/local/lib/ruby/1.8/universal-darwin8.0", 
"/usr/local/lib/ruby/1.8/universal-darwin8.0", "."]

Its the load path. It turns out $LOAD_PATH is a synonym. So that would take me:

$LOAD_PATH.unshift(File.dirname(__FILE__))
 
require "parser/black_cat"
require "parser/dar"
require "parser/dc_nine"
require "parser/iota"
require "parser/jammin_java"

But is this a bad idea? What if the load path gets large? Do we care?

politweets

Thursday, January 10th, 2008

We built another twitter app, this time tracking candidates names. Its called politweets.

One #1 referrer today was from 100shiki. I’ve always been big in Japan.

Hopefully this one is a little more relevant than tracking curse words. But I still think the bitch balls‘er is awesome.

nginx conf with alternate cache dir

Monday, January 7th, 2008

Its a good idea to use an alternate cache directory in rails (in your environment.rb):

config.action_controller.page_cache_directory = RAILS_ROOT + "/public/cache/"

This makes it easier to sweep. To setup nginx to pick up from a rails alternate cache directory like public/cache, I used:

if ($http_user_agent ~* "(iPhone|iPod)") {
  rewrite ^/$ /iphone break;
  proxy_pass http://mongrel-pt;
  break;
}
 
if (-f $request_filename) {
  break;
}
 
if (-f $document_root/cache/$uri/index.html) {
  rewrite (.*) /cache/$1/index.html break;
}
 
if (-f $document_root/cache/$uri.html) {
  rewrite (.*) /cache/$1.html break;
}
 
if (-f $document_root/cache/$uri) {
  rewrite (.*) /cache/$1 break;
}
 
if (!-f $request_filename) {
  proxy_pass http://mongrel-pt;
  break;
}

It was a little tricky to figure out to use the $uri variable. The first rewrite is used for iphone requests so it doesn’t get the non-iphone cached page.

On duck typing and interfaces

Wednesday, January 2nd, 2008

I was looking at different type systems (apparently there are 4 dimensions) in different languages and ran across this use of duck typing in C# :

For example, the C#’s foreach operator already uses duck typing. This might be surprising to some, but to support foreach in C# you don’t need to implement IEnumerable! All you have to do is:



Provide a public method GetEnumerator that takes no parameters and returns a type that has two members: a) a method MoveMext that takes no parameters and return a Boolean, and b) a property Current with a getter that returns an Object.

Do you have multiple fine-grained interfaces (like IEnumerable and IEnumerator and ISupportsAdd) or a single interface with all the methods and maybe they throw UnsupportedOperationExceptions if they don’t actually support a particular call (like in a mutable versus immutable collection)?

The closer you get to more fine grained interfaces like ISupportsAdd<T> or Closeable, defining a contract for a single method Add(T obj) or Close is that you might as well just ask the class if it has that method (if it “quacks”) instead of whether it implemented a single method interface. Better yet, just assume it and let it throw an error at runtime. Whatever the compiler doesn’t give you, some decent test coverage will.

But what strikes me as particularly great is that foreach is obviously such a powerful thing to restrict to a single interface, and so they chose “Duck Notation”, because in this case it is worth it.

This reminded me of why I like ecma 4 (and its derivatives like actionscript). You have freedom to use static and dynamic typing at will.

If you check out my take on an AS3 HTTP client library, HttpRequest class and allowing the request body to be of any type:

public class HttpRequest {
 
  // Request method. For example, "GET"
  protected var _method:String;
 
  // Request header
  protected var _header:HttpHeader;
 
  // Request body
  protected var _body:*;
 
  /**
   * Create request.
   *  
   * The request body can be anything but should respond to:
   *  - readBytes(bytes:ByteArray, offset:uint, length:uint)
   *  - length
   *  - bytesAvailable
   *  - close
   *  
   * @param method HTTP Method, for example 'GET'
   * @param header HTTP request header (or null)
   * @param body HTTP request body (or null)
   *  
   */
  public function HttpRequest(method:String, header:HttpHeader = null, body:* = null) {
    _method = method;
    _header = header;      
    _body = body;
 
 ...

I think this is a good choice because:

  1. The IDataInput interface (that ByteArray already implements) doesn’t have a length property and we need to know the request body size (Content-Length) before we send.
  2. The IDataInput interface wants you to implement a ton of read methods, which would make it annoying to force people to implement.
  3. ByteArray has these methods and also implements the length property already. It quacks.
  4. If we created our own interface with these methods, we can’t add this interface retroactively to ByteArray.
  5. I wrote it. Heh.

The other option is to subclass ByteArray and have that implement the new interface, but it just seems awkward (in this case) having any empty subclass solely for the point of enforcing an interface.

Another place where this principle applied for me is in HttpSocket. We need to support both Socket (for http) and TLSSocket (for https). TLSSocket has all the same (mostly) methods as Socket (but does not extend Socket; yay for composition over inheritance). Creating a proxy to delegate to different socket implementations based on the http scheme is an option but to me wasn’t worth it. And using a design pattern to overcome the lack of an appropriate and existing interface just seems to make things worse.