Programatically adding Applications to the Login Items
July 28th, 2008
Its taking some kicking around, but here is the fruit of my labour… using core foundation over the RC bridge.
require 'osx/cocoa'
loginItems = OSX::CFPreferencesCopyValue(
"AutoLaunchedApplicationDictionary",
"loginwindow",
OSX::KCFPreferencesCurrentUser,
OSX::KCFPreferencesAnyHost)
application_path = File.expand_path("~/path/to/your.app")
application_hidden = false
loginItems << OSX::NSDictionary.dictionaryWithObjects_forKeys(
[ application_path, application_hidden ],
[ :Path, :Hide ])
# puts loginItems
OSX::CFPreferencesSetValue(
"AutoLaunchedApplicationDictionary",
loginItems,
"loginwindow",
OSX::KCFPreferencesCurrentUser,
OSX::KCFPreferencesAnyHost)
OSX::CFPreferencesSynchronize("loginwindow",
OSX::KCFPreferencesCurrentUser,
OSX::KCFPreferencesAnyHost)
With any luck this might help someone :-)
Checking Network Connectivity with Ruby
July 25th, 2008
I’ve just been playing around with a few things and stumbled accross a really neat ruby lib called ‘timeout’. I used it to make a quick check for network connectivity like so:
require 'timeout'
require 'socket'
begin
timeout(10) do
TCPSocket.new("www.rubyforge.org", 80)
end
puts true
rescue
puts false
end
For so few lines thats a really neat; I thought so at least! :-)
Bongtastic load testing!!
July 8th, 2008
My mind escapes me at this late hour on a Tuesday eve, but Im fairly sure i’ve blogged about the httperf tool from HP Labs before.
Anyway, if I havent, thats a different story, as today, I want to point you good reader to the wonderfull tool that is Bong
httperf has somewhat cryptic command syntax, and bong is a really nice wrapper around it which make leveraging the full power of httperf a breeze.
Check out the Bong home page for more info – I’ll put up a quick tutorial when its not so late and my brain is functioning properly.
Java Is Not A Dirty Word...
April 11th, 2008
Strong title I know… It feels like thats how Java is regarded these days – Ruby and Python are becoming the golden boys of programming choice and poor ol’ java is being left out in the cold because people only remember it as having crap costing/license models where you [the developer] needed to pay for everything.
Well, I have good news for you my friends, Java should no longer be a dirty word! The inertia that Ruby on Rails had in the Java community did cause quite a lot of controversy its true, but its almost like after the initial xenophobia had worn off they sat up and thought “you know what, these guys might actually be onto something here”. I recently got into using Maven 2, and god, my good god, its a million times better than Ant, which just sucked so badly I cant explain! For anyone who is familiar with Rake, Maven is like Rake, but with all the package management stuff built right in – it does still have a certain level of entry required, but it just simplifies the process of created projects and managing dependencies in a very streamlined way.
The language itself has evolved quite a lot too – the new annotations are used heavily be JEE apps and frameworks – take CXF as an example; it will eventually replace XFire and Axis2 as the premier SOAP/WebService framework for Java, its a very very powerful tool and pretty easy to use (relatively speaking)
Anyway, I digress… my point is that if, like me, you left Java because the last time you worked with it you were slogging it out with 1.4 and Ant hell, then perhaps its time you took another look? Java has had significant investment as a platform, and there is a hell of a lot of good code out there for doing pretty much anything you can think of. In all honesty, one of the main reasons I have come back to JEE and the JVM in general is deployment – the JVM is very robust, and the containers built of top of it like Resin and Glassfish are being used in very high-concurrency environments and the deployment method via JAR or WAR is just so much more robust than on a platform like Ruby – and thats coming from having spent nearly the past 3 years solidly coding Ruby and doing all manner of deployments!
Dont write Java off – its an amazing platform, so what if its not as easy to get started as with other languages; think long-term, its a language that will grow with you rather than one you might someday reach the ceiling of – or just find incredibly annoying when the application dispatchers crash for a past time ;-)
Over and out
How to use rails 2.0.2 without a database
April 9th, 2008
Step 1
Run the rake task to freeze rails 2.0.2 into the project so your not reading from gems:
rake rails:freeze:gems
Step 2
Remove the database.yml file from RAILS_ROOT/config/
Step 3
Change line 21 in RAILS_ROOT/config/enviroment.rb to:
config.frameworks -= [ :active_record ]
Bobs your uncle, that should be it!
Cross Platform Language Mashups Are The Way Forward
April 5th, 2008
With new cross-language mash ups appearing all the time with things like JRuby and Jython it makes me wonder where all this is going? Will we have J2EE apps deployed alongside dynamic languages all within the same container, all capable of leveraging the awesome JVM runtime? If so, then wow, thats an awesome proposition. Pretty much every language you can think of is now deployable within a java container – its even possible to deploy .net applications via mono!
Perhaps people will start to standardize on the JVM as a platform – all this constant fighting over runtimes, platforms and environments makes work for the developer and architect extremely difficult; we want to keep up with the latest developments, but it just makes it so difficult to do that with all this chopping and changing.
Anyway, things I think are going to be seriously hot this year are:
Lift Framework and Scala
We’ll see how things play out over the next few months, but whatever happens, its going to be exciting to see how all these technologies interact with each other – which fizzle out and which go on to achieve wonderful things.
Updated XMPie / Merb Extension for Merb 0.9.2
April 3rd, 2008
Just a quick note that I have refactored the code base for the XMPie ICP extension for Merb 0.9.2 and added some extra cool things that are inherited by the ICP subclasses.
Now, its possible to add validation into the model subclass. Lets say we have a feild defined in our uPlan called ‘email’ and ‘user_name’. I need the ‘user_name’ field to be required, which you can now do like so:
class Visitor < Xmpie::Icp::Base
validates_presence_of :user_name
end
# in your controller...
@visitor.valid? # => true if has a user_name, otherwise false
All exciting stuff! When XMPie make ICP a more viable persistance tier, then this will no doubt be the quickest and slickest way to implement front ends in. Furthermore, with the Engine Yard team working on mod_rubinus then we should see ruby web application performance finally get where it needs to be.
Capistrano recipe for Merb 0.5.3 in production
March 14th, 2008
Further to my article about God, and using it for watching Merb it seemed like a good idea that I also post my capistrano recipe so people can get the complete picture :)
# MIT License
#
# Copyright (c) 2008, Tim Perrett
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated
# documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons
# to whom the Software is furnished to do so, subject to the
# following conditions:
#
# The above copyright notice and this permission notice shall
# be included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
# ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
# TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
# OR OTHER DEALINGS IN THE SOFTWARE.
set :application, "domain.com"
set :repository, "svn://yourrepo.com/path/to/repo"
# Set your SVN and SSH User
set :user, "sshuser"
set :svn_user, "svnuser"
#Set the full path to your application on the server
set :deploy_to, "/path/to/your/#{application}"
# define your servers
role :app, "domain.com"
role :web, "domain.com"
role :db, "domain.com", :primary => true
desc "Link in the production extras"
task :after_update_code do
run "ln -nfs #{shared_path}/log #{release_path}/log"
end
desc "Merb it up with"
deploy.task :restart do
# you need to add restart tasks for each port you plan
# to run merb on. Whilst this is a little long winded,
# it will ensure uptime compared to the sledge hammer
# than is #{current_path}/script/stop_merb
run "(cd #{current_path}; merb -k 4006); sleep 1; \
#{current_path}/script/merb -u timperrett -G timperrett \
-M #{current_path}/config/merb.yml -p 4006 \
-e production -d"
run "(cd #{current_path}; merb -k 4007); sleep 1; \
#{current_path}/script/merb -u timperrett -G timperrett \
-M #{current_path}/config/merb.yml -p 4007 \
-e production -d"
end
Any problems, let me know :)
Monitoring Merb Processes in the Wild with God
March 13th, 2008
Before you start reading, this post only applies for Merb 0.5.3, any newer version is totally untested
When you take Merb out into the wild, it does, unfortunatly, suffer a lot of the same problems as the mongrel handler than runs Rails.
There is however a saviour out there – God – To clarify, im not talking about the man upstairs; rather the process monitoring tool which rocks at restarting bloated mongrel processes on *nix based OS.
The Merb handler does not have any way of restarting a running cluster, so you physically have to stop, then start a new merb process. This is somewhat out of sync with how the god process handling and restarting works in that you define start, stop and critically, restart paramaters. To get around this we have to use a hacky sleep then start method – its not ideal, but hey, it works :)
Rather than letting merb handle the process forking, what were going to do is let God handle the writing of Pids and managing of the process. Ok, less of all this talk and lets take a look at some configuration code for the God configuration.
# MIT License
#
# Copyright (c) 2008, Tim Perrett
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated
# documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons
# to whom the Software is furnished to do so, subject to the
# following conditions:
#
# The above copyright notice and this permission notice shall
# be included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
# ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
# TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
# OR OTHER DEALINGS IN THE SOFTWARE.
SITE_LOCATION = "/var/www/sites/domain.com"
MERB_ROOT = "#{SITE_LOCATION}/current"
MERB_CONFIG = "#{SITE_LOCATION}/shared/config/merb.yml"
MERB_ENVIROMENT = 'production'
PROCESS_USER = 'timperrett'
PROCESS_GROUP = 'timperrett'
%w{4006 4007}.each do |port|
God.watch do |w|
pid_path = File.join(MERB_ROOT, 'log',"merb.#{port}.pid")
w.name = "merb-#{port}"
w.interval = 30.seconds # default
w.start = "#{MERB_ROOT}/script/merb -u #{PROCESS_USER} \
-G #{PROCESS_GROUP} -M #{MERB_CONFIG} -p #{port} \
-e #{MERB_ENVIROMENT} -d"
w.log = "/home/timperrett/godmerb.log"
w.stop = "(cd #{MERB_ROOT}; merb -k #{port})"
w.restart = "(cd #{MERB_ROOT}; merb -k #{port}); sleep 1; \
#{MERB_ROOT}/script/merb -u #{PROCESS_USER} -G \
#{PROCESS_GROUP} -M #{MERB_CONFIG} -p #{port} \
-e #{MERB_ENVIROMENT} -d"
w.start_grace = 5.seconds
w.restart_grace = 20.seconds
w.pid_file = File.join(MERB_ROOT, "log/merb.#{port}.pid")
# w.group = "merbs"
w.behavior(:clean_pid_file)
w.start_if do |start|
start.condition(:process_running) do |c|
c.interval = 10.seconds
c.running = false
end
end
w.restart_if do |restart|
restart.condition(:memory_usage) do |c|
c.above = 51.megabytes
c.times = [3, 5] # 3 out of 5 intervals
end
restart.condition(:cpu_usage) do |c|
c.above = 50.percent
c.times = 5
end
end
w.lifecycle do |on|
on.condition(:flapping) do |c|
c.to_state = [:start, :restart]
c.times = 5
c.within = 5.minute
c.transition = :unmonitored
c.retry_in = 5.minutes
c.retry_times = 5
c.retry_within = 2.hours
end
end
end
end
Im not sure that this is ideal, but it certainly seems to work for me and importantly keeps the site running without problems – which is a dang sight better than them becoming unresponsive!
I hope this might help someone, somewhere….
XSLT using Ruby
January 31st, 2008
Short Story
libxsl-ruby is a nightmare to install. If you can indeed get it to install at all. I couldnt get the bloody thing to install at all on my 10.5 OSX box; and thats with ALL the required libs installed. I get the impression that its not very well maintained anymore and the project following has dropped off.
I turned to ruby-xslt – based on REXML, so yes, its slower. If your looking for speed then persist with the libxsl ruby path, but otherwise, save yourself a lot of time and just use this. Its vastly simpler!
Long(er) Story
Libxsl sucks. Strong statment I know. I would say im a fairly techincal chap, and ive just spent, nay, wasted, the last 3 – 4 hours trying to work out why libxsl-ruby wont install. Thats a bit of a bugger indeed. Who knows what the problem is, but ultimately its less portable due to reliance of the Gnome XML parsing libs. Granted there very fast, but thats no help at all if you cant even install them.
REXML vs Libxml is a non-contest. We all know libxml is significantly faster – if you need that speed then i strongly advise you to continue with libxml; it will pay dividends in the end. If however your not going to need very fast parsing, then really, save yourself a lot of wasted time and use REXML.
REXML is bundled with the ruby distribution, so its also a lot more portable that libxml2. Anyway, if your even still reading, stop now, and bosh this into your terminal:
sudo gem install ruby-xslt
Job done.