Freebootr update
December 30th, 2008
Chris Irish and I have been hard at work making another release of Freebootr. We released it in mid-December with improved search and speed as well as a redesigned look and feel. Shortly after this release, we got a write up in the Phoenix Business Journal.
To date we have over 23,000 listings in 17 states. We’re excited about the progress made on Freebootr and hope that 2009 continues the progress we’ve made in waste reduction. We hope you’re excited too! We’d love to hear your thoughts or ideas about Freebootr, so please send us your feedback.
Monitoring Thin using God, with Google Apps Notifications
December 14th, 2008
We’ve been using God to monitor our Thin processes on Freebootr and set it up to notify us through our Google Apps account. Thought our God config file might be useful to anyone trying to use God with Thin and Google Apps.
Thin configuration
# == God config file
# http://god.rubyforge.org/
# Authors: Gump and michael@glauche.de
#
# Config file for god that configures watches for each instance of a thin server for
# each thin configuration file found in /etc/thin.
# In order to get it working on Ubuntu, I had to make a change to god as noted at
# the following blog:
# http://blog.alexgirard.com/2007/10/25/ruby-one-line-to-save-god/
#
require 'yaml'
config_path = "/etc/thin"
Dir[config_path + "/*.yml"].each do |file|
config = YAML.load_file(file)
num_servers = config["servers"] ||= 1
(0...num_servers).each do |i|
# UNIX socket cluster use number 0 to 2 (for 3 servers)
# and tcp cluster use port number 3000 to 3002.
number = config['socket'] ? i : (config['port'] + i)
God.watch do |w|
w.group = "thin-" + File.basename(file, ".yml")
w.name = w.group + "-#{number}"
w.interval = 30.seconds
w.uid = config["user"]
w.gid = config["group"]
w.start = "thin start -C #{file} -o #{number}"
w.start_grace = 10.seconds
w.stop = "thin stop -C #{file} -o #{number}"
w.stop_grace = 10.seconds
w.restart = "thin restart -C #{file} -o #{number}"
pid_path = config["pid"]
ext = File.extname(pid_path)
w.pid_file = pid_path.gsub(/#{ext}$/, ".#{number}#{ext}")
w.behavior(:clean_pid_file)
w.start_if do |start|
start.condition(:process_running) do |c|
c.interval = 5.seconds
c.running = false
c.notify = 'developers'
end
end
w.restart_if do |restart|
restart.condition(:memory_usage) do |c|
c.above = 150.megabytes
c.times = [3,5] # 3 out of 5 intervals
c.notify = 'developers'
end
restart.condition(:cpu_usage) do |c|
c.above = 50.percent
c.times = 5
c.notify = 'developers'
end
end
w.lifecycle do |on|
on.condition(:flapping) do |c|
c.to_state = [:start, :restart]
c.times = 5
c.within = 5.minutes
c.transition = :unmonitored
c.retry_in = 10.minutes
c.retry_times = 5
c.retry_within = 2.hours
c.notify = 'developers'
end
end
w.transition(:up, :start) do |on|
on.condition(:process_exits) do |c|
c.notify = 'developers'
end
end
end
end
end
Email through Google Apps configuration
require 'tlsmail'
Net::SMTP.enable_tls(OpenSSL::SSL::VERIFY_NONE)
God::Contacts::Email.message_settings = {
:from => 'user@domain.com'
}
God::Contacts::Email.server_settings = {
:address => 'smtp.gmail.com',
:tls => 'true',
:port => 587,
:domain => 'domain.com',
:user_name => 'user@domain.com',
:password => '******',
:authentication => :plain
}
God.contact(:email) do |c|
c.name = 'Dev 1'
c.email = 'dev1@domain.com'
c.group = 'developers'
end
God.contact(:email) do |c|
c.name = 'Dev 2'
c.email = 'dev2@domain.com'
c.group = 'developers'
end
References
Installing aspell and raspell for Ultrasphinx
September 25th, 2008
We’ve been playing around with the Sphinx full-text search engine and Ultrasphinx, the Ruby on Rails configurator and client to the Sphinx full text search engine. Sadly, it was giving us a warning about spell checking:
ultrasphinx: spelling support not available (raspell configuration raised "uninitialized constant Ultrasphinx::Spell::Aspell")
This is pretty easy to get rid of, though. You just need to install the aspell, spell checking library and raspell, the Ruby interface to aspell. The raspell README has instructions for installing aspell and raspell on both Mac and Ubuntu.
After we did this, we got one additional error:
ultrasphinx: spelling support not available (raspell configuration raised "No word lists can be found for the language "ap".")
Follow the instructions for setting up the custom wordlist needed by Ultrasphinx and you should be good to go.
Good luck and happy searching!
Error after upgrading SliceHost
September 23rd, 2008
If you happen to see this error after upgrading your SliceHost account, be calm.
ActionView::TemplateError (Define INLINEDIR or HOME in your environment and try again)
The simple solution is to add an environment declaration to your environment/production.rb file:
ENV['INLINEDIR'] = '/path/to/.ruby_inline'
Once that was set, we were in business again… whew!
References
Here’s a relevant reference that took a while to find:
Quick Tip: Setting an SPF record
September 23rd, 2008
I recently noticed a lot of rejected emails coming from a production app that had just switched to send mail through Google Apps. For some reason Google felt we might be spammers, so it began rejecting our emails out-of-hand. We would continuously get the following error message:
Technical details of permanent failure: Message rejected. See http://mail.google.com/support/bin/answer.py?answer=69585 for more information.
That wasn’t very helpful, but with a little digging it led me to find out about something called an SPF and convinced me that I should set this up. It was really easy and I suggest you do it if you’re sending mail from your Ruby on Rails application through Google Apps (or some other means).
When using Google Apps, simply add a TXT record to your DNS settings with the following value:
v=spf1 mx include:aspmx.googlemail.com ~all
Note also that Google wants you to use include and specify all with a tilde(~), not a plus(+) or minus(-).
Publishing an SPF record that lacks include:aspmx.googlemail.com or specifying -all instead of ~all may result in delivery problems.
I also contacted Google to let them know of the error and if you start seeing this, be sure to let them know, too. Either that or setting the SPF record corrected our problem and we no longer get the rejected emails…
References
Freebootr Ahoy!
September 19th, 2008
I wrote recently about Phoenix Hacknight (that happens every Wednesday) because I want people to know that there is a vibrant, active community in Phoenix centered around technology. Hacknight has become a place where people meet consistently to network with each other and hack on various projects. I have attended every single Hacknight and closed shop on most of them, but besides the amazing 6 hour hacknight website, I’ve yet to really release a new idea to the public.
That’s why I’m happy to announce the launch of
The Idea
Freebootr is an idea hatched at Hacknight by Chris Irish and me. It provides a place for people to easily and quickly find free items in their area as well as post free items they no longer want or need. We hope that this will result in less landfill waste and reduced cost to consumers. We believe this type of service should be free and open to the public and that’s exactly what we’ve done. What’s more, we believe it should be fun to use, which is why the site is pirate themed! Why, you ask?
freebooter |ˈfrēˌboōtər|
noun
a pirate or lawless adventurer.
That’s right, a freebooter is a pirate, so naturally we themed the site after these denizens of the sea. Arrr!
The Journey
Freebootr has been in the works for about 8 weeks at Hacknight. Chris and I have put in about 40 hours each throughout that time and set a goal to release the first version of the product today, on International Talk Like a Pirate Day. We also took a 2 week hiatus to implement the Hacknight website. It has been a fun, and somewhat bumpy, ride to get here, but we did it.
The Rest
Now the real work begins, for us and for you. We want… nay, need your feedback to make Freebootr.com a great, useful site. So check it out and be sure to call us out when we suck (and occasionally when we kick ass).
Now go out there, me hearty, and become a Freebootr!
Hacknight
September 16th, 2008
About 24 weeks ago, we started hosting a regular Wednesday night gathering at our Chandler, Arizona office called hacknight (originally hack-a-mania). We open our office to the public from 6pm until whenever to allow people in the Phoenix area to meet, network, play, eat, have fun and, of course, hack on projects. After almost 6 months, hacknight is still going strong!
Check out this hacknight video
Hack Night from Integrum Technologies on Vimeo.
Also check out the people and projects at hacknight, on the new site devoted to everyone who makes these wonderful events happen! If you’re interested in what hacknights are doing for the Phoenix community, be sure to come by the office located at
290 E. El Prado Ct., Chandler, AZ 85225
We’re there every Wednesday night, hacking away… you should be too!
Quick Tip: Setting time zone on Ubuntu Hardy
September 13th, 2008
I’ve been pretty enamored with SliceHost recently. They make it very easy to setup a slice, configure it and get your product deployed quickly (I’m down to 30 min). I hadn’t noticed until just recently that I’ve never set a time zone on any slice I’ve configured. So, here’s how you do it, simple and easy.
- SSH into your slice
- Run this command:
sudo dpkg-reconfigure tzdata - Select your geographic area and location
That’s it, hope it helps!
If you want your own slice, consider using my Slicehost referral link. Thanks!
GoRuCo 2008 Wrap-up
April 28th, 2008
As I stated in a previous post, I attended the Gotham Ruby Conference this past weekend in NYC. It was a great time with many interesting talks. The weather was amazing as well. I don’t want to spend a lot of time rehashing the conference because you can view the GoRuCo 2008 presentations for yourself, but I did want to mention a few things I got out of it.
Bryan Helmkamp gave an interesting introduction to story driven development using rspec and story runner. This is something we’ve been talking about at Integrum, but haven’t had a chance to use in a real setting yet. Derek and I got to spend some time at the WePlay offices (where Bryan works) and they showed us some of the stuff they’re doing, including using story runner. It was awesome to hear about their experiences and hopefully we’ll get a chance to use it soon.
Next up was “Archaeopteryx: A Ruby MIDI Generator.” I was skeptical about this one, but was blown away by Giles Bowkett’s presentation. From recounting his life adventures, including a “psycho throwing rocks at his dad until he threatened him with a piece of rebar” to calling venture capitalists “weasel-brained muppet fuckers… they’re not fools, they’re liars.” He kept the crowd well entertained, but threw in some really interesting and well-delivered points about startups and life. It is well worth watching.
Another one that really stood out was Ryan Davis’ presentation about “Hurting code for fun and profit.” He had a lot of really great things to say about being a developer, so go watch it already!
These speakers helped me to become aware of a few things:
- I don’t read enough. Ryan mentioned that the average developer reads 1 book a year. Is one book a month really so hard?
- I don’t hurt my code enough. I don’t use flog or heckle consistently and I often don’t take the time to correct code that I know should be improved.
I definitely have some things to work on… how about you?
Integrum Trip - SxSW day 1
March 8th, 2008
The first real day of the conference. I’m not gonna lie to you, the first day seemed pretty light. Registration was from 10:00am until 2:30pm with no panels, sessions, etc. scheduled during that time.
We got to the convention center in Austin at about 11:00am, registered with ease and proceeded to B. D. Riley’s Irish Pub for an Austin Refresh meetup. Not wanting to partake in the suds before noon, Gist and I headed for Starbucks for some early afternoon pick-me-up.
After the Refresh meeting we headed back to the convention center to prepare for the first panel of the day. Then a strange thing happened… While we were shooting the shit, Gist comes up with a great idea for a simple application for Twitter. We laugh about it, throw some ideas around and viola we have the beginnings of a new project. After taking a poll amongst the others, we decided to devote a triple to working on a first release – me, Jade, and Gist.
While Gist drew some sketches, Jade and I borrowed a laptop from Heidmo to begin development. Just a few short hours later we have our first version of an app we are calling “Props and Drops”. It is a way for people to give props (or drops) via Twitter. It’s pretty easy to get started, just visit http://props.integrumtech.com and click ‘About’ to get started. It also has a nifty iPhone interface, so if you’re lucky enough to have an iPhone check it out!
It was really awesome to see an idea progress so quickly. Here is a brief timeline of the day (totally estimated):
- 1:00pm – Mother jokes
- 1:07pm – Gist mentions way to vote people up or down via Twitter
- 1:08pm – Someone says props
- 1:12pm – More mother jokes
- 1:17pm – The idea turns serious and Jade, Gist and I volunteer to build it in the few hours before the 5:00pm panel
- 1:21pm – Another mom joke…
- 1:35pm – Gist sketches interface
- 1:30pm to 3:30pm – Jade controls laptop while I pair and we write the app in under 2 hours
- 3:30pm to 4:52pm – Deployment takes about another hour, including minor tweaks discovered on deployment
- 5:00pm – People begin to use ‘Props and Drops’ during the 5:00pm panel
- 5:45pm – Strebel gains a substantial props lead over all others
- 6:10pm – High fives are exchanged amongst Integremlins
- 6:11pm – Mother jokes resume
- 6:40pm to 2:00am – Alcohol is consumed
What a completely awesome day. Thanks to Jade and Gist for kicking ass to get this app out there and ready for use. Thanks to everyone already partaking of the Twitter Props and Drops goodness. Send us feature requests!!
Integrum and me
February 9th, 2008
In August 2006, I left my employer to embark on a journey to change my skill set and mind set. My previous employer was a very large defense contractor who offered a decent workplace, average salary, excellent benefits, and, of course, job stability. I announced to my friends and family that I would be leaving this employer, returning to Arizona and leaving the ranks of the employed for an undetermined amount of time. It seemed ludicrous to most people at the time, myself included. I was sure of only one thing at that time: I intended to refocus my career goals in an entirely different direction.
Unemployment
I had attempted to take my career in a different direction while still working, but I found that after 60-80 hour work weeks, a Master’s program in Computer Science and a wife and two young children, I didn’t have the energy. Voluntary unemployment was a calculated risk that I could learn what I needed to enter my newly chosen career path before I was forced to declare bankruptcy.
Unemployment is not really as bad as I thought it would be. I was able to spend time learning the things I was truly interested in, including Ruby on Rails. I spent a lot of time with my family and generally enjoyed myself. I found that I could actually work longer with more focus that I ever did at a previous employer without feeling tired or burnt out.
Eventually, our finances drained to the point of alarm and I began to look for a professional position working with Ruby on Rails.
Contracting
Since early 2007, I have been contracting my Ruby on Rails services to various employers. While this was lucrative it was also very frustrating. During that time I learned a little about myself and the environment in which I work best. I invest myself in what I do and as a contractor I found it hard to not get involved beyond what was required of me.
My first contract position was a fixed bid contract that was referred to me by my brother. It allowed me to choose the technology and create a simple student tracking system for a wellness center. It was deployed internally in January of 2007 and as far as I know it is still being used. My first real, deployed and used application! With that experience under my belt, I placed my resume on various websites advertising my interest in Ruby on Rails development positions. In a few short days I was contacted.
My second contracting position was an 18 month contract to create an EMR system for a local, privately held behavioral health organization. This was the big test for me to gauge if my calculated risk would pay off. Unlike the previous contract I was interviewed about my knowledge of Ruby on Rails, databases and Agile development. Two weeks after advertising my resume, I was hired to work professionally with Ruby on Rails. I learned a lot during my time contracting for that company, including how much I didn’t know, and met a great Phoenix Ruby on Rails developer, Josh Huckabee. I also attended my first RailsConf in Portland, OR in May with Josh and a few of the full-time employees.
Attending RailsConf was a real turning point for me, in many ways. Part of what I was missing as a lone wolf developer was the sense of community and interaction with other Rubyists – I met some great people at RailsConf! Upon returning, I began attending the Ruby User’s Group in Phoenix, Phoenix Rails Group and Refresh Phoenix to connect at a local level with other enthusiastic Rubyists, developers and designers.
This was the beginning of the end of my time at my current contract. As I discovered more about agile Ruby on Rails projects I realized that it would be highly improbable to influence the current direction of my contract employer. For three more months Josh and I attempted to influence the direction of our project and rescue it from impending failure. In August, we made our exit and, because of RailsConf and local networking, we began contracting for a Phoenix Ruby on Rails consulting company, Integrum Technologies.
Integrum and Me
In January 2008, Josh and I became full-time Integrum code monkeys. Integrum is an amazing place to work and completely unlike any company I’ve worked for. There is a level of openness and transparency that I have only read and dreamed about. Of course, Integrum is not perfect, but we are working hard to constantly improve ourselves while still having a blast. My wife constantly reminds me that Integrum is fueled by fun :) I believe that this year will be an important one for our company. You can keep up on what’s going on with us by reading, or subscribing to, the Integrum blog.
A year and a half has passed since I resigned my comfortable, full-time position in California. In that time I have accomplished more that I could have hoped for and am happier than I’ve been in some time – my calculated risk paid off.
Google Maps API with large data sets
February 11th, 2007
Part of the startup I’m pursuing involves using the Google Maps API to display a map containing location markers. The number of location markers could exceed 4000 at any given time. I currently have a sample dataset of around 500 and found that the map loading was starting to slow down. I considered several reasons this may be the case including how I was generating the JavaScript on the page using Ruby on Rails. I decided to do a little testing using examples from the Google Maps API Documentation.
I found a wiki reference that discussed marker optimization techniques and tried some of them to see the differences. There are others besides these, so if you are interested visit the link.
- Only Draw the Points in the Area Viewport – Great suggestion, but is only valid when the user zooms in. At the highest level, if all points are displayed then this has no effect.
- Load Different Points at Different Zooms – Another good suggestion. This is accomplished through the use of the GMarkerManager. However, the question remains as to how to breakup your data. Do you provide a generic icon at higher zoom levels and when clicked on it zooms in and displays markers? Do you display “preferred” locations at higher zoom levels (e.g., paying users)? Do you display higher ranking/rated (assuming you have a ranking/rating system) locations at higher zoom levels? For my particular app, I use the GInfoWindow to display information about a particular point. If I don’t go with the generic icon approach then I would be giving preferential treatment to some locations and would need to figure out how to justify it. For example, people might not zoom in to reveal other locations and thus the highest zoom level markers would get all the attention. If I did use a generic icon, then the data on my map would not be as impressive because you could only see a few icons until you zoom in. Additionally, it would not be possible to see the locations in relation to each other at higher zoom levels.
- Add HTML to InfoWindows (Bubble) Using Click Event – Yea, I thought about this one too, but found that during my testing without using the InfoWindows it was still slow.
- Preload the marker images – Hmmm… special case for IE? Nah, I say let ‘em suffer.
- Omit the shadows – Those pesky shadows… This actually did seem to make a difference during my testing, but it doesn’t look as nice.
So, what to do? I am considering trying a combination of the approaches above as well as delaying the loading of the markers. For example, at the highest zoom level, all markers are visible, so I might wait about half of a second before adding markers. Then when I’m adding, I allow about an eighth of a second between batches, where a batch is 20-25 locations. Instead of using the GMarkerManager at the highest zoom level I would just use addOverlay. This gives the map the appearance of pretty smoothly adding markers to the map. Although it is kinda cool to watch, adding one marker at a time takes too long, so it has to be a few at a time. Not so many that it appears chunky though.
The other techniques that I think might be useful are delaying the InfoWindow data until the onclick event as well as factoring in the viewport area for marker display. Theoretically, this should allow me to load all of the markers with the smallest amount of information possible and increase the performance as the user zooms in.
I really don’t like the clustering approach as is tends to obscure the data. Part of what I am trying to accomplish with using Google Maps is to present my data in a way that allows for easy visualization of the points in relation to each other. Clustering seems to defeat that purpose. I also like the shadows because it makes it look nicer. If it comes down to it I will, reluctantly, lose the shadows.
My other options are to disallow viewing all of the locations at once. This might be accomplished by loading an empty map and asking the user to search first. Additionally, I could limit the search results to a few hundred. I’m not keen on this approach, but I may be forced to go this route if I can’t improve the performance otherwise. I could also try using an XML file with GDownloadURL, but I can’t see that actually being faster.
I had an extremely hard time finding information about Google Maps and performance, including tips, techniques, hacks, etc. If you have any suggestions please post in the comments. It would be very interesting to see how other people are handling this problem.
Contracting
January 23rd, 2007
I am about to end my first contract position with the Gila Community College Wellness Center in Arizona. I have been developing an internal web-based application for them and will deliver it at the end of this week. I was able to convince them to let me use Ruby on Rails for the development with a MySQL Database. Essentially these are the same technologies I have been using on my startup.
Have I mentioned recently that I love Ruby on Rails? No? Okay, ummm… I love it. For the startup I was concentrating on pushing features as quickly as possible and I was least concerned about formal testing. In a contract position though I needed to really delve into how to test my code using the built in functionality provided with Ruby on Rails. With a little help from the Agile Web Development with Rails book I was testing in no time. The testing framework in place makes it very easy to develop and run your tests. Eventually I will need to go back through my startup code and add tests. I was dreading that activity, but now it seems like it will be easier than I expected. Of course, I am a bad programmer for letting it lapse in the first place… baaaad programmer!
Testing is one of those activities that is often overlooked during the course of your academic career. When I completed my BS in Computer Science at the UofA testing was not on the curriculum. Our introduction to testing was when some teaching assistant developed a rudimentary suite of tests to grade our program. They usually released some of them so you could get a feel for how well you had coded, but your grade was based on a super-set of the tests you were given. Now that I look back on it they probably knew only a little more than us about testing, but of course they needed something to base a grade on. I remember several times when people discovered errors in the TA’s tests!
There were very few people who developed their own tests. In fact, the philosophy I heard espoused most often from students and faculty was “Just get it working!” There was one guy though, Tal, who created tests and, compassionately, allowed others to test against them. He was a special case though as he was light years ahead of anyone else I knew in that program. Only later did I find out that he was a chess grandmaster... He eventually went on to pursue an advanced degree at UW and currently works at Google.
Anyway, I have wanted to try test-driven development for a while, but keep putting it off. Why? Why is it so hard to do? I think I have been conditioned to think of tests as a secondary activity. Sadly, this looks to be a difficult habit to overcome. Anyone have any suggestions for these testing withdrawal symptoms? Any advice is appreciated.
What is an entrepreneur?
January 16th, 2007
Over the holiday break I had a chance to talk with a lot of friends and family members about starting a company. I have been working on this venture for a few months, but had been keeping everything hush-hush. Most of them had no idea what I was doing. So, I decided to spill the beans and talk openly with people I know I can trust for an honest opinion. Just like I said in a previous post, reactions were mixed.
It got me thinking about what it means to be an entrepreneur. Merriam-Webster defines entrepreneur as “one who organizes, manages, and assumes the risks of a business or enterprise.” I think that the role of entrepreneur is more difficult than that short definition implies. It’s not enough to be the one who has an idea and organizes the company to realize the idea. As I have been finding, there is a social aspect to being an entrepreneur that takes you on a roller coaster of emotions, from depressed to uplifted, frustrated to satisfied, empty to fulfilled. It is the job of the entrepreneur to push past those feelings of depression and inadequacy and focus their energy on the task at hand.
There have been several times when I thought I should throw in the towel and get a “real job”, as my parents so eloquently put it. It took the advice of an old friend who I recently reconnected with on LinkedIn to put me back on track. He is also trying to start his own company called Webographers, but he’s a few steps ahead of me. Sharing his own experiences with me about his company helped me to reaffirm my intention of making my venture work.
While it is good to get many opinions about your venture, be sure to surround yourself and keep in close contact with people who will renew your focus and ambition. It is easy to quit something when it becomes tough, in fact, our society almost encourages it. It is far more rewarding to persevere in the face of adversity. As an entrepreneur we must not only steer the company through rough waters, but we must fend off these dark thoughts and emotions that creep in from time to time. Only if we do both successfully will we have a real chance to succeed.
Holiday 2006
December 23rd, 2006
I took a little time before the holiday to go on another fishing trip with my dad. This time we went to Bartlett Lake, just northeast of Phoenix. The fishing wasn’t great, but the location was spectacular. The lake itself sits in the Tonto National Forest, an area overflowing with saguaro cactus, desert vegetation, and wildlife. We only caught three fish between the two of us, the largest being my large mouth bass. It was about 15.5 inches and probably around 2-2.5 pounds, although we didn’t weigh it. We may take another trip before the new year, but that is yet to be decided.
I met my end of year goals of revising my executive summary, creating a presentation from it, and submitting it to a handful of VC firms. I also updated my resume as a few firms would like your full resume, not just a paragraph description of your accomplishments. I also met a stretch goal of releasing another version of the site, although admittedly it is only a minor version; mostly backend changes. I feel really good about what I have accomplished this year.
I hope everyone has a happy holiday. I will be spending time with my family and relaxing for a few days then it’s full steam ahead into 2007. I am confident this will be a great year.