starling 0.9.3 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,205 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
2
+
3
+ require 'rubygems'
4
+ require 'fileutils'
5
+ require 'memcache'
6
+ require 'digest/md5'
7
+
8
+ require 'starling/server'
9
+
10
+ class StarlingServer::PersistentQueue
11
+ remove_const :SOFT_LOG_MAX_SIZE
12
+ SOFT_LOG_MAX_SIZE = 16 * 1024 # 16 KB
13
+ end
14
+
15
+ def safely_fork(&block)
16
+ # anti-race juice:
17
+ blocking = true
18
+ Signal.trap("USR1") { blocking = false }
19
+
20
+ pid = Process.fork(&block)
21
+
22
+ while blocking
23
+ sleep 0.1
24
+ end
25
+
26
+ pid
27
+ end
28
+
29
+ describe "StarlingServer" do
30
+ before do
31
+ @tmp_path = File.join(File.dirname(__FILE__), "tmp")
32
+
33
+ begin
34
+ Dir::mkdir(@tmp_path)
35
+ rescue Errno::EEXIST
36
+ end
37
+
38
+ @server_pid = safely_fork do
39
+ server = StarlingServer::Base.new(:host => '127.0.0.1',
40
+ :port => 22133,
41
+ :path => @tmp_path,
42
+ :logger => Logger.new(STDERR),
43
+ :log_level => Logger::FATAL)
44
+ Signal.trap("INT") {
45
+ server.stop
46
+ exit
47
+ }
48
+
49
+ Process.kill("USR1", Process.ppid)
50
+ server.run
51
+ end
52
+
53
+ @client = MemCache.new('127.0.0.1:22133')
54
+ end
55
+
56
+ it "should test if temp_path exists and is writeable" do
57
+ File.exist?(@tmp_path).should be_true
58
+ File.directory?(@tmp_path).should be_true
59
+ File.writable?(@tmp_path).should be_true
60
+ end
61
+
62
+ it "should set and get" do
63
+ v = rand((2**32)-1)
64
+ @client.get('test_set_and_get_one_entry').should be_nil
65
+ @client.set('test_set_and_get_one_entry', v)
66
+ @client.get('test_set_and_get_one_entry').should eql(v)
67
+ end
68
+
69
+ it "should expire entries" do
70
+ v = rand((2**32)-1)
71
+ @client.get('test_set_with_expiry').should be_nil
72
+ now = Time.now.to_i
73
+ @client.set('test_set_with_expiry', v + 2, now)
74
+ @client.set('test_set_with_expiry', v)
75
+ sleep(1.0)
76
+ @client.get('test_set_with_expiry').should eql(v)
77
+ end
78
+
79
+ it "should have age stat" do
80
+ now = Time.now.to_i
81
+ @client.set('test_age', 'nibbler')
82
+ sleep(1.0)
83
+ @client.get('test_age').should eql('nibbler')
84
+
85
+ stats = @client.stats['127.0.0.1:22133']
86
+ stats.has_key?('queue_test_age_age').should be_true
87
+ (stats['queue_test_age_age'] >= 1000).should be_true
88
+ end
89
+
90
+ it "should rotate log" do
91
+ log_rotation_path = File.join(@tmp_path, 'test_log_rotation')
92
+
93
+ Dir.glob("#{log_rotation_path}*").each do |file|
94
+ File.unlink(file) rescue nil
95
+ end
96
+ @client.get('test_log_rotation').should be_nil
97
+
98
+ v = 'x' * 8192
99
+
100
+ @client.set('test_log_rotation', v)
101
+ File.size(log_rotation_path).should eql(8207)
102
+ @client.get('test_log_rotation')
103
+
104
+ @client.get('test_log_rotation').should be_nil
105
+
106
+ @client.set('test_log_rotation', v)
107
+ @client.get('test_log_rotation').should eql(v)
108
+
109
+ File.size(log_rotation_path).should eql(1)
110
+ # rotated log should be erased after a successful roll.
111
+ Dir.glob("#{log_rotation_path}*").size.should eql(1)
112
+ end
113
+
114
+ it "should output statistics per server" do
115
+ stats = @client.stats
116
+ assert_kind_of Hash, stats
117
+ assert stats.has_key?('127.0.0.1:22133')
118
+
119
+ server_stats = stats['127.0.0.1:22133']
120
+
121
+ basic_stats = %w( bytes pid time limit_maxbytes cmd_get version
122
+ bytes_written cmd_set get_misses total_connections
123
+ curr_connections curr_items uptime get_hits total_items
124
+ rusage_system rusage_user bytes_read )
125
+
126
+ basic_stats.each do |stat|
127
+ server_stats.has_key?(stat).should be_true
128
+ end
129
+ end
130
+
131
+ it "should return valid response with unkown command" do
132
+ response = @client.add('blah', 1)
133
+ response.should eql("CLIENT_ERROR bad command line format\r\n")
134
+ end
135
+
136
+ it "should disconnect and reconnect again" do
137
+ v = rand(2**32-1)
138
+ @client.set('test_that_disconnecting_and_reconnecting_works', v)
139
+ @client.reset
140
+ @client.get('test_that_disconnecting_and_reconnecting_works').should eql(v)
141
+ end
142
+
143
+ it "should use epoll on linux" do
144
+ # this may take a few seconds.
145
+ # the point is to make sure that we're using epoll on Linux, so we can
146
+ # handle more than 1024 connections.
147
+
148
+ unless IO::popen("uname").read.chomp == "Linux"
149
+ pending "skipping epoll test: not on Linux"
150
+ end
151
+
152
+ fd_limit = IO::popen("bash -c 'ulimit -n'").read.chomp.to_i
153
+ unless fd_limit > 1024
154
+ pending "skipping epoll test: 'ulimit -n' = #{fd_limit}, need > 1024"
155
+ end
156
+
157
+ v = rand(2**32 - 1)
158
+ @client.set('test_epoll', v)
159
+
160
+ # we can't open 1024 connections to memcache from within this process,
161
+ # because we will hit ruby's 1024 fd limit ourselves!
162
+ pid1 = safely_fork do
163
+ unused_sockets = []
164
+ 600.times do
165
+ unused_sockets << TCPSocket.new("127.0.0.1", 22133)
166
+ end
167
+ Process.kill("USR1", Process.ppid)
168
+ sleep 90
169
+ end
170
+ pid2 = safely_fork do
171
+ unused_sockets = []
172
+ 600.times do
173
+ unused_sockets << TCPSocket.new("127.0.0.1", 22133)
174
+ end
175
+ Process.kill("USR1", Process.ppid)
176
+ sleep 90
177
+ end
178
+
179
+ begin
180
+ client = MemCache.new('127.0.0.1:22133')
181
+ client.get('test_epoll').should eql(v)
182
+ ensure
183
+ Process.kill("TERM", pid1)
184
+ Process.kill("TERM", pid2)
185
+ end
186
+ end
187
+
188
+ it "should raise error if queue collection is an invalid path" do
189
+ invalid_path = nil
190
+ while invalid_path.nil? || File.exist?(invalid_path)
191
+ invalid_path = File.join('/', Digest::MD5.hexdigest(rand(2**32-1).to_s)[0,8])
192
+ end
193
+
194
+ lambda {
195
+ StarlingServer::QueueCollection.new(invalid_path)
196
+ }.should raise_error(StarlingServer::InaccessibleQueuePath)
197
+ end
198
+
199
+ after do
200
+ Process.kill("INT", @server_pid)
201
+ Process.wait(@server_pid)
202
+ @client.reset
203
+ FileUtils.rm(Dir.glob(File.join(@tmp_path, '*')))
204
+ end
205
+ end
metadata CHANGED
@@ -1,66 +1,92 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: starling
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
5
- platform: ""
4
+ version: 0.9.8
5
+ platform: ruby
6
6
  authors:
