Installeren Git en Ruby op Solaris

Op een Solaris machine zonder internet connectie en zonder admin rechten.

De GNU tools in het path plaatsen:

1
export PATH=$PATH:/usr/sfw/bin:/usr/ccs/bin

Installeren Git:

1
2
3
4
gtar -xvzf /tmp/git-1.6.5.4.tar.gz 
cd git-1.6.5.4
MAKE=gmake ./configure --prefix=/apps/local --without-tcltk  --enable-pthreads=-pthreads
MAKE=gmake gmake install

Installeren Ruby

1
2
3
4
5
gtar -xvzf /tmp/ruby-1.9.1-p243.tar.gz 
cd ruby-1.9.1-p243/
MAKE=gmake ./configure --prefix=/apps/local
MAKE=gmake gmake
MAKE=gmake gmake install

Uncle Bob’s keynote

Inspirerende praatje met een staande ovatie aan het eind. Wil meteen een IDE opstarten en wat gaan coderen, misschien zelfs in het dode Smalltalk.

Niet echt nieuwe inzichten over de ondergang van Smalltalk, maar eigenlijk gewoon een leuk praatje over waar we nu in ons vak staan.

Als Smalltalker's moeten we het ook niet te serieus nemen of willen verdedigen, dat is ook wat hij zegt in zijn praatje. Leuk ter vermaak al die verschillende technologie communities die de spot met elkaar drijven, het wordt pas een probleem als we er serieus in gaan geloven.

JRuby to the rescue

Onze applicatie zorgt eens in de zoveel tijd voor een out of swap space error, waardoor tomcat down gaat. De oorzaak van de error is een externe library waar we nog geen oplossing voor hebben. Voor nu willen we dat tomcat automatisch weer opstart als de out of swap space error zich weer voordoet.

Via de pid van het tomcat proces kan ik controleren of het proces nog draait. Hiervoor moet ik wel de CATALINA_PID environment gebruiken, zodat ik de pid uit een bestand kan halen.

Voor het scottie project had ik al iets vergelijkbaars gemaakt met Ruby componenten. Ruby is echter niet geinstalleerd op de Solaris productie omgeving. Om deployment simpel te houden heb ik het geprobeerd met een shell script, maar ik merkte dat ik daarvoor nog te weinig van af wist. Uiteindelijk kon het ook met JRuby. Het enige is dat JRuby zich net wat anders gedraagd dan MRI als het gaat om processen. Waar MRI een exceptie gooit, geeft JRuby een -1 terug.

Het script heb ik eerst geprobeerd als cron job te draaien, maar ik zat dan weer met environment settings die dan ontbraken.

Voor nu heb ik gewoon een loop in de code gemaakt en start ik het script met nohup.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/usr/bin/ruby
class Tomcat
 
  def initialize(pidfile)
    @pidfile=pidfile
  end
 
  def running?
    begin
      Process.getpgid(pid)!= -1
    rescue Errno::ESRCH, Errno::ENOENT
      false
    end
  end
 
  def pid
    File.open(@pidfile) do |f|
      f.gets.to_i
    end
  end
 
  def start
    puts "Starting tomcat"
    `./startup.sh`
  end
 
end
 
@pidfile=ENV["CATALINA_PID"]
if @pidfile.nil?
  puts "CATALINA_PID environment variable not set."
  exit
end
 
tomcat = Tomcat.new(@pidfile)
loop do
  puts "checking"
  tomcat.start unless tomcat.running?
  sleep(30)
end

Ben nog bezig het in gem vorm te gieten en heb het intussen op github geplaatst.

Reading code: concerns

Zat weer even te kijken hoe anderen in Ruby coderen. Voor het integreren van een forum in een applicatie, zat ik met altered_beast te werken. De manier hoe functionaliteit aan een User object toegevoegd werd was nieuw voor mij.

Een User model in een forum heeft verschillende 'concerns', functionaliteiten die je bij elkaar kunt groeperen zoals: authenticatie, posten van reacties, etc. Deze zijn gegroepeerd in aparte modules i.p.v. in een grote User class.

ActiveRecord word uitgebreid met een concerned_with methode om dependencies te laden.

1
2
3
4
5
6
7
class << ActiveRecord::Base
  def concerned_with(*concerns)
    concerns.each do |concern|
      require_dependency "#{name.underscore}/#{concern}"
    end
  end
end

In het User model geef je aan wat geladen moet worden, zoals posting.

1
2
3
4
class User < ActiveRecord::Base
  concerned_with :validation, :states, :activation, :posting
  #...
end

In user/posting.rb heb je dan alleen de functionaliteit m.b.t. het posten van reacties.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class User
  # Creates new topic and post.
  # Only..
  #  - sets sticky/locked bits if you're a moderator or admin 
  #  - changes forum_id if you're an admin
  #
  def post(forum, attributes)
    attributes.symbolize_keys!
    Topic.new(attributes) do |topic|
      topic.forum = forum
      topic.user  = self
      revise_topic topic, attributes
    end
  end
 
 #...
end

Ik heb zelf nog geen oordeel over, ik moest in eerste instantie de code gewoon begrijpen. Het voordeel is dat je i.p.v. wat regels met require_dependency, je een enkele regel hebt met een duidelijke intentie. Je zit niet te denken in het linken van modules, maar in de verantwoordingen van het object. Dit is goed. Het is echter altijd wel even uitzoeken hoe dit soort oplossingen in elkaar zit.