sbt-git-stamp released

I finally published a simple sbt plugin: sbt-git-stamp, which I had written long ago, and every now and then, someone would find the code and ask about it.

This is a little project I created in 20% time at work, and it enables you to include some basic information about the state of the Git repository when the artifact was built, so you never have to wonder where an artifact came from. The information recorded is:

  • Head revision
  • Branch name
  • Whether or not there were uncommitted changes
  • Build date

This info is recorded in the MANIFEST.MF file, like so (the highlighted entries are from the plugin):

Manifest-Version: 1.0
Implementation-Vendor: My-Company
Implementation-Title: My Project
Implementation-Version: 0.1
Implementation-Vendor-Id: My-Company
Specification-Vendor: My-Company
Git-Repo-Is-Clean: false
Git-Branch: gitstamp
Specification-Title: My Company
Git-Build-Date: 2013-04-26T17:22:58.538-07:00
Specification-Version: 0.1
Git-Head-Rev: b0d5a67d59dc7c0133aecce2e2ceb18fc8d23597

Installation instructions and more are on Bitbucket.

Posted in computers | Tagged , | Leave a comment

Injecting connection information into Typesafe Slick at the last possible point

Often when designing a database-driven application, you will want flexibility as to which database you want to connect to. You will certainly want different databases for production, test, and development environments. You might even want different database engines for different environments. For example, you might use an H2 database in your local development environment, and Postgres in test and production. Or perhaps you are writing an application that will be used in many environments, and you need to support Postgres, MySQL, DB2, Oracle, etc. The usual answer to this problem is dependency injection, and while there are frameworks for this, in many cases, you can accomplish these goals using just the language features of Scala.

Most tutorials (that I have found, anyway) for using Typesafe Slick assume that you are picking one database engine and sticking with it. You need to import implicits specific to the driver you are using. You can easily specify different connection URIs at runtime, but you need to commit to a driver throughout your application.

Here, I will present an alternative that allows you to specify your driver in one place, and have various classes of your database interface code all agnostic to the particular driver you are using. There is no runtime switching of the driver, and (almost) everything is type checked at compile time.

Schema Definition

The Slick docs start with selecting a database driver before doing anything else:

// Use H2Driver to connect to an H2 database
import scala.slick.driver.H2Driver.simple._

But of course, we don’t want to do that. So, here is a schema definition class that only assumes that we will be using some kind of scala.slick.driver.JdbcDriver:

import slick.driver._
class Tables(val profile: JdbcProfile) {
  import profile.simple._
  def ddl: profile.SchemaDescription = names.ddl