7
7
  - Blaine Cook
8
+ - Chris Wanstrath
9
+ - Britt Selvitelle
10
+ - Glenn Rempe
11
+ - Abdul-Rahman Advany
8
12
  autorequire:
9
13
  bindir: bin
10
14
  cert_chain: []
11
15
 
12
- date: 2008-01-10 00:00:00 -08:00
16
+ date: 2008-08-26 00:00:00 -07:00
13
17
  default_executable:
14
- dependencies: []
15
-
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: memcache-client
21
+ type: :runtime
22
+ version_requirement:
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: "0"
28
+ version:
29
+ - !ruby/object:Gem::Dependency
30
+ name: SyslogLogger
31
+ type: :runtime
32
+ version_requirement:
33
+ version_requirements: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: "0"
38
+ version:
39
+ - !ruby/object:Gem::Dependency
40
+ name: eventmachine
41
+ type: :runtime
42
+ version_requirement:
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.12.0
48
+ version:
16
49
  description: Starling is a lightweight, transactional, distributed queue server
17
- email: blaine@twitter.com
50
+ email:
51
+ - blaine@twitter.com
52
+ - chris@ozmm.org
53
+ - abdulrahman@advany.com
18
54
  executables:
19
55
  - starling
56
+ - starling_top
20
57
  extensions: []
