rsense-server 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/Gemfile +14 -0
  4. data/Guardfile +5 -0
  5. data/LICENSE.txt +1 -0
  6. data/README.md +51 -0
  7. data/Rakefile +9 -0
  8. data/bin/_rsense.rb +115 -0
  9. data/config/puma.rb +2 -0
  10. data/lib/rsense/server/code.rb +38 -0
  11. data/lib/rsense/server/command/completion_result.rb +11 -0
  12. data/lib/rsense/server/command/special_meth.rb +18 -0
  13. data/lib/rsense/server/command/type_inference_method.rb +24 -0
  14. data/lib/rsense/server/command.rb +239 -0
  15. data/lib/rsense/server/config.rb +70 -0
  16. data/lib/rsense/server/gem_path.rb +18 -0
  17. data/lib/rsense/server/listeners/find_definition_event_listener.rb +91 -0
  18. data/lib/rsense/server/listeners/where_event_listener.rb +39 -0
  19. data/lib/rsense/server/load_path.rb +62 -0
  20. data/lib/rsense/server/options.rb +85 -0
  21. data/lib/rsense/server/parser.rb +17 -0
  22. data/lib/rsense/server/path_info.rb +17 -0
  23. data/lib/rsense/server/project.rb +24 -0
  24. data/lib/rsense/server/version.rb +5 -0
  25. data/lib/rsense/server.rb +18 -0
  26. data/rsense-server.gemspec +35 -0
  27. data/spec/fixtures/config_fixture/.rsense +4 -0
  28. data/spec/fixtures/deeply/nested/thing.rb +0 -0
  29. data/spec/fixtures/find_def_sample.json +10 -0
  30. data/spec/fixtures/sample.json +10 -0
  31. data/spec/fixtures/test_gem/.gitignore +22 -0
  32. data/spec/fixtures/test_gem/Gemfile +4 -0
  33. data/spec/fixtures/test_gem/LICENSE.txt +22 -0
  34. data/spec/fixtures/test_gem/README.md +29 -0
  35. data/spec/fixtures/test_gem/Rakefile +2 -0
  36. data/spec/fixtures/test_gem/lib/sample/version.rb +3 -0
  37. data/spec/fixtures/test_gem/lib/sample.rb +16 -0
  38. data/spec/fixtures/test_gem/sample.gemspec +23 -0
  39. data/spec/fixtures/test_gem/test.json +10 -0
  40. data/spec/rsense/server/code_spec.rb +44 -0
  41. data/spec/rsense/server/command/special_meth_spec.rb +23 -0
  42. data/spec/rsense/server/command_spec.rb +108 -0
  43. data/spec/rsense/server/config_spec.rb +27 -0
  44. data/spec/rsense/server/gem_path_spec.rb +16 -0
  45. data/spec/rsense/server/load_path_spec.rb +63 -0
  46. data/spec/rsense/server/options_spec.rb +33 -0
  47. data/spec/rsense/server/path_info_spec.rb +11 -0
  48. data/spec/rsense/server/project_spec.rb +18 -0
  49. data/spec/rsense/server_spec.rb +7 -0
  50. data/spec/spec_helper.rb +16 -0
  51. data/vendor/gems/puma-2.8.2-java/COPYING +55 -0
  52. data/vendor/gems/puma-2.8.2-java/DEPLOYMENT.md +92 -0
  53. data/vendor/gems/puma-2.8.2-java/Gemfile +17 -0
  54. data/vendor/gems/puma-2.8.2-java/History.txt +532 -0
  55. data/vendor/gems/puma-2.8.2-java/LICENSE +26 -0
  56. data/vendor/gems/puma-2.8.2-java/Manifest.txt +68 -0
  57. data/vendor/gems/puma-2.8.2-java/README.md +251 -0
  58. data/vendor/gems/puma-2.8.2-java/Rakefile +158 -0
  59. data/vendor/gems/puma-2.8.2-java/bin/puma +10 -0
  60. data/vendor/gems/puma-2.8.2-java/bin/puma-wild +17 -0
  61. data/vendor/gems/puma-2.8.2-java/bin/pumactl +12 -0
  62. data/vendor/gems/puma-2.8.2-java/docs/config.md +0 -0
  63. data/vendor/gems/puma-2.8.2-java/docs/nginx.md +80 -0
  64. data/vendor/gems/puma-2.8.2-java/docs/signals.md +42 -0
  65. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/PumaHttp11Service.java +17 -0
  66. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/ext_help.h +15 -0
  67. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/extconf.rb +8 -0
  68. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser.c +1225 -0
  69. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser.h +64 -0
  70. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser.java.rl +161 -0
  71. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser.rl +146 -0
  72. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser_common.rl +54 -0
  73. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/io_buffer.c +155 -0
  74. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/mini_ssl.c +195 -0
  75. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/org/jruby/puma/Http11.java +225 -0
  76. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/org/jruby/puma/Http11Parser.java +488 -0
  77. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/org/jruby/puma/MiniSSL.java +289 -0
  78. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/puma_http11.c +491 -0
  79. data/vendor/gems/puma-2.8.2-java/lib/puma/accept_nonblock.rb +23 -0
  80. data/vendor/gems/puma-2.8.2-java/lib/puma/app/status.rb +59 -0
  81. data/vendor/gems/puma-2.8.2-java/lib/puma/binder.rb +298 -0
  82. data/vendor/gems/puma-2.8.2-java/lib/puma/capistrano.rb +86 -0
  83. data/vendor/gems/puma-2.8.2-java/lib/puma/cli.rb +587 -0
  84. data/vendor/gems/puma-2.8.2-java/lib/puma/client.rb +289 -0
  85. data/vendor/gems/puma-2.8.2-java/lib/puma/cluster.rb +389 -0
  86. data/vendor/gems/puma-2.8.2-java/lib/puma/compat.rb +18 -0
  87. data/vendor/gems/puma-2.8.2-java/lib/puma/configuration.rb +377 -0
  88. data/vendor/gems/puma-2.8.2-java/lib/puma/const.rb +165 -0
  89. data/vendor/gems/puma-2.8.2-java/lib/puma/control_cli.rb +251 -0
  90. data/vendor/gems/puma-2.8.2-java/lib/puma/daemon_ext.rb +25 -0
  91. data/vendor/gems/puma-2.8.2-java/lib/puma/delegation.rb +11 -0
  92. data/vendor/gems/puma-2.8.2-java/lib/puma/detect.rb +4 -0
  93. data/vendor/gems/puma-2.8.2-java/lib/puma/events.rb +130 -0
  94. data/vendor/gems/puma-2.8.2-java/lib/puma/io_buffer.rb +7 -0
  95. data/vendor/gems/puma-2.8.2-java/lib/puma/java_io_buffer.rb +45 -0
  96. data/vendor/gems/puma-2.8.2-java/lib/puma/jruby_restart.rb +83 -0
  97. data/vendor/gems/puma-2.8.2-java/lib/puma/minissl.rb +148 -0
  98. data/vendor/gems/puma-2.8.2-java/lib/puma/null_io.rb +34 -0
  99. data/vendor/gems/puma-2.8.2-java/lib/puma/puma_http11.jar +0 -0
  100. data/vendor/gems/puma-2.8.2-java/lib/puma/rack_default.rb +7 -0
  101. data/vendor/gems/puma-2.8.2-java/lib/puma/rack_patch.rb +45 -0
  102. data/vendor/gems/puma-2.8.2-java/lib/puma/reactor.rb +183 -0
  103. data/vendor/gems/puma-2.8.2-java/lib/puma/runner.rb +146 -0
  104. data/vendor/gems/puma-2.8.2-java/lib/puma/server.rb +801 -0
  105. data/vendor/gems/puma-2.8.2-java/lib/puma/single.rb +102 -0
  106. data/vendor/gems/puma-2.8.2-java/lib/puma/tcp_logger.rb +32 -0
  107. data/vendor/gems/puma-2.8.2-java/lib/puma/thread_pool.rb +185 -0
  108. data/vendor/gems/puma-2.8.2-java/lib/puma/util.rb +9 -0
  109. data/vendor/gems/puma-2.8.2-java/lib/puma.rb +14 -0
  110. data/vendor/gems/puma-2.8.2-java/lib/rack/handler/puma.rb +66 -0
  111. data/vendor/gems/puma-2.8.2-java/puma.gemspec +55 -0
  112. data/vendor/gems/puma-2.8.2-java/test/test_app_status.rb +92 -0
  113. data/vendor/gems/puma-2.8.2-java/test/test_cli.rb +173 -0
  114. data/vendor/gems/puma-2.8.2-java/test/test_config.rb +26 -0
  115. data/vendor/gems/puma-2.8.2-java/test/test_http10.rb +27 -0
  116. data/vendor/gems/puma-2.8.2-java/test/test_http11.rb +144 -0
  117. data/vendor/gems/puma-2.8.2-java/test/test_integration.rb +165 -0
  118. data/vendor/gems/puma-2.8.2-java/test/test_iobuffer.rb +38 -0
  119. data/vendor/gems/puma-2.8.2-java/test/test_minissl.rb +25 -0
  120. data/vendor/gems/puma-2.8.2-java/test/test_null_io.rb +31 -0
  121. data/vendor/gems/puma-2.8.2-java/test/test_persistent.rb +238 -0
  122. data/vendor/gems/puma-2.8.2-java/test/test_puma_server.rb +323 -0
  123. data/vendor/gems/puma-2.8.2-java/test/test_rack_handler.rb +10 -0
  124. data/vendor/gems/puma-2.8.2-java/test/test_rack_server.rb +141 -0
  125. data/vendor/gems/puma-2.8.2-java/test/test_tcp_rack.rb +42 -0
  126. data/vendor/gems/puma-2.8.2-java/test/test_thread_pool.rb +156 -0
  127. data/vendor/gems/puma-2.8.2-java/test/test_unix_socket.rb +39 -0
  128. data/vendor/gems/puma-2.8.2-java/test/test_ws.rb +89 -0
  129. data/vendor/gems/puma-2.8.2-java/tools/jungle/README.md +9 -0
  130. data/vendor/gems/puma-2.8.2-java/tools/jungle/init.d/README.md +54 -0
  131. data/vendor/gems/puma-2.8.2-java/tools/jungle/init.d/puma +332 -0
  132. data/vendor/gems/puma-2.8.2-java/tools/jungle/init.d/run-puma +3 -0
  133. data/vendor/gems/puma-2.8.2-java/tools/jungle/upstart/README.md +61 -0
  134. data/vendor/gems/puma-2.8.2-java/tools/jungle/upstart/puma-manager.conf +31 -0
  135. data/vendor/gems/puma-2.8.2-java/tools/jungle/upstart/puma.conf +63 -0
  136. data/vendor/gems/puma-2.8.2-java/tools/trickletest.rb +45 -0
  137. metadata +389 -0
