0.9.1 already? Thats how we roll
We fixed a lot of bugs from 0.9.0 (see the changelog.) In addition to that we made two big(ish) changes.
Full Server Code Reloading
Volt already reloaded code on the client side, but we had the major pain that you had to restart the server when you added things like Tasks. Server side code reloading can be very complex, its something I’ve personally had to deal with in other frameworks, and also something that has bit me on many occasions.
I had a few requirements for code reloading:
1. It had to work all of the time. This seems obvious, but if you’ve hit against load order issues in other frameworks, you’ll know thats not an easy task. A common strategy is to unload classes, then re-require the files. The problem is this is very order dependent and also only works if the files follow a file name/class name convention. It also doesn’t handle one off code in files. For more details check out this great article on Rails’s code reloading.
2. It has to reload fast. This is probably the most important. I don’t want to be waiting around for my app to reload.
3. It should be simple under the hood. Complex loading/reloading strategies can make debugging, maintenance, and overall understanding whats going on difficult. Simple usually wins.
How server code reloading works in Volt 0.9.1 #1 above is pretty important to me because I’ve had to deal with the problems of when it doesn’t work. I also wanted to support things like reloading when lib changes and when the Gemfile changes (maybe after a bundle?). I haven’t gotten to those things yet, but they should be pretty easy to add now. To guarantee correct reloads, we decided to do a “preforking” strategy.
When a Volt app boots, it loads all of Volt, all component gems. Next it forks off a child process and loads your app in the fork. When a request comes in, it gets answered in the child process. The child continues to answer requests until a ruby file changes in your app folder. At that point, the child process is killed and a new one is forked.
The great thing about this strategy is that you guarantee nothing sticks around and there’s no load order issues. Its as if you had rebooted your app entirely for everything in your app. You might think this strategy would be slow, but its amazingly fast for a few reasons.
1. Your only reloading your code. Most of the boot time on Volt is loading Ruby, Volt, Volts dependencies, and component gems. In the grand scheme of things, your app is usually a pretty small piece of the puzzle. 2. Copy on Write. You might think that fork is slow because it has to make a copy of the memory of your entire process. However, most OS’s (linux, OSX, freebsd, etc..) support what’s called “copy on write”. This means the memory isn’t actually copied until it is changed. For the majority of your app it won’t actually be changed. Ruby 2.0 made some big improvements to make sure that very little memory is changed as part of the garbage collection process. 3. Granular Reloading. So this one is still a work in progress, but the plan is to prioritize the load order based on reload frequency. (when applicable) So for example, lib classes could be loaded first, since they are rarely reloaded. Then we can fork at different stages so even less of your code needs to reload each time.
If your on MRI on OSX or Linux, give 0.9.1 a try and I think you’ll be very happy with the new code reloading. I will give the disclaimer that the current strategy has a few drawbacks and we’ll probably introduce a second strategy at some point (for those who don’t support the current strategy).
The first drawback is windows and jruby don’t support fork. So for now it just doesn’t reload on windows. Jruby support is in the works I personally love jruby, but I was stuck on MRI before because of our sockjs server implementation, which leads me to the next improvement.
Support for more app servers
Previously Volt used sockjs for socket connections to the browser. SockJS is nice because it has fallbacks for really old browsers. Unfortunately, the SockJS server we were using was tied to the thin server. However upon closer inspection, websockets are very well supported. The only two browsers with any traction that aren’t supported are IE 8&9. We switched to use the faye-websocket gem for Volt’s sockets. This lets us use other servers. First up was support for puma. We’re still recommending thin, but you can switch out puma in your Gemfile now and everything should work fine. We’ve also been told the nginx version of phusion passenger is working. We fixed some issues with running Volt directly as a rack app. In 0.9.2 it should be easy to mount volt in another rack app. (Just a few minor changes are still needed on our end).
Mailer Support
New volt apps now include the volt-mailer gem. Check out the gem README.md for full details. Basically though, you can create a view with a .email extension. We use the same controller/view system for html. Instead of :Title and :Body sections, you can use :Subject, :Html, and :Email sections.
<:Subject> Welcome to the site <:Html> <h1>Welcome</h1> <p>...</p> <:Text> Welcome ...
Then to send the email you can just call Mailer.deliver(’view/path’, {to: ‘[email protected]’}) You can only call Mailer.deliver from the server (to prevent unwanted e-mailing). We recommend using a task to send the e-mails. (If you need to trigger from the client side) The nice thing with sections in volt templates is you can keep the whole e-mail in a single file. This makes it easy to look at it and see what people are going to receive. (Plus I really like having the subject in the view).
Next Up
We’ve been working on the Data Provider API to support other databases than mongo. We did 0.9.1 earlier than expected to fix a few bugs and get a few other things out. But I think 0.9.2 will be the release with the data provider api.
- Ryan