21
58
 
22
59
  extra_rdoc_files:
23
- - History.txt
24
- - License.txt
25
- - Manifest.txt
26
- - README.txt
27
- - website/index.txt
60
+ - README.rdoc
61
+ - CHANGELOG
62
+ - LICENSE
28
63
  files:
29
- - History.txt
30
- - License.txt
31
- - Manifest.txt
32
- - README.txt
64
+ - README.rdoc
65
+ - LICENSE
66
+ - CHANGELOG
33
67
  - Rakefile
34
- - bin/starling
35
- - config/hoe.rb
36
- - config/requirements.rb
37
- - lib/starling.rb
38
68
  - lib/starling/handler.rb
39
69
  - lib/starling/persistent_queue.rb
40
70
  - lib/starling/queue_collection.rb
41
- - lib/starling/runner.rb
71
+ - lib/starling/server_runner.rb
42
72
  - lib/starling/server.rb
43
- - script/destroy
44
- - script/generate
45
- - script/txt2html
46
- - setup.rb
47
- - tasks/deployment.rake
48
- - tasks/environment.rake
49
- - tasks/website.rake
50
- - test/test_helper.rb
51
- - test/test_persistent_queue.rb
52
- - test/test_starling.rb
53
- - website/index.html
54
- - website/index.txt
55
- - website/javascripts/rounded_corners_lite.inc.js
56
- - website/stylesheets/screen.css
57
- - website/template.rhtml
73
+ - lib/starling.rb
74
+ - etc/starling.redhat
75
+ - etc/starling.ubuntu
76
+ - etc/sample-config.yml
58
77
  has_rdoc: true
59
- homepage: http://starling.rubyforge.org
78
+ homepage: http://github.com/starling/starling/
60
79
  post_install_message:
61
80
  rdoc_options:
81
+ - --quiet
82
+ - --title
83
+ - starling documentation
84
+ - --opname
85
+ - index.html
86
+ - --line-numbers
62
87
  - --main
63
- - README.txt
88
+ - README.rdoc
89
+ - --inline-source
64
90
  require_paths:
65
91
  - lib
66
92
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -77,12 +103,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
103
  version:
78
104
  requirements: []
79
105
 
80
- rubyforge_project: starling
81
- rubygems_version: 0.9.5
106
+ rubyforge_project:
107
+ rubygems_version: 1.2.0
82
108
  signing_key:
83
109
  specification_version: 2
84
110
  summary: Starling is a lightweight, transactional, distributed queue server
85
111
  test_files:
