starling 0.9.3 → 0.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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'