spring_standalone 0.1.13

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.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +418 -0
  4. data/bin/spring_sa +49 -0
  5. data/lib/spring_standalone/application.rb +367 -0
  6. data/lib/spring_standalone/application/boot.rb +19 -0
  7. data/lib/spring_standalone/application_manager.rb +141 -0
  8. data/lib/spring_standalone/binstub.rb +13 -0
  9. data/lib/spring_standalone/boot.rb +10 -0
  10. data/lib/spring_standalone/client.rb +48 -0
  11. data/lib/spring_standalone/client/binstub.rb +198 -0
  12. data/lib/spring_standalone/client/command.rb +18 -0
  13. data/lib/spring_standalone/client/help.rb +62 -0
  14. data/lib/spring_standalone/client/rails.rb +34 -0
  15. data/lib/spring_standalone/client/run.rb +232 -0
  16. data/lib/spring_standalone/client/server.rb +18 -0
  17. data/lib/spring_standalone/client/status.rb +30 -0
  18. data/lib/spring_standalone/client/stop.rb +22 -0
  19. data/lib/spring_standalone/client/version.rb +11 -0
  20. data/lib/spring_standalone/command_wrapper.rb +82 -0
  21. data/lib/spring_standalone/commands.rb +50 -0
  22. data/lib/spring_standalone/commands/rake.rb +30 -0
  23. data/lib/spring_standalone/configuration.rb +58 -0
  24. data/lib/spring_standalone/env.rb +116 -0
  25. data/lib/spring_standalone/errors.rb +36 -0
  26. data/lib/spring_standalone/failsafe_thread.rb +14 -0
  27. data/lib/spring_standalone/json.rb +626 -0
  28. data/lib/spring_standalone/process_title_updater.rb +65 -0
  29. data/lib/spring_standalone/server.rb +150 -0
  30. data/lib/spring_standalone/sid.rb +42 -0
  31. data/lib/spring_standalone/version.rb +3 -0
  32. data/lib/spring_standalone/watcher.rb +30 -0
  33. data/lib/spring_standalone/watcher/abstract.rb +117 -0
  34. data/lib/spring_standalone/watcher/polling.rb +98 -0
  35. metadata +106 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b509c5f6550de465547a6880c5284ee413c0ddfede609f09d3383380f28ce63f