86
- - test/test_helper.rb
87
- - test/test_persistent_queue.rb
88
- - test/test_starling.rb
112
+ - spec/starling_server_spec.rb
data/History.txt DELETED
@@ -1,3 +0,0 @@
1
- == 1.0.0 2007-11-02
2
-
3
- * Initial release
data/Manifest.txt DELETED
@@ -1,29 +0,0 @@
1
- History.txt
2
- License.txt
3
- Manifest.txt
4
- README.txt
5
- Rakefile
6
- bin/starling
7
- config/hoe.rb
8
- config/requirements.rb
9
- lib/starling.rb
10
- lib/starling/handler.rb
11
- lib/starling/persistent_queue.rb
12
- lib/starling/queue_collection.rb
13
- lib/starling/runner.rb
14
- lib/starling/server.rb
15
- script/destroy
16
- script/generate
17
- script/txt2html
18
- setup.rb
19
- tasks/deployment.rake
20
- tasks/environment.rake
21
- tasks/website.rake
22
- test/test_helper.rb
23
- test/test_persistent_queue.rb
24
- test/test_starling.rb
25
- website/index.html
26
- website/index.txt
27
- website/javascripts/rounded_corners_lite.inc.js
28
- website/stylesheets/screen.css
29
- website/template.rhtml
data/README.txt DELETED
@@ -1,42 +0,0 @@
1
- = Name
2
-
3
- Starling - a light weight server for reliable distributed message passing.
4
-
5
- = Synopsis
6
-
7
- # Start the Starling server as a daemonized process:
8
- starling -h 192.168.1.1 -d
9
-
10
- # Put messages onto a queue:
11
- require 'memcache'
12
- starling = MemCache.new('192.168.1.1:22122')
13
- starling.set('my_queue', 12345)
14
-
15
- # Get messages from the queue:
16
- require 'memcache'
17
- starling = MemCache.new('192.168.1.1:22122')
18
- loop { puts starling.get('my_queue') }
19
-
20
- # See the Starling documentation for more information.
21
-
22
- = Description
23
-
24
- Starling is a powerful but simple messaging server that enables reliable
25
- distributed queuing with an absolutely minimal overhead. It speaks the
26
- MemCache protocol for maximum cross-platform compatibility. Any language
27
- that speaks MemCache can take advantage of Starling's queue facilities.
28
-
29
- = Known Issues
30
-
31
- * Starling is "slow" as far as messaging systems are concerned. In practice,
32
- it's fast enough. If you'd like to help make it faster please do. Starting
33
- points would be to use an event-driven interface, and get rid of threading.
34
-
35
- = Authors
36
-
37
- Blaine Cook <romeda@gmail.com>
38
-
39
- = Copyright
40
-
41
- Starling - a light-weight server for reliable distributed message passing.
42
- Copyright 2007 Blaine Cook <blaine@twitter.com>, Twitter Inc.
data/config/hoe.rb DELETED
@@ -1,71 +0,0 @@
1
- require 'starling/server'
2
-
3
- AUTHOR = 'Blaine Cook' # can also be an array of Authors
4
- EMAIL = "blaine@twitter.com"
5
- DESCRIPTION = "Starling is a lightweight, transactional, distributed queue server"
6
- GEM_NAME = 'starling' # what ppl will type to install your gem
7
- RUBYFORGE_PROJECT = 'starling' # The unix name for your project
8
- HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
- DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
-
11
- @config_file = "~/.rubyforge/user-config.yml"
12
- @config = nil
13
- RUBYFORGE_USERNAME = "unknown"
14
- def rubyforge_username
15
- unless @config
16
- begin
17
- @config = YAML.load(File.read(File.expand_path(@config_file)))
18
- rescue
19
- puts <<-EOS
20
- ERROR: No rubyforge config file found: #{@config_file}
21
- Run 'rubyforge setup' to prepare your env for access to Rubyforge
22
- - See http://newgem.rubyforge.org/rubyforge.html for more details
23
- EOS
24
- exit
25
- end
26
- end
27
- RUBYFORGE_USERNAME.replace @config["username"]
28
- end
29
-
30
-
31
- REV = nil
32
- # UNCOMMENT IF REQUIRED:
33
- # REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
34
- VERS = StarlingServer::VERSION + (REV ? ".#{REV}" : "")
35
- RDOC_OPTS = ['--quiet', '--title', 'starling documentation',
36
- "--opname", "index.html",
37
- "--line-numbers",
38
- "--main", "README",
39
- "--inline-source"]
40
-
41
- class Hoe
42
- def extra_deps
43
- @extra_deps.reject! { |x| Array(x).first == 'hoe' }
44
- @extra_deps
45
- end
46
- end
47
-
48
- # Generate all the Rake tasks
49
- # Run 'rake -T' to see list of generated tasks (from gem root directory)
50
- hoe = Hoe.new(GEM_NAME, VERS) do |p|
51
- p.author = AUTHOR
52
- p.description = DESCRIPTION
53
- p.email = EMAIL
54
- p.summary = DESCRIPTION
55
- p.url = HOMEPATH
56
- p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
57
- p.test_globs = ["test/**/test_*.rb"]
58
- p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
59
-
60
- # == Optional
61
- p.changes = p.paragraphs_of("History.txt", 0..1).join("\\n\\n")
62
- #p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
63
-
64
- #p.spec_extras = {} # A hash of extra values to set in the gemspec.
65
-
66
- end
67
-
68
- CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
69
- PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
70
- hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
71
- hoe.rsync_args = '-av --delete --ignore-errors'