Compare commits

...

20 Commits

Author SHA1 Message Date
Denis Knauf 92060db994 More readable description for RobusServer-class. 2021-11-30 14:09:35 +01:00
Denis Knauf 0e90737ae1 ignore pkg and vi-tempfiles 2013-04-15 16:17:31 +02:00
Denis Knauf f09d6150dd Regenerate gemspec for version 0.0.3 2013-04-15 16:16:21 +02:00
Denis Knauf c34cc60ae6 Version bump to 0.0.3 2013-04-15 16:16:17 +02:00
Denis Knauf 5b7d63fb2d s = s removed 2013-04-15 16:11:26 +02:00
Denis Knauf 37ac8bb3db only display disregarded signals, if there are disregarded signals 2013-04-15 12:19:23 +02:00
Denis Knauf 960f3ef7a9 exception -> exit(2). unimplemented -> message+exit(1) 2013-04-15 12:13:23 +02:00
Denis Knauf d7edbb750e #loop was a bad idea. #run raises UnimplementedRun. on UnimplementedRun main will never retry. 2013-04-15 12:11:55 +02:00
Denis Knauf f11b7df104 Gemfile and gemspec generated 2013-04-15 12:06:24 +02:00
Denis Knauf 9551fbe35d translated (english). $stderr -> output (default $stderr). #run / #loop dummies (#loop will be called by #run in a loop, if #run not overwritten. SystemExit will be reraised. 2013-04-15 12:04:12 +02:00
Denis Knauf fc48ded7ba Rakefile updated. 2013-04-15 12:01:57 +02:00
Denis Knauf 56070055d8 this new at_exit is ready. new version! 2010-03-21 20:59:39 +01:00
Denis Knauf 5ef72caa6b at_exit added. use it to clean your dishes. 2010-03-21 20:58:42 +01:00
Denis Knauf 5169bee0ea little changes: metafiles 2010-03-20 23:22:53 +01:00
Denis Knauf e11976f9a2 More docs 2010-03-17 13:26:24 +01:00
Denis Knauf 899a1dd399 First comments for Retries and RobustServer. 2010-03-11 11:32:27 +01:00
Denis Knauf c992701299 Version 0.0.1. Only changes for gemcutter 2010-03-11 00:23:20 +01:00
Denis Knauf 0d4506941e Signalhandler mit Ausgabe. 2010-03-07 21:30:43 +01:00
Denis Knauf aa47581eb9 Signalhandler mit Puffer. 2010-03-07 19:30:33 +01:00
Denis Knauf c20b420d4a Default value fuer max=10 or range=10, if it will be nil. 2010-03-03 17:04:19 +01:00
8 changed files with 217 additions and 71 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.*.swp
pkg

View File

12
Gemfile Normal file
View File

@ -0,0 +1,12 @@
source "http://rubygems.org"
# Add dependencies to develop your gem here.
# Include everything needed to run rake, tests, features, etc.
group :development do
gem "shoulda"
gem "yard"
gem "rdoc"
gem "bundler"
gem "jeweler"
gem "simplecov"
end

46
Gemfile.lock Normal file
View File

@ -0,0 +1,46 @@
GEM
remote: http://rubygems.org/
specs:
activesupport (3.2.13)
i18n (= 0.6.1)
multi_json (~> 1.0)
bourne (1.4.0)
mocha (~> 0.13.2)
git (1.2.5)
i18n (0.6.1)
jeweler (1.8.4)
bundler (~> 1.0)
git (>= 1.2.5)
rake
rdoc
json (1.7.7)
metaclass (0.0.1)
mocha (0.13.3)
metaclass (~> 0.0.1)
multi_json (1.7.2)
rake (10.0.4)
rdoc (4.0.1)
json (~> 1.4)
shoulda (3.4.0)
shoulda-context (~> 1.0, >= 1.0.1)
shoulda-matchers (~> 1.0, >= 1.4.1)
shoulda-context (1.1.0)
shoulda-matchers (1.5.6)
activesupport (>= 3.0.0)
bourne (~> 1.3)
simplecov (0.7.1)
multi_json (~> 1.0)
simplecov-html (~> 0.7.1)
simplecov-html (0.7.1)
yard (0.8.5.2)
PLATFORMS
ruby
DEPENDENCIES
bundler
jeweler
rdoc
shoulda
simplecov
yard

View File