4
+ data.tar.gz: fd7307b1d085def8d17492fc670dc0515520d779fb88d49ba7d3c0331fb1c5fe
5
+ SHA512:
6
+ metadata.gz: 79ee1082ca2b5c8a5eeee4d470d85a0ecc2e2ef6fb0a450897a49ca2977461966f789869b61e82f474fefd18455a3793ef1bada33a41038df0dcd747a3af6e41
7
+ data.tar.gz: 5607c8a473ce4e62ba03c11e57f19f5d29600d26b188dedb38d9589cac2702d5368c440acd17417876d8a7d96971ed3292ba5582d8303da00d18a6ee1d9f0adc
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012-2017 Jon Leighton
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,418 @@
1
+ # SpringStandalone
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/spring_standalone.svg)](http://badge.fury.io/rb/spring_standalone)
4
+
5
+ SpringStandalone Standalone is a ruby application preloader based on SpringStandalone, a Rails
6
+ application preloader. It speeds up development by
7
+ keeping your application running in the background so you don't need to
8
+ boot it every time you run your application commands.
9
+
10
+ ## Features
11
+
12
+ * Totally automatic; no need to explicitly start and stop the background process
13
+ * Reloads your application code on each run
14
+ * Restarts your application when configs / initializers / gem
15
+ dependencies are changed
16
+
17
+ ## Compatibility
18
+
19
+ * Ruby versions: MRI 2.5, MRI 2.6
20
+
21
+ SpringStandalone Standalone makes extensive use of `Process.fork` (inherited from SpringStandalone
22
+ gem), so won't be able to
23
+ provide a speed up on platforms which don't support forking (Windows, JRuby).
24
+
25
+ ## Walkthrough
26
+
27
+ ### Setup
28
+
29
+ Add SpringStandalone to your Gemfile:
30
+
31
+ ``` ruby
32
+ gem "spring_standalone", group: :development
33
+ ```
34
+
35
+ (Note: using `gem "spring_standalone", git: "..."` *won't* work and is not a
36
+ supported way of using SpringStandalone.)
37
+
38
+ It's recommended to 'springify' the executables in your `bin/`
39
+ directory:
40
+
41
+ ```
42
+ $ bundle install
43
+ $ bundle exec spring_sa binstub --all
44
+ ```
45
+
46
+ This generates a `bin/spring_sa` executable, and inserts a small snippet of
47
+ code into relevant existing executables. The snippet looks like this:
48
+
49
+ ``` ruby
50
+ begin
51
+ load File.expand_path('../spring_sa', __FILE__)
52
+ rescue LoadError
53
+ end
54
+ ```
55
+
56
+ On platforms where SpringStandalone Standalone is installed and supported, this snippet
57
+ hooks SpringStandalone into the execution of commands. In other cases, the snippet
58
+ will just be silently ignored and the lines after it will be executed as
59
+ normal.
60
+
61
+ If you don't want to prefix every command you type with `bin/`, you
62
+ can [use direnv](https://github.com/direnv/direnv#the-stdlib) to
63
+ automatically add `./bin` to your `PATH` when you `cd` into your application.
64
+ Simply create an `.envrc` file with the command `PATH_add bin` in your
65
+ Rails directory.
66
+
67
+ ### Usage
68
+
69
+ For this walkthrough I've generated a new Rails application, and run
70
+ `rails generate scaffold post name:string`.
71
+
72
+ Let's run a test:
73
+
74
+ ```
75
+ $ time bin/rake test test/controllers/posts_controller_test.rb
76
+ Running via SpringStandalone preloader in process 2734
77
+ Run options:
78
+
79
+ # Running tests:
80
+
81
+ .......
82
+
83
+ Finished tests in 0.127245s, 55.0121 tests/s, 78.5887 assertions/s.
84
+
85
+ 7 tests, 10 assertions, 0 failures, 0 errors, 0 skips
86
+
87
+ real 0m2.165s
88
+ user 0m0.281s
89
+ sys 0m0.066s
90
+ ```
91
+
92
+ That wasn't particularly fast because it was the first run, so SpringStandalone
93
+ had to boot the application. It's now running:
94
+
95
+ ```
96
+ $ bin/spring status
97
+ SpringStandalone is running:
98
+
99
+ 26150 spring server | spring-demo-app | started 3 secs ago
100
+ 26155 spring app | spring-demo-app | started 3 secs ago | test mode
101
+ ```
102
+
103
+ The next run is faster:
104
+
105
+ ```
106
+ $ time bin/rake test test/controllers/posts_controller_test.rb
107
+ Running via SpringStandalone preloader in process 8352
108
+ Run options:
109
+
110
+ # Running tests:
111
+
112
+ .......
113
+
114
+ Finished tests in 0.176896s, 39.5714 tests/s, 56.5305 assertions/s.
115
+
116
+ 7 tests, 10 assertions, 0 failures, 0 errors, 0 skips
117
+
118
+ real 0m0.610s
119
+ user 0m0.276s
120
+ sys 0m0.059s
121
+ ```
122
+
123
+ If we edit any of the application files, or test files, the changes will
124
+ be picked up on the next run without the background process having to
125
+ restart. This works in exactly the same way as the code reloading
126
+ which allows you to refresh your browser and instantly see changes during
127
+ development.
128
+
129
+ But if we edit any of the files which were used to start the application
130
+ (configs, initializers, your gemfile), the application needs to be fully
131
+ restarted. This happens automatically.
132
+
133
+ Let's "edit" `config/application.rb`:
134
+
135
+ ```
136
+ $ touch config/application.rb
137
+ $ bin/spring status
138
+ SpringStandalone is running:
139
+
140
+ 26150 spring server | spring-demo-app | started 36 secs ago
141
+ 26556 spring app | spring-demo-app | started 1 sec ago | test mode
142
+ ```
143
+
144
+ The application detected that `config/application.rb` changed and
145
+ automatically restarted itself.
146
+
147
+ If we run a command that uses a different environment, then that
148
+ environment gets booted up:
149
+
150
+ ```
151
+ $ bin/rake routes
152
+ Running via SpringStandalone preloader in process 2363
153
+ posts GET /posts(.:format) posts#index
154
+ POST /posts(.:format) posts#create
155
+ new_post GET /posts/new(.:format) posts#new
156
+ edit_post GET /posts/:id/edit(.:format) posts#edit
157
+ post GET /posts/:id(.:format) posts#show
158
+ PUT /posts/:id(.:format) posts#update
159
+ DELETE /posts/:id(.:format) posts#destroy
160
+
161
+ $ bin/spring status
162
+ SpringStandalone is running:
163
+
164
+ 26150 spring server | spring-demo-app | started 1 min ago
165
+ 26556 spring app | spring-demo-app | started 42 secs ago | test mode
166
+ 26707 spring app | spring-demo-app | started 2 secs ago | development mode
167
+ ```
168
+
169
+ There's no need to "shut down" SpringStandalone. This will happen automatically
170
+ when you close your terminal. However if you do want to do a manual shut
171
+ down, use the `stop` command:
172
+
173
+ ```
174
+ $ bin/spring stop
175
+ SpringStandalone stopped.
176
+ ```
177
+
178
+ From within your code, you can check whether SpringStandalone is active with `if defined?(SpringStandalone)`.
179
+
180
+ ### Removal
181
+
182
+ To remove SpringStandalone:
183
+
184
+ * 'Unspring' your bin/ executables: `bin/spring binstub --remove --all`
185
+ * Remove spring from your Gemfile
186
+
187
+ ### Deployment
188
+
189
+ You must not install SpringStandalone on your production environment. To prevent it from
190
+ being installed, provide the `--without development test` argument to the
191
+ `bundle install` command which is used to install gems on your production
192
+ machines:
193
+
194
+ ```
195
+ $ bundle install --without development test
196
+ ```
197
+
198
+ ## Commands
199
+
200
+ ### `rake`
201
+
202
+ Runs a rake task. Rake tasks run in the `development` environment by
203
+ default. You can change this on the fly by using the `RAILS_ENV`
204
+ environment variable. The environment is also configurable with the
205
+ `SpringStandalone::Commands::Rake.environment_matchers` hash. This has sensible
206
+ defaults, but if you need to match a specific task to a specific
207
+ environment, you'd do it like this:
208
+
209
+ ``` ruby
210
+ SpringStandalone::Commands::Rake.environment_matchers["perf_test"] = "test"
211
+ SpringStandalone::Commands::Rake.environment_matchers[/^perf/] = "test"
212
+
213
+ # To change the environment when you run `rake` with no arguments
214
+ SpringStandalone::Commands::Rake.environment_matchers[:default] = "development"
215
+ ```
216
+
217
+ ### `rails console`, `rails generate`, `rails runner`
218
+
219
+ These execute the rails command you already know and love. If you run
220
+ a different sub command (e.g. `rails server`) then SpringStandalone will automatically
221
+ pass it through to the underlying `rails` executable (without the
222
+ speed-up).
223
+
224
+ ### Additional commands
225
+
226
+ You can add these to your Gemfile for additional commands:
227
+
228
+ * [spring-commands-rspec](https://github.com/jonleighton/spring-commands-rspec)
229
+ * [spring-commands-cucumber](https://github.com/jonleighton/spring-commands-cucumber)
230
+ * [spring-commands-spinach](https://github.com/jvanbaarsen/spring-commands-spinach)
231
+ * [spring-commands-testunit](https://github.com/jonleighton/spring-commands-testunit) - useful for
232
+ running `Test::Unit` tests on Rails 3, since only Rails 4 allows you
233
+ to use `rake test path/to/test` to run a particular test/directory.
234
+ * [spring-commands-parallel-tests](https://github.com/DocSpring/spring-commands-parallel-tests) - Adds the `parallel_*` commands from [`parallel_tests`](https://github.com/grosser/parallel_tests).
235
+ * [spring-commands-teaspoon](https://github.com/alejandrobabio/spring-commands-teaspoon.git)
236
+ * [spring-commands-m](https://github.com/gabrieljoelc/spring-commands-m.git)
237
+ * [spring-commands-rubocop](https://github.com/p0deje/spring-commands-rubocop)
238
+ * [spring-commands-rackup](https://github.com/wintersolutions/spring-commands-rackup)
239
+ * [spring-commands-rack-console](https://github.com/wintersolutions/spring-commands-rack-console)
240
+
241
+ ## Use without adding to bundle
242
+
243
+ If you don't want SpringStandalone-related code checked into your source
244
+ repository, it's possible to use SpringStandalone without adding to your Gemfile.
245
+ However, using SpringStandalone binstubs without adding SpringStandalone to the Gemfile is not
246
+ supported.
247
+
248
+ To use SpringStandalone like this, do a `gem install spring` and then prefix
249
+ commands with `spring`. For example, rather than running `bin/rake -T`,
250
+ you'd run `spring rake -T`.
251
+
252
+ ## Temporarily disabling SpringStandalone
253
+
254
+ If you're using SpringStandalone binstubs, but temporarily don't want commands to
255
+ run through SpringStandalone, set the `DISABLE_SPRING` environment variable.
256
+
257
+ ## Class reloading
258
+
259
+ SpringStandalone uses Rails' class reloading mechanism
260
+ (`ActiveSupport::Dependencies`) to keep your code up to date between
261
+ test runs. This is the same mechanism which allows you to see changes
262
+ during development when you refresh the page. However, you may never
263
+ have used this mechanism with your `test` environment before, and this
264
+ can cause problems.
265
+
266
+ It's important to realise that code reloading means that the constants
267
+ in your application are *different objects* after files have changed:
268
+
269
+ ```
270
+ $ bin/rails runner 'puts User.object_id'
271
+ 70127987886040
272
+ $ touch app/models/user.rb
273
+ $ bin/rails runner 'puts User.object_id'
274
+ 70127976764620
275
+ ```
276
+
277
+ Suppose you have an initializer `config/initializers/save_user_class.rb`
278
+ like so:
279
+
280
+ ``` ruby
281
+ USER_CLASS = User
282
+ ```
283
+
284
+ This saves off the *first* version of the `User` class, which will not
285
+ be the same object as `User` after the code has been reloaded:
286
+
287
+ ```
288
+ $ bin/rails runner 'puts User == USER_CLASS'
289
+ true
290
+ $ touch app/models/user.rb
291
+ $ bin/rails runner 'puts User == USER_CLASS'
292
+ false
293
+ ```
294
+
295
+ So to avoid this problem, don't save off references to application
296
+ constants in your initialization code.
297
+
298
+ ## Using SpringStandalone with a containerized development environment
299
+
300
+ As of SpringStandalone 1.7, there is some support for doing this. See [this
301
+ example
302
+ repository](https://github.com/jonleighton/spring-docker-example) for
303
+ information about how to do it with [Docker](https://www.docker.com/).
304
+
305
+ ## Configuration
306
+
307
+ SpringStandalone will read `~/.spring.rb` and `config/spring.rb` for custom
308
+ settings. Note that `~/.spring.rb` is loaded *before* bundler, but
309
+ `config/spring.rb` is loaded *after* bundler. So if you have any
310
+ `spring-commands-*` gems installed that you want to be available in all
311
+ projects without having to be added to the project's Gemfile, require
312
+ them in your `~/.spring.rb`.
313
+
314
+ `config/spring_client.rb` is also loaded before bundler and before a
315
+ server process is started, it can be used to add new top-level commands.
316
+
317
+ ### Application root
318
+
319
+ SpringStandalone must know how to find your Rails application. If you have a
320
+ normal app everything works out of the box. If you are working on a
321
+ project with a special setup (an engine for example), you must tell
322
+ SpringStandalone where your app is located:
323
+
324
+ ```ruby
325
+ SpringStandalone.application_root = './test/dummy'
326
+ ```
327
+
328
+ ### Running code before forking
329
+
330
+ There is no `SpringStandalone.before_fork` callback. To run something before the
331
+ fork, you can place it in `~/.spring.rb` or `config/spring.rb` or in any of the files
332
+ which get run when your application initializes, such as
333
+ `config/application.rb`, `config/environments/*.rb` or
334
+ `config/initializers/*.rb`.
335
+
336
+ ### Running code after forking
337
+
338
+ You might want to run code after SpringStandalone forked off the process but
339
+ before the actual command is run. You might want to use an
340
+ `after_fork` callback if you have to connect to an external service,
341
+ do some general cleanup or set up dynamic configuration.
342
+
343
+ ```ruby
344
+ SpringStandalone.after_fork do
345
+ # run arbitrary code
346
+ end
347
+ ```
348
+
349
+ If you want to register multiple callbacks you can simply call
350
+ `SpringStandalone.after_fork` multiple times with different blocks.
351
+
352
+ ### Watching files and directories
353
+
354
+ SpringStandalone will automatically detect file changes to any file loaded when the server
355
+ boots. Changes will cause the affected environments to be restarted.
356
+
357
+ If there are additional files or directories which should trigger an
358
+ application restart, you can specify them with `SpringStandalone.watch`:
359
+
360
+ ```ruby
361
+ SpringStandalone.watch "config/some_config_file.yml"
362
+ ```
363
+
364
+ By default SpringStandalone polls the filesystem for changes once every 0.2 seconds. This
365
+ method requires zero configuration, but if you find that it's using too
366
+ much CPU, then you can use event-based file system listening by
367
+ installing the
368
+ [spring-watcher-listen](https://github.com/jonleighton/spring-watcher-listen)
369
+ gem.
370
+
371
+ ### Quiet output
372
+
373
+ To disable the "Running via SpringStandalone preloader" message which is shown each time
374
+ a command runs:
375
+
376
+ ``` ruby
377
+ SpringStandalone.quiet = true
378
+ ```
379
+
380
+ ### Environment variables
381
+
382
+ The following environment variables are used by SpringStandalone:
383
+
384
+ * `DISABLE_SPRING` - If set, SpringStandalone will be bypassed and your
385
+ application will boot in a foreground process
386
+ * `SPRING_LOG` - The path to a file which SpringStandalone will write log messages
387
+ to.
388
+ * `SPRING_TMP_PATH` - The directory where SpringStandalone should write its temporary
389
+ files (a pidfile and a socket). By default we use the
390
+ `XDG_RUNTIME_DIR` environment variable, or else `Dir.tmpdir`, and then
391
+ create a directory in that named `spring-$UID`. We don't use your
392
+ Rails application's `tmp/` directory because that may be on a
393
+ filesystem which doesn't support UNIX sockets.
394
+ * `SPRING_APPLICATION_ID` - Used to identify distinct Rails
395
+ applications. By default it is an MD5 hash of the current
396
+ `RUBY_VERSION`, and the path to your Rails project root.
397
+ * `SPRING_SOCKET` - The path which should be used for the UNIX socket
398
+ which SpringStandalone uses to communicate with the long-running SpringStandalone server
399
+ process. By default this is `SPRING_TMP_PATH/SPRING_APPLICATION_ID`.
400
+ * `SPRING_PIDFILE` - The path which should be used to store the pid of
401
+ the long-running SpringStandalone server process. By default this is related to
402
+ the socket path; if the socket path is `/foo/bar/spring.sock` the
403
+ pidfile will be `/foo/bar/spring.pid`.
404
+ * `SPRING_SERVER_COMMAND` - The command to run to start up the SpringStandalone
405
+ server when it is not already running. Defaults to `spring _[version]_
406
+ server --background`.
407
+
408
+ ## Troubleshooting
409
+
410
+ If you want to get more information about what SpringStandalone is doing, you can
411
+ run SpringStandalone explicitly in a separate terminal:
412
+
413
+ ```
414
+ $ spring server
415
+ ```
416
+
417
+ Logging output will be printed to stdout. You can also send log output
418
+ to a file with the `SPRING_LOG` environment variable.
data/bin/spring_sa ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if defined?(SpringStandalone)
4
+ $stderr.puts "You've tried to invoke SpringStandalone when it's already loaded (i.e. the SpringStandalone " \
5
+ "constant is defined)."
6
+ $stderr.puts
7
+ $stderr.puts "This is probably because you generated binstubs with " \
8
+ "SpringStandalone 1.0, and you now have a SpringStandalone version > 1.0 on your system. To solve " \
9
+ "this, upgrade your bundle to the latest SpringStandalone version and then run " \
10
+ "`bundle exec spring binstub --all` to regenerate your binstubs. This is a one-time " \
11
+ "step necessary to upgrade from 1.0 to 1.1."
12
+ $stderr.puts
13
+ $stderr.puts "Here's the backtrace:"
14
+ $stderr.puts
15
+ $stderr.puts caller
16
+ exit 1
17
+ end
18
+
19
+ if defined?(Gem)
20
+ if Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.1.0")
21
+ warn "Warning: You're using Rubygems #{Gem::VERSION} with SpringStandalone. " \
22
+ "Upgrade to at least Rubygems 2.1.0 and run `gem pristine --all` for better " \
23
+ "startup performance."
24
+ else
25
+ stubs = Gem::Specification.stubs.grep(Gem::StubSpecification)
26
+
27
+ # stubbed? method added in https://github.com/rubygems/rubygems/pull/694
28
+ if Gem::Specification.stubs.first.respond_to?(:stubbed?)
29
+ unstubbed = stubs.reject(&:stubbed?)
30
+ else
31
+ unstubbed = stubs.reject { |s| s.send(:data).is_a?(Gem::StubSpecification::StubLine) }
32
+ end
33
+
34
+ # `gem pristine --all` ignores default gems. it doesn't really matter,
35
+ # as there are probably not many of them on the system.
36
+ unstubbed.reject!(&:default_gem?)
37
+
38
+ if unstubbed.any?
39
+ warn "Warning: Running `gem pristine --all` to regenerate your installed gemspecs " \
40
+ "(and deleting then reinstalling your bundle if you use bundle --path) " \
41
+ "will improve the startup performance of SpringStandalone."
42
+ end
43
+ end
44
+ end
45
+
46
+ lib = File.expand_path("../../lib", __FILE__)
47
+ $LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib) # enable local development
48
+ require 'spring_standalone/client'
49
+ SpringStandalone::Client.run(ARGV)