Archive for September 2012

Bindings update that removes extra server round-trips

So, we noticed recently that our Java and Python bindings were doing an extra round-trip to our servers for every request. We’ve just done updates to each of them that removes this.

Per the HTTP spec, when a request uses HTTP BASIC authentication, as our API does, the client is supposed to first send a request without credentials. When it receives a 401 error, then it should retry with the credentials supplied and repeat that process for each and every request.

While that makes sense for interactive use from a browser, for use in a web services API, it makes much more sense to avoid the extra round-trip and send the credentials already in the first request, thus significantly speeding up request times.

You can get the updated versions of our bindings on Github.

Shopify app updates, new Ruby bindings beta, new web services features coming down the pipe

Shopify app updates

So, it’s been a gazillion years since we posted updates here, but there have been a number of things shaking out of the woodwork.

First, we just did the biggest update to our Shopify app since we first launched it a couple years back.  It features a new Bootstrap-ified configuration interface and a whole bunch of new recommendations types.

New Ruby Bindings in Beta

Whilst working on our Shopify app, which itself is a Rails app, we got frustrated with the current state of our Ruby bindings.

You see, our Ruby bindings were written back in the dark days before we actually used Ruby at all inside of the company.  Truth be told, the original version was written by yours truly a couple hours after I started learning Ruby.

These days, along with Java and C++ (which our lower-level, performance critical bits are written in), we write quite a bit of Ruby as as such, our tastes have become more refined.

Here are a couple of quick examples:

Old:

require 'rubygems'
require 'directed_edge'
 
DE_USER = ENV['DIRECTEDEDGE_TEST_DB']
DE_PASS = ENV['DIRECTEDEDGE_TEST_PASS']
 
# Import some data
 
DE_FILE = 'temp.xml'
 
exporter = DirectedEdge::Exporter.new(DE_FILE)
 
(1..10).each do |i|
  item = DirectedEdge::Item.new(exporter.database, "item_#{i}")
  item.add_tag('item')
  item.link_to("item_#{rand(10) + 1}")
  exporter.export(item)
end
 
exporter.finish
 
database = DirectedEdge::Database.new(DE_USER, DE_PASS)
database.import(DE_FILE)
 
# Get recommendations
 
item = DirectedEdge::Item.new(database, 'item_1')
item.related([ 'item' ]).each { |i| puts i }
 
# Update item
 
item.add_tag('foo')
item.save

New:

require 'rubygems'
require 'directededge'
 
DE_USER = ENV['DIRECTEDEDGE_TEST_DB']
DE_PASS = ENV['DIRECTEDEDGE_TEST_PASS']
 
database = DirectedEdge::Database.new(DE_USER, DE_PASS)
 
DirectedEdge::UpdateJob.run(database, :replace) do |update|
  (1..10).each do |i|
    update.item("item_#{i}") do |item|
      item.tags.add('item')
      item.links.add("item_#{rand(10) + 1}")
    end
  end
end
 
# Get recommendations
 
item = DirectedEdge::Item.new(database, 'item_1')
item.related(:tags => :item).each { |i| puts i }
 
# Update item
 
item.tags.add('foo')
item.save

The changes are most obvious in the importer above, but there are a lot of little subtle improvements in the API’s semantics.

If you’re up for beta testing the new bindings, drop us a line.  The documentation is sorely lacking at present (ahem, meaning non-existent), but that’s the main thing that we know of that’s missing at the moment:  the new bindings are already in use by our Shopify app and the code is up on Github.

Web services updates on the way

In a similar vein, we’ve got some stuff that we added to the web services for the Shopify app that still have some rough corners that we want to smooth out before pushing them out to the unwashed masses, but we’ll soon have explicit API support for tracking product view histories and showing recommendations based on them.  It’s been possible to do such in a hackey way in the past, but the new stuff adds some special math-fu for time-clustered recommendations and storing high-traffic queues of updates.  More on that soon.