@ -1,57 +1,49 @@
# encoding: utf-8
require 'rubygems'
require 'bundler'
begin
Bundler.setup(:default, :development)
rescue Bundler::BundlerError => e
$stderr.puts e.message
$stderr.puts "Run `bundle install` to install missing gems"
exit e.status_code
end
require 'rake'
begin
require 'jeweler'
Jeweler::Tasks.new do |gem|
gem.name = "robustserver"
gem.summary = %Q{Robust Server}
gem.description = %Q{Protects your Server against SIGS and unplaned exceptions}
gem.email = "Denis.Knauf@gmail.com"
gem.homepage = "http://github.com/DenisKnauf/robustserver"
gem.authors = ["Denis Knauf"]
gem.files = ["AUTHORS", "README.md", "VERSION", "lib/**/*.rb", "test/**/*.rb"]
gem.require_paths = ["lib"]
end
Jeweler::GemcutterTasks.new
rescue LoadError
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
require 'jeweler'
Jeweler::Tasks.new do |gem|
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
gem.name = "robustserver"
gem.summary = %Q{Robust Server}
gem.description = %Q{Protects your Server against SIGS and rescues all exceptions.}
gem.email = "Denis.Knauf@gmail.com"
gem.homepage = "http://github.com/DenisKnauf/robustserver"
gem.authors = ["Denis Knauf"]
gem.files = %w[AUTHORS README.md VERSION lib/**/*.rb test/**/*.rb]
gem.require_paths = %w[lib]
# dependencies defined in Gemfile
end
Jeweler::RubygemsDotOrgTasks.new
require 'rake/testtask'
Rake::TestTask.new(:test) do |test|
test.libs << 'lib' << 'test' << 'ext'
test.pattern = 'test/**/*_test.rb'
test.libs << 'lib' << 'test'
test.pattern = 'test/**/test_*.rb'
test.verbose = true
end
begin
require 'rcov/rcovtask'
Rcov::RcovTask.new do |test|
test.libs << 'test'
test.pattern = 'test/**/*_test.rb'
test.verbose = true
end
rescue LoadError
task :rcov do
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
end
=begin
require 'rcov/rcovtask'
Rcov::RcovTask.new do |test|
test.libs << 'test'
test.pattern = 'test/**/test_*.rb'
test.verbose = true
test.rcov_opts << '--exclude "gems/*"'
end
task :test => :check_dependencies
=end
task :default => :test
require 'rake/rdoctask'
Rake::RDocTask.new do |rdoc|
if File.exist?('VERSION')
version = File.read('VERSION')
else
version = ""
end
rdoc.rdoc_dir = 'rdoc'
rdoc.title = "sbdb #{version}"
rdoc.rdoc_files.include('README*')
rdoc.rdoc_files.include('lib/**/*.rb')
end
require 'yard'
YARD::Rake::YardocTask.new

View File

@ -1 +1 @@
0.0.0
0.0.3

View File

@ -4,6 +4,7 @@ def Signal.signame s
when String then s
when Symbol then s.to_s
when Fixnum then list.invert[s]
else raise ArgumentError, "String, Symbol or Fixnum expected, not #{s.class}"
end
end
@ -12,6 +13,7 @@ def Signal.sig s
when Fixnum then s
when String then list[s]
when Symbol then list[s.to_s]
else raise ArgumentError, "String, Symbol or Fixnum expected, not #{s.class}"
end
end
@ -25,25 +27,65 @@ def Signal.[] s
when String then list[s]
when Symbol then list[s.to_s]
when Fixnum then list.invert[s]
else raise ArgumentError
else raise ArgumentError, "String, Symbol or Fixnum expected, not #{s.class}"
end
end
# Description
# ===========
#
# Counts retries ot something. If the retries are to often in a short time,
# you shouldn't retry again.
#
# Examples
# ========
#
# Strings aren't Integers and 2*"Text" will raise TypeError.
#
# retries = Retry.new 5, 1
# begin
# array_of_ints_and_some_strings.each do |i|
# puts 2*i
# end
# rescue TypeError
# retries.retry? and retry
# raise $!
# end
#
# Retry.new( 10, 30).run( ConnectionLost) do
# try_to_connect_to_db
# try_query
# end
class Retries
attr_accessor :max, :range
attr_reader :count, :last
def initialize max = 10, range = 10
@max, @range, @count, @last = max, range, 0, Time.now
# max: How many retries in range-time are allowed maximal.
# range: In which time-range are these retries are allowed
def initialize max = nil, range = nil
@max, @range, @count, @last = max || 10, range || 10, 0, Time.now
end
# Counts retries on every call.
# If these retries are to often - max times in range - it will return false
# else true.
# Now you can say: "I give up, to many retries, it seems it doesn't work."
def retry?
@count = @last + @range > Time.now ? @count + 1 : 1
@last = Time.now
@count < @max
end
def run ex, &e
# Automatical retrieing on raised exceptions in block.
# ex: Your expected Esception you will rescue. Default: Object, so realy everything.
#
# Example:
# Retries.new( 10, 30).run ArgumentError do something_do_which_could_raise_exception ArgumentError end
#
# This will retry maximal 10 times in 30 seconds to Call this block. But only rescues ArgumentError!
# Every other Error it will ignore and throws Exception. No retry.
def run ex = nil, &e
ex ||= Object
begin e.call *args
rescue ex
retries.retry? and retry
@ -51,17 +93,33 @@ class Retries
end
end
# Easy problem-handler for your Server.
#
# Problem: Your process should not crash, it should be available for anytime.
# If an exception will be raised, you have to handle it, or it will be shutdown abnormaly.
# Or if a signal tries to "kill" your program, your program will shutdown abnormaly, too.
#
# RobustServer handles any exception / kill, logs it and prevents the server to shutting down.
#
# For implementation a server, create a subclass of RobustServer and implement the *#run*-method.
# Anytime this *#run*-method returns or an exception will be raised, it will be rescued and run recalled.
# For initialization, you can override **#initialize**, but don't forget to call **super**.
class RobustServer
class UnimplementedRun <Exception
end
attr_reader :signals, :output
def self.main *argv
self.new( *argv).main
end
def initialize *p
def initialize *_
sh = method :signal_handler
@sigs = {
Signal[:INT] => sh, Signal[:HUP] => nil, Signal[:TERM] => sh,
Signal[:KILL] => sh, Signal[:USR1] => nil, Signal[:USR2] => nil
}
@signals, @output = [], $stderr
end
def trapping
@ -69,23 +127,42 @@ class RobustServer
end
def signal_handler s
@signal = s
output.puts [:signal, s, Signal[s]].inspect
@signals.push s unless @signals.include? s
end
def main max = nil, range = nil
retries = Retries.new max, range
trapping
$stderr.puts "Arbeit wird nun aufgenommen..."
output.puts "Running...."
begin
self.run
rescue SystemExit, Interrupt, SignalException
$stderr.puts "Das Beenden des Programms wurde angefordert. #{$!}"
rescue UnimplementedRun
output.puts $!.message
exit 1
rescue SystemExit
output.puts "Server interrupted by signal: #$!"
raise
rescue Interrupt, SignalException
output.puts "Server interrupted by signal: #$!"
exit 0
rescue Object
$stderr.puts [:rescue, $!, $!.class, $!.backtrace].inspect
output.puts [:rescue, $!, $!.class, $!.backtrace].inspect
retry if retries.retry?
$stderr.print "Zuviele Fehler in zu kurzer Zeit. Ich gebe auf und "
output.print "Too many errors in too short time. Give up: "
exit 2
end
ensure
output.puts "Disregarded signals: #{@signals.map(&Signal.method(:[])).join( ', ')}" unless @signals.empty?
trapping
$stderr.puts "Beende mich selbst."
self.at_exit
output.puts "Shutdown."
end
def run
raise UnimplementedRun, "Unimplemented #{self.class.name}#run."
end
def at_exit
end
end