@@ -0,0 +1,108 @@
1
+ require "pathname"
2
+ require "json"
3
+ require_relative "../../spec_helper.rb"
4
+
5
+ describe Rsense::Server::Command::Command do
6
+ before do
7
+ @json_path = Pathname.new("spec/fixtures/sample.json")
8
+ @json = JSON.parse(@json_path.read)
9
+ @options = Rsense::Server::Options.new(@json)
10
+ end
11
+
12
+ it "can be initialized" do
13
+ Rsense::Server::Command::Command.new(@options)
14
+ end
15
+
16
+ describe "finding dependencies" do
17
+ Dependency = Struct.new(:name, :full_name, :path)
18
+ Project = Struct.new(:load_path, :gem_path, :stubs)
19
+
20
+ before do
21
+ @dependencies = [
22
+ Dependency.new("foo", "foo.1.2", ["/foo/bar/baz"]),
23
+ Dependency.new("scooby", "scooby.1.2", ["/scooby/dooby/doo"])
24
+ ]
25
+ @loadpath = [
26
+ "spec/fixtures",
27
+ "/bada/bing/bang/boom"
28
+ ]
29
+ @gempath = [
30
+ "/fee/fi/fo/fum",
31
+ "/i/smell/the/blood/of/an/englishman"
32
+ ]
33
+ @stubs = Dir.glob(Rsense::BUILTIN.join("**/*.rb"))
34
+ @project = Project.new(@loadpath, @gempath, @stubs)
35
+ @command = Rsense::Server::Command::Command.new(@options)
36
+ end
37
+
38
+ it "finds the dependency" do
39
+ matches = @command.dependency_matches(@dependencies, "foo")
40
+ matches.first.to_s.must_match(/baz/)
41
+ end
42
+
43
+ it "does not find a dependency which is not there" do
44
+ @command.dependency_matches(@dependencies, "scoby").must_be_empty
45
+ end
46
+
47
+ it "finds the path in the load_path" do
48
+ @command.load_path_matches(@project, "def_sample").size.must_equal(1)
49
+ end
50
+
51
+ it "gathers the lib directory paths from the dependencies" do
52
+ deps = [
53
+ Dependency.new("foo", "foo.1.2", ["/foo/lib/foo.rb"]),
54
+ Dependency.new("scooby", "scooby.1.2", ["/scooby/lib/scooby.rb"])
55
+ ]
56
+ paths = @command.dependency_paths(deps)
57
+ paths.size.must_equal(2)
58
+ paths.first.to_s.must_match(/\/foo\/lib$/)
59
+ end
60
+
61
+ it "finds a deeply nested path" do
62
+ dep_paths = [Pathname.new("spec/fixtures/deeply"), Pathname.new("foo/bar/baz")]
63
+ matches = @command.deep_check(@gempath, dep_paths, "thing")
64
+ matches.first.must_match(/nested/)
65
+ matches.size.must_equal(1)
66
+ end
67
+
68
+ it "finds the stubs" do
69
+ matches = @command.stub_matches(@project, "_builtin")
70
+ matches.size.must_equal(1)
71
+ end
72
+
73
+ it "finds the _builtin" do
74
+ @command.builtin_path(@project).to_s.must_match(/_builtin/)
75
+ end
76
+ end
77
+
78
+ describe "completions" do
79
+ require 'json'
80
+
81
+ class Testscript
82
+ attr_accessor :json_path, :json, :options, :command, :name, :file, :project
83
+
84
+ def initialize
85
+ @json_path = Pathname.new("spec/fixtures/test_gem/test.json").expand_path
86
+ @json = JSON.parse(@json_path.read)
87
+ @options = Rsense::Server::Options.new(@json)
88
+ @command = Rsense::Server::Command::Command.new(@options)
89
+ @name = "sample"
90
+ @file = @options.project_path
91
+ @project = Rsense::Server::Project.new(@name, @file)
92
+ end
93
+
94
+ def code_complete
95
+ @command.code_completion(@options.file, @options.location)
96
+ end
97
+ end
98
+
99
+ before do
100
+ @test = Testscript.new
101
+ end
102
+
103
+ it "returns completions" do
104
+ @test.code_complete.size.must_equal(51)
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,27 @@
1
+ require "filetree"
2
+ require_relative "../../spec_helper"
3
+
4
+ describe Rsense::Server::Config do
5
+ before do
6
+ @path = "spec/fixtures/config_fixture"
7
+ @conf_path = FileTree.new("spec/fixtures/config_fixture/.rsense").expand_path
8
+ @config = Rsense::Server::Config.new
9
+ end
10
+
11
+ it "searches for a config file" do
12
+ search = @config.search(@path)
13
+ search.to_s.must_match(/spec\/fixtures\/config_fixture\/\.rsense/)
14
+ @config.searched.size.must_equal(1)
15
+ end
16
+
17
+ it "sets the port" do
18
+ options = @config.options(@conf_path)
19
+ @config.port.must_equal(123456)
20
+ end
21
+
22
+ it "sets ignores" do
23
+ options = @config.options(@conf_path)
24
+ @config.ignores.must_include(".foo")
25
+ @config.ignores.must_include(".bar")
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ require_relative "../../spec_helper.rb"
2
+
3
+ describe Rsense::Server::GemPath do
4
+
5
+ it "returns the list of Gem paths" do
6
+ Rsense::Server::GemPath.stub :fetch, ["/path/to/the/gems"] do
7
+ Rsense::Server::GemPath.paths.first.must_match(/\/path\/to\/the\/gems/)
8
+ end
9
+ end
10
+
11
+ it "excludes paths inside jruby\'s jars" do
12
+ Rsense::Server::GemPath.stub :fetch, ["file: file in a jar"] do
13
+ Rsense::Server::GemPath.paths.wont_include("file: file in a jar")
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,63 @@
1
+ require "pathname"
2
+ require_relative "../../spec_helper.rb"
3
+
4
+ describe Rsense::Server::LoadPath do
5
+ it "lists loads paths" do
6
+ Rsense::Server::LoadPath.stub :fetch,["/some/path/to/load"] do
7
+ Rsense::Server::LoadPath.paths.first.must_match(/\/some\/path\/to\/load/)
8
+ end
9
+ end
10
+
11
+ it "does not list paths inside a jar" do
12
+ Rsense::Server::LoadPath.stub :fetch, ["file:path/in/jar"] do
13
+ Rsense::Server::LoadPath.paths.wont_include("file:path/in/jar")
14
+ end
15
+ end
16
+
17
+ describe "with project" do
18
+ ProjectMock = Struct.new(:path)
19
+
20
+ before do
21
+ @proj_path = "spec/fixtures/load_path_fixture"
22
+ @project = ProjectMock.new(@proj_path)
23
+ end
24
+
25
+ it "checks for a Gemfile.lock" do
26
+ Rsense::Server::LoadPath.find_gemfile(@project.path).to_s.must_match(/Gemfile/)
27
+ end
28
+
29
+ it "checks paths for correct version" do
30
+ fake_paths = ["1", "2", "3"]
31
+ checked = Rsense::Server::LoadPath.check_version(fake_paths, "2")
32
+ checked.size.must_equal(1)
33
+ checked.must_include("2")
34
+ checked.wont_include("1")
35
+ checked.wont_include("3")
36
+ end
37
+
38
+ it "returns a list of Gems" do
39
+ class SpecMock
40
+ def name
41
+ "mock"
42
+ end
43
+
44
+ def version
45
+ "2"
46
+ end
47
+ end
48
+
49
+ lfile = Object.new
50
+
51
+ def lfile.specs
52
+ [SpecMock.new]
53
+ end
54
+
55
+ Gem.stub :find_files, ["/stubbed/path-2"] do
56
+ ret_gems = Rsense::Server::LoadPath.gem_info(lfile).first
57
+ ret_gems.name.must_match(/mock/)
58
+ ret_gems.full_name.must_match(/mock-2/)
59
+ ret_gems.path.first.must_match(/stubbed/)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,33 @@
1
+ require "pathname"
2
+ require "json"
3
+ require_relative "../../spec_helper"
4
+
5
+ describe Rsense::Server::Options do
6
+ before do
7
+ @json_path = Pathname.new("spec/fixtures/sample.json")
8
+ @json = JSON.parse(@json_path.read)
9
+ @options = Rsense::Server::Options.new(@json)
10
+ end
11
+
12
+ it "has a command" do
13
+ @options.command.must_match(/code_completion/)
14
+ end
15
+
16
+ it "has a project path" do
17
+ @options.project_path.to_s.must_match(/code/)
18
+ @options.project_path.class.must_equal(Pathname)
19
+ end
20
+
21
+ it "has code" do
22
+ @options.code.must_match(/def/)
23
+ end
24
+
25
+ it "has a location" do
26
+ @options.location["row"].must_equal(2)
27
+ @options.location["column"].must_equal(10)
28
+ end
29
+
30
+ it "has a file" do
31
+ @options.file.to_s.must_match(/rsense\.rb/)
32
+ end
33
+ end
@@ -0,0 +1,11 @@
1
+ require_relative "../../spec_helper.rb"
2
+
3
+ describe Rsense::Server::PathInfo do
4
+ it "knows where its home is" do
5
+ Rsense::Server::PathInfo::RSENSE_SERVER_HOME.to_s.must_match(/rsense-server$/)
6
+ end
7
+
8
+ it "knows where to find the bin file" do
9
+ Rsense::Server::PathInfo.bin_path.to_s.must_match(/rsense-server\/bin\/_rsense.rb$/)
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ require_relative "../../spec_helper"
2
+
3
+ describe Rsense::Server::Project do
4
+ before do
5
+ @project = Rsense::Server::Project.new(__FILE__, File.dirname(__FILE__))
6
+ end
7
+
8
+ it "has stubs" do
9
+ stubs = @project.stubs.select { |e| e.to_s =~ /_builtin/ }
10
+ stubs.size.must_equal(1)
11
+ end
12
+
13
+ it "tracks loaded features" do
14
+ @project.loaded << "feature"
15
+ @project.loaded?("feature").must_equal(true)
16
+ @project.loaded?("different").must_equal(false)
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ require_relative "../spec_helper"
2
+
3
+ describe Rsense::Server do
4
+ it "loads" do
5
+ Rsense::Server.class.must_equal Module
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ require "minitest/autorun"
2
+ require "minitest/reporters"
3
+ Minitest::Reporters.use!
4
+
5
+ require "rsense-core"
6
+
7
+ require_relative "../lib/rsense/server/command.rb"
8
+ require_relative "../lib/rsense/server/gem_path.rb"
9
+ require_relative "../lib/rsense/server/load_path.rb"
10
+ require_relative "../lib/rsense/server/options.rb"
11
+ require_relative "../lib/rsense/server/code.rb"
12
+ require_relative "../lib/rsense/server.rb"
13
+ require_relative "../lib/rsense/server/path_info.rb"
14
+ require_relative "../lib/rsense/server/command/special_meth.rb"
15
+ require_relative "../lib/rsense/server/project.rb"
16
+ require_relative "../lib/rsense/server/config.rb"
@@ -0,0 +1,55 @@
1
+ Mongrel Web Server (Mongrel) is copyrighted free software by Zed A. Shaw
2
+ <zedshaw at zedshaw dot com> You can redistribute it and/or modify it under
3
+ either the terms of the GPL or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise make them
13
+ Freely Available, such as by posting said modifications to Usenet or an
14
+ equivalent medium, or by allowing the author to include your
15
+ modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) rename any non-standard executables so the names do not conflict with
21
+ standard executables, which must also be provided.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or executable
26
+ form, provided that you do at least ONE of the following:
27
+
28
+ a) distribute the executables and library files of the software,
29
+ together with instructions (in the manual page or equivalent) on where
30
+ to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of the
33
+ software.
34
+
35
+ c) give non-standard executables non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under this terms.
43
+
44
+ 5. The scripts and library files supplied as input to or produced as
45
+ output from the software do not automatically fall under the
46
+ copyright of the software, but belong to whomever generated them,
47
+ and may be sold commercially, and may be aggregated with this
48
+ software.
49
+
50
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
51
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
52
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53
+ PURPOSE.
54
+
55
+
@@ -0,0 +1,92 @@
1
+ # Deployment engineering for puma
2
+
3
+ Puma is software that is expected to be run in a deployed environment eventually.
4
+ You can centainly use it as your dev server only, but most people look to use
5
+ it in their production deployments as well.
6
+
7
+ To that end, this is meant to serve as a foundation of wisdom how to do that
8
+ in a way that increases happiness and decreases downtime.
9
+
10
+ ## Specifying puma
11
+
12
+ Most people want to do this by putting `gem "puma"` into their Gemfile, so we'll
13
+ go ahead and assume that. Go add it now... we'll wait.
14
+
15
+
16
+ Welcome back!
17
+
18
+ ## Single vs Cluster mode
19
+
20
+ Puma was originally concieved as a thread-only webserver, but grew the ability to
21
+ also use processes in version 2.
22
+
23
+ Here are some rules of thumb:
24
+
25
+ ### MRI
26
+
27
+ * Use cluster mode and set the number of workers to 1.5x the number of cpu cores
28
+ in the machine, minimum 2.
29
+ * Set the number of threads to desired concurrent requests / number of workers.
30
+ Puma defaults to 8 and thats a decent number.
31
+
32
+ #### Migrating from Unicorn
33
+
34
+ * If you're migrating from unicorn though, here are some settings to start with:
35
+ * Set workers to half the number of unicorn workers you're using
36
+ * Set threads to 2
37
+ * Enjoy 50% memory savings
38
+ * As you grow more confident in the thread safety of your app, you can tune the
39
+ workers down and the threads up.
40
+
41
+ #### Worker utilization
42
+
43
+ **How do you know if you're got enough (or too many workers)?**
44
+
45
+ A good question. Due to MRI's GIL, only one thread can be executing at a time.
46
+ But since so many apps are waiting on IO from DBs, etc., they can utilize threads
47
+ to make better use of the process.
48
+
49
+ The rule of thumb is you never want processes that are pegged all the time. This
50
+ means that there is more work to do that the process can get through. On the other
51
+ hand, if you have processes that sit around doing nothing, then they're just eating
52
+ up resources.
53
+
54
+ Watching your CPU utilization over time and aim for about 70% on average. This means
55
+ you've got capacity still but aren't starving threads.
56
+
57
+ ## Daemonizing
58
+
59
+ I prefer to not daemonize my servers and use something like `runit` or `upstrart` to
60
+ monitor them as child processes. This gives them fast response to crashes and
61
+ makes it easy to figure out what is going on. Additionally, unlike `unicorn`,
62
+ puma does not require daemonization to do zero-downtime restarts.
63
+
64
+ I see people using daemonization because they start puma directly via capistrano
65
+ task and thus want it to live on past the `cap deploy`. To this people I said:
66
+ You need to be using a process monitor. Nothing is making sure puma stays up in
67
+ this scenario! You're just waiting for something weird to happen, puma to die,
68
+ and to get paged at 3am. Do yourself a favor, at least the process monitoring
69
+ your OS comes with, be it `sysvinit`, `upstart`, or `systemd`. Or branch out
70
+ and use `runit` or hell, even `monit`.
71
+
72
+ ## Restarting
73
+
74
+ You probably will want to deploy some new code at some point, and you'd like
75
+ puma to start running that new code. Minimizing the amount of time the server
76
+ is unavailable would be nice as well. Here's how to do it:
77
+
78
+ 1. Don't use `preload!`. This dirties the master process and means it will have
79
+ to shutdown all the workers and re-exec itself to get your new code, which means
80
+ much higher waiting around for things to load.
81
+
82
+ 1. Use `prune_bundler`. This makes it so that the cluster master will detach itself
83
+ from a Bundler context on start. This allows the cluster workers to load your app
84
+ and start a brand new Bundler context within the worker only. This means your
85
+ master remains pristine and can live on between new releases of your code.
86
+
87
+ 1. Use phased-restart (`SIGUSR1` or `pumactl phased-restart`). This tells the master
88
+ to kill off one worker at a time and restart them in your new code. This minimizes
89
+ downtime and staggers the restart nicely. **WARNING** This means that both your
90
+ old code and your new code will be running concurrently. Most deployment solutions
91
+ already cause that, but it's worth warning you about it again. Be careful with your
92
+ migrations, etc!
@@ -0,0 +1,17 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "hoe"
4
+ gem "hoe-git"
5
+ gem "hoe-ignore"
6
+ gem "rdoc"
7
+ gem "rake-compiler"
8
+ gem "rack"
9
+
10
+ gem 'minitest', '~> 4.0'
11
+
12
+ gem "jruby-openssl", :platform => "jruby"
13
+
14
+ platforms :rbx do
15
+ gem 'rubysl', '~> 2.0'
16
+ end
17
+