Extending Adobe CS3 Applications
March 31st, 2008
Of late ive been doing some investigation into extending InDesign with plugins and such. Traditional Adobe plugins needed to be written in C++ but now with the addition of the CS3 SDK its possible to write JSXB’s from which you can extend the UI and all sorts of other good stuff!
I’ve been playing around with it, and true, its not as quick as C++, but its so much vastly more accessible the trade off does not seem like a major crime. If you want to try it for yourself, check out the SDK here
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….
Choosing a style of personalised URL
March 13th, 2008
I think that pretty much all the ‘Personalised URL’ jobs that I have ever needed to do have always been of the directory style, e.g:
www.domain.com/mylovelyusername
However, it strikes me that a better and more programatically favourable format is the sub-domain pattern, e.g:
mylovelyusername.domain.com
In this instance you don’t have to worry about holding information in sessions, or setting up anything else complicated to make sure that they visit that URL first – it doesn’t matter with the sub-domain pattern as you always have there unique identifier to hand in the URL. Im not wholly sure why it is that more people don’t see the benefit of doing this – if you ask me it ‘feels’ more personal that a one time visit to a directory style URL.