View File

@ -1,40 +1,57 @@
# Generated by jeweler
# DO NOT EDIT THIS FILE DIRECTLY
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
s.name = %q{robustserver}
s.version = "0.0.0"
s.name = "robustserver"
s.version = "0.0.3"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Denis Knauf"]
s.date = %q{2010-03-02}
s.description = %q{Protects your Server against SIGS and unplaned exceptions}
s.email = %q{Denis.Knauf@gmail.com}
s.date = "2013-04-15"
s.description = "Protects your Server against SIGS and rescues all exceptions."
s.email = "Denis.Knauf@gmail.com"
s.extra_rdoc_files = [
"LICENSE",
"README.md"
"README.md"
]
s.files = [
"AUTHORS",
"README.md",
"VERSION",
"lib/robustserver.rb"
"VERSION",
"lib/robustserver.rb"
]
s.homepage = %q{http://github.com/DenisKnauf/robustserver}
s.rdoc_options = ["--charset=UTF-8"]
s.homepage = "http://github.com/DenisKnauf/robustserver"
s.require_paths = ["lib"]
s.rubygems_version = %q{1.3.5}
s.summary = %q{Robust Server}
s.rubygems_version = "1.8.23"
s.summary = "Robust Server"
if s.respond_to? :specification_version then
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 3
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_development_dependency(%q<shoulda>, [">= 0"])
s.add_development_dependency(%q<yard>, [">= 0"])
s.add_development_dependency(%q<rdoc>, [">= 0"])
s.add_development_dependency(%q<bundler>, [">= 0"])
s.add_development_dependency(%q<jeweler>, [">= 0"])
s.add_development_dependency(%q<simplecov>, [">= 0"])
else
s.add_dependency(%q<shoulda>, [">= 0"])
s.add_dependency(%q<yard>, [">= 0"])
s.add_dependency(%q<rdoc>, [">= 0"])
s.add_dependency(%q<bundler>, [">= 0"])
s.add_dependency(%q<jeweler>, [">= 0"])
s.add_dependency(%q<simplecov>, [">= 0"])
end
else
s.add_dependency(%q<shoulda>, [">= 0"])
s.add_dependency(%q<yard>, [">= 0"])
s.add_dependency(%q<rdoc>, [">= 0"])
s.add_dependency(%q<bundler>, [">= 0"])
s.add_dependency(%q<jeweler>, [">= 0"])
s.add_dependency(%q<simplecov>, [">= 0"])
end
end