  class PersonTable(tag: Tag) extends Table[(Long, String)](tag, "person") {
    def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
    def name = column[String]("name")
    def * = (id, name)
  val names = TableQuery[PersonTable]

Note that this gets the implicits from the JdbcProfile that is passed in. This allows us to pass in the profile when we know what it is, but we don’t have to worry about it here.

DAO layer

Next, lets add some DAO code that uses this new table:

class PersonDao(t: Tables) {
  import t.profile.simple._
  def makePerson(name: String)(implicit sess: Session): Long =
    (t.names returning += (-1, name)

Again, we just import the implicits needed for the Slick DSL from the profile that was given to the schema definition.

Finally, we bind the database driver

Up until now, we have been agnostic as to which database driver we use. At some point, though, you need to choose one. Here is a simple Main class that does that with a hardcoded value. You can imagine some logic that reads a config file, or some other mechanism to do this, though.

import slick.driver._

object Main extends App {
  import scala.slick.driver.H2Driver.simple._
  import slick.driver.H2Driver.profile
  val db = Database.forURL("jdbc:h2:db", driver="org.h2.Driver")
  db.withSession { implicit s => 
    val foo = new PersonDao(new Tables(profile))

Only lines 4-6 in the above snippet commit us to a specific database. They could be swapped out for a different driver, with a different profile, and a different connection string, and our schema definition and DAO code could remain unchanged.

While coming up with this, I did find one case where the compiler got confused, and I needed to cast something, though. This was while adding a function to recreate the DDL:

  db.withSession { implicit s => 
    val ddl: profile.SchemaDescription = new Tables(profile).ddl.asInstanceOf[profile.SchemaDescription]
    import profile.Implicit._

From looking at the code, you can tell that the Tables.ddl object should be of the type profile.SchemaDescription (for whatever type profile you are passing in), but the cast was necessary to make the compiler happy.

Caveats to this approach

  • You are stuck with the lowest common denominator. Some features may compile, but then fail at runtime if you use a feature that one driver doesn’t support. Likewise, if one driver presents a non-standard feature, you may not be able to use it.
  • Be sure to run your test suite (at least the part that exercises your db interface) against all drivers you intend to support. If your database functions prove to behave identically whether run on an H2 in-memory database or a real Postgres DB, you can then test the rest of your code (that just calls your db interface layer) against the H2 in-memory db, and possibly achieve faster test runs.
Posted in computers | Tagged , | Leave a comment

33 is the Magic Number…

Photo courtesy of Flickr user schoeband

On the No Agenda Show, there is the theory that the number ’33′ is inserted into news stories as code.  No one is sure what the code means, though.  In some contexts, it seems to mean that the rest of the news story is bogative, or maybe it means ‘mission accomplished’, or it is just a flag to alert people in-the-know to take heed.

In any case, I created a little site to track instances of such numbers in the news.  Introducing:

Subscribe to the feeds if you want to be kept abreast of any possible coded stories!

This was a fun little project to get more familiar with Heroku, Play 2.1, and Reactive Mongo.  I even worked a little bit of Shapeless HLists in there, for good measure.

Posted in Uncategorized | Leave a comment

FIBS: Functional interface for Interactive Brokers for Scala

Announcing a small side project I have been hacking on: a Scala wrapper library for the Interactive Brokers TWS API.  The TWS API uses a message-passing design, where you pass a message asking for a quote, for instance, and then you get a series of messages back, making up that quote.  It is up to you to keep track of which response messages are referring which quote request, and the whole thing involves a lot of mutable state.

I, however, wanted to write an application staying as functionally pure as possible, with little or no shared mutable state, which could process many quotes at once.  I wanted to do this using my favorite functional language du jour, Scala/scalaz.

So, I created FIBS, which is a terrible backronym that I am claiming stands for Functional interface for Interactive Brokers for Scala.  It is in its infancy, and currently only supports the following operations:

  • Realtime Stock Quotes
  • Historical Stock Quotes

There is much, much more in the API to flesh out.  One of the other things I don’t like in the TWS API is that it is up to you to know which parameters are appropriate for the request you are making.  (For example, only certain order parameters make sense for a given order type.)  So, I want to enforce this logic with the type system.  You, as the consumer fo my API, should never pass a null value because that parameter makes no sense in the context of what you are doing.  The type system should enforce this.

Instead of waiting for various pieces of information to return, you will get a Promise or a Stream, or some other monad to allow you to move forward with your code while IB is doing its thing.

So, I am making progress on the API slowly, as I need it for my application.  I wanted to make it public to see if anyone else was interested.  I could also use some domain expertise in knowing exactly what parameters are appropriate, when.  My experience as a quant is strictly amateur.

Check it out on Bitbucket!

Posted in computers | Tagged , , , , | Leave a comment

Building Inline Comments for Pull Requests and Commits

(or, what I did over summer vacation)

For the last few months, I have been working with the Bitbucket team at Atlassian.  I switched over to this team at the beginning of the summer to help build a new inline commenting feature on pull requests and commit pages, to help make the tool more useful for code reviews in a team.

It was a great project, and I wrote up a story of how we built inline comments for pull requests and commits over at the Bitbucket blog.  Check it out!

Posted in Uncategorized | Leave a comment

Proof that Netflix is the only thing holding the USPS afloat

"Netflix Only" chute at the post office

Posted in Uncategorized | Leave a comment

LivingSocial/Fiesta Americana Resort Bait & Switch Scam

UPDATE: I contacted LivingSocial about this issue, and they responded in a timely manner, and offered a partial refund, which I feels remedies the situation.  I am leaving this post up to tell the story, and to alert people that they should always be on guard for issues like this, but at least LivingSocial has made a good effort to rectify the situation.
My wife and I recently returned from a trip to Los Cabos, Mexico, where we stayed at the Fiesta Americana Grand Los Cabos Golf & Spa Resort.  We purchased the resort package through “Living Social Escapes” (archived as PDF in case Living Social removes the page).  As excellent of a time we had while enjoying the warm weather and the beautiful beach, some of the items included in the offer we felt were misleading and blatantly untrue.

Under one of the bullets in the “escape kit” it states: “Daily Continental Breakfast, Afternoon Cocktails, and Hors D’œuvres at the Grand Club and Free Upgrade to Grand Club Level for First 50 Vouchers Sold”.  This gives the impression that daily continental breakfast, afternoon cocktails and hors D’oeuvres are included in the package deal and that the first 50 vouchers sold will receive free upgrade to Grand Club Level.  After being denied the continental breakfast, we spoke to the front desk.  The front desk people read it as “all of the items in this statement are only for the first 50 people.  This is a very tricky and misleading statement. Furthermore, in the body of the webpage, it states

“You’ll know you’ve been good this year as you enjoy meet-and-greet services and private ground transportation from Los Cabos International Airport, private check-in and check-out service, daily continental breakfast, and a $600 resort experience credit.”

This states nothing about the “first 50 vochers sold”.  We probably would not have bought the package had we know that the continental breakfast was not included, and instead found a package that included the amenities we were looking for at the right price.

Under another bullet it states:  “In-Room Bottle of Wine and Canapés Daily”.  When we first arrived, there was a bottle of wine and a plate of canapés in our room waiting for us.  The reminder of the days, there was no wine or canapés.  When we asked the front desk about this, they told us that a bottle of wine was only supplied on the first day and that Living Social lied about that in their ad. One front desk woman even admitted that the statement was a bait and switch tactic.

Overall, we are very unimpressed with Living Social’s misleading tactics.  We would love to be able to take advantage of the wonderful offers they have available, however they have lost a lot of our trust.

Posted in Uncategorized | Tagged | Leave a comment