Rails 3 provides a lot of really neat functionality, and one of the pieces that looked coolest was Arel – ActiveRecord’s own relational algebra. Finally, we could get rid of SQL in queries and use a clear, syntactic DSL to manage our queries!
Well, in reality, that isn’t quite what happened. ActiveRecord’s Arel functionality does provide some neat criteria chaining methods, but unfortunately you either end of typing a lot of raw SQL:
Ruby 1.9 includes a lot of neat stuff, and one of the coolest things is the SecureRandom module.
SecureRandom presents a plethora of useful methods for creating random numbers and strings. You can check out the documentation for a full list, but some of the more personally useful methods I’ve found are:
I really like answering questions on Stack Overflow – it’s like a trivia game that you win by knowing Rails backwards and forwards, but instead of cheesy prizes you get awesome reputation points! And also little badges!
Recently I’ve been seeing a lot of beginner-style questions, and the most popular has definitely been some variant of “how do I mess with the primary key column?”
The answer is always, invariably, the same: don’t.
I’ve been giving a lot of thought recently to working around DynamoDB’s built-in limitations. Like most good web products (and I do believe DynamoDB is good), it uses a less is better approach: but in a database, less is surprising and can make it difficult for people to transition from their existing, fully-featured solutions to a cheaper, faster, but simpler product.
Nevertheless, I think you can still do a lot with DynamoDB, and I think the key is using tools targeted specifically towards its shortcomings: lack of indexing and transactional support. Today I’ll talk a little about overcoming the indexing problem, since I’m still noodling around the transaction issue.
When I was analyzing tools to deploy applications into Amazon’s elastic cloud, I settled on rubber as our EC2 provisioner of choice.
rubber has a lot going for it. It provides simple, close-to-the-metal server creation and bootstrapping; it’s super easy to start a server with nothing more than:
1
cap rubber:create ALIAS=fluttershy ROLES=unicorn
And bootstrap it with all the software needed for that role with:
1
cap rubber:bootstrap FILTER=fluttershy
Of course, looking at command line magic doesn’t tell you anything about how hard or easy it is to initially configure, but rubber is also pretty easy to figure out and get running. When you initially rubber-ize your project, you get an entire directory in config/ called rubber that contains all the configuration files, separated by role, that you can browse to figure out exactly what rubber is doing.
It’s easy to extend, as well. Adding in hubot scripts to automatically start and stop our little Hipstabot was really painless and will make a good future post, I’m sure. The good part – for me at least – is how close it is to the servers and how well it ties in with Capistrano. There’s no magic going on and there’s almost nothing to learn: as long as you have an EC2 account, you can set up a server quickly and painlessly with rubber… but if you know what you’re doing, it provides an immense amount of flexibility and power to deploy whatever you want in a simple, repeatable way.
rubber isn’t just happiness and unicorns, though; it has some definite downsides. It seems to have a lot less mindshare than tools like Chef or Puppet, and because it’s deployed on a per-application basis, it can’t easily manage multiple applications deployed onto one machine. But despite these problems I like it a lot, and it perfectly suits our present use case.
Dynamoid is (another) gem I developed, but I think it’s a lot more exciting than rapnd! I started work on it over Christmas but didn’t really get a lot of opportunity to focus on it again until recently, when work become relatively less busy.
Dynamoid owes a lot to Mongoid – it’s essentially trying to be for DynamoDB what Mongoid is for MongoDB. Unfortunately, it doesn’t really do a whole lot of exciting stuff yet…
But it will soon! The TODO list is particularly exciting:
Association magic: The standard fare like belongs_to, has_many, habtm.
Automatic value separation and joining: Values for DynamoDB keys are limited to 64KB, but with a clever framework we can get around that constraint with multiple keys conjoined together.
Automatic key distribution: As per Amazon’s provisioned throughput guidelines, keys that are frequently accessed incur a throughput penalty due to traffic concentration. Dynamoid will distribute keys that you specify across a number of duplicated keys, and will concatenate them together when read.
Not-gimpy finders: Criteria like you’re used to with ActiveRecord, so that you can do User.where(:name => ‘Josh’) rather than User.find_by_name(‘Josh’).
Range keys for models and indexes: To support queries like User.where(:created_at.gt => DateTime.now - 1.day)
I hope to have time over the next few days and the weekend to continue improving Dynamoid. Watch this space for further updates.
rapnd is a gem I developed to create a persistent connection through which to pass messages to Apple’s Push Notification servers. It’s pretty neat and you should check it out.
Why another push notification gem?
The existing ones just didn’t do what I wanted. There were some that created persistent daemon connections… but they were only usable with one app, and we have two apps we want to send push notifications for. There were some with multiple app support, but they didn’t have daemons or they assumed the existence of ActiveRecord. And in my opinion using ActiveRecord to store notifications is pretty dumb.
Whoa! ActiveRecord is just fine, bro.
Yeah, I love ActiveRecord. But it’s clearly the wrong storage solution for push notifications. For every single push notification we send, we couldn’t care less about the content or whether or not it was actually delivered – so storing them in the database just built a huge table that we ended up not needing at all. Redis is the perfect solution: it can handle arbitrarily-sized lists, but doesn’t bother with any significant kind of persistence. Also, blpop made the programming a breeze.
Why a daemon?
Well, Apple tells you to do it. But for a more important reason, Apple claims that constantly established and dropped connections to their servers will result in IP blacklisting. I’ve never actually seen this in practice, but… well… why chance it? rapnd uses one connection per daemon and tries to keep it open as long as possible.
Ran into some annoying problems with redis and resque recently that couldn’t be immediately solved through judicious Googling, so figured I’d make a quick post about it.
Resource temporarily unavailable - Timeout reading from the socket
If you installed redis-rb and hiredis by following the instructions at the redis-rb github page then you might start running into this problem. Essentially, the version of hiredis they specify (and that you probably installed) is out of date – 0.3.1 has a known bug with socket disconnects when reading from redis. So happily, the solution to this is pretty simple: just upgrade your version of hiredis. We use 0.4.4 now.
unexpected token at ‘OK’ (Resque::Helpers::DecodeException)
This one took a bit more tracking down to fix.
The newest versions of resque (I’m using 1.20.0) rely on versions greater than 2.4 of redis. Versions below that respond differently to certainly redis commands – for example, returning “OK.” Upgrading your redis server handily fixes this problem.