alki-reload 0.1.0 → 0.2.0
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.
- checksums.yaml +4 -4
- data/README.adoc +162 -0
- data/alki-reload.gemspec +1 -1
- data/config/assembly.rb +26 -5
- data/lib/alki/reload/load_path_handler.rb +1 -1
- data/lib/alki/reload/{dsl_handler.rb → loader_handler.rb} +5 -7
- data/lib/alki/reload/reloadable_delegator.rb +30 -0
- data/lib/alki/reload/unloader.rb +12 -10
- data/lib/alki/reload/version.rb +1 -1
- metadata +7 -12
- data/README.md +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b05597e13de69db0fcbc34fd150c89fde3647a24
|
4
|
+
data.tar.gz: 6e7161d23ae9d232b7e7c0e5309ca6e3b49871a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 672a296eadf628c9cbb3a5a3f53766d1c67d48b22e30ff53d865b89f151897197219643bb336c2f892333aed1671a230948763bd1dc34eed0a13e83067ef19c0
|
7
|
+
data.tar.gz: 751e2cc7bcb01466edb10ddb95d15017b2e3f53732d99f75f4e6eaab333a7de28c8ec629955bc8fe625c9cbc9f9438250ed2728d624af3ec03c9dd9e2e522ed5
|
data/README.adoc
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
= Alki::Reload
|
2
|
+
|
3
|
+
Provides auto-reload feature to Alki projects. Like the auto-reload feature in Ruby on Rails, when
|
4
|
+
enabled it will monitor source files and whenever a change is detected, will reload the project.
|
5
|
+
|
6
|
+
== Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
[source,ruby]
|
11
|
+
----
|
12
|
+
gem 'alki-reload'
|
13
|
+
----
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
[source]
|
18
|
+
----
|
19
|
+
$ bundle
|
20
|
+
----
|
21
|
+
|
22
|
+
Or install it yourself as:
|
23
|
+
|
24
|
+
[source]
|
25
|
+
----
|
26
|
+
$ gem install alki-reload
|
27
|
+
----
|
28
|
+
|
29
|
+
== Usage
|
30
|
+
|
31
|
+
To use Alki::Reload in an Alki project, it must be mounted in the assembly. By default, Alki::Reload
|
32
|
+
will not actively watch files or actively hook into services. Setting `enable` to true will enable both.
|
33
|
+
|
34
|
+
.config/assembly.rb
|
35
|
+
```ruby
|
36
|
+
Alki do
|
37
|
+
mount :reloader, 'alki/reload' do
|
38
|
+
set(:enable) { true }
|
39
|
+
end
|
40
|
+
# ...
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
44
|
+
### Conditional usage
|
45
|
+
|
46
|
+
Because enabling reload can have a performance impact, typically it's only enabled when in some sort
|
47
|
+
of development mode.
|
48
|
+
|
49
|
+
.config/assembly.rb
|
50
|
+
```ruby
|
51
|
+
Alki do
|
52
|
+
set(:development?) { ENV['APP_ENV'] != 'production' }
|
53
|
+
|
54
|
+
mount :reloader, 'alki/reload' do
|
55
|
+
set(:enable) { development? }
|
56
|
+
end
|
57
|
+
# ...
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
### Main Loops
|
62
|
+
|
63
|
+
A problem that naturally comes up is how to reload an application, while the application is running.
|
64
|
+
Most applications, when running, spend most of their time inside a "main loop". If it's a server,
|
65
|
+
it might be the loop listening for incoming data, if it's a console application it might be the loop
|
66
|
+
waiting for user input.
|
67
|
+
|
68
|
+
Because the main loop is always running, there is never an opportunity to reload it. Alki::Reload
|
69
|
+
provides a feature to help work around this.
|
70
|
+
|
71
|
+
First off, because the service the main loop is in can't be reloaded, it should be made as small and
|
72
|
+
simple as possible, offloading all other functionality into secondary services that it takes as
|
73
|
+
dependencies.
|
74
|
+
|
75
|
+
Second, it should be tagged with a `main_loop` tag. By tagging your main loop service, Alki::Reload will
|
76
|
+
actively hook into the service and wrap it's dependencies with wrapper objects that will pick up the
|
77
|
+
new version of those dependencies whenever the project is reloaded.
|
78
|
+
|
79
|
+
Alki::Loader must be enabled for this feature to be active.
|
80
|
+
|
81
|
+
.config/assembly.rb
|
82
|
+
```ruby
|
83
|
+
Alki do
|
84
|
+
mount :reloader, 'alki/reload', enable: true
|
85
|
+
|
86
|
+
set :prompt, "> "
|
87
|
+
service :handler do
|
88
|
+
-> line { puts line }
|
89
|
+
end
|
90
|
+
|
91
|
+
tag :main_loop
|
92
|
+
service :main do
|
93
|
+
require 'readline_loop'
|
94
|
+
ReadlineLoop.new prompt, handler
|
95
|
+
end
|
96
|
+
# ...
|
97
|
+
end
|
98
|
+
```
|
99
|
+
|
100
|
+
.lib/readline_loop.rb
|
101
|
+
```ruby
|
102
|
+
require 'readline'
|
103
|
+
class ReadlineLoop
|
104
|
+
def initialize(prompt, handler)
|
105
|
+
@prompt = prompt
|
106
|
+
@handler = handler
|
107
|
+
end
|
108
|
+
|
109
|
+
def run
|
110
|
+
while line = Readline.readline(@prompt,true)
|
111
|
+
@handler.call line
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
```
|
116
|
+
|
117
|
+
In this example, our main loop is `main.run`. Because the `main` service is tagged even while it
|
118
|
+
is running the prompt and handler can be changed and reloaded.
|
119
|
+
|
120
|
+
### Watched Directories
|
121
|
+
|
122
|
+
By default, `lib`, `config` and any files or directories configured in
|
123
|
+
https://github.com/alki-project/alki-loader[Alki::Loader] are watched.
|
124
|
+
|
125
|
+
Additional directories can be added by overriding the dirs element. Additional directories must also
|
126
|
+
be in `$LOAD_PATH`.
|
127
|
+
|
128
|
+
.config/assembly.rb
|
129
|
+
```ruby
|
130
|
+
Alki do
|
131
|
+
mount :reloader, 'alki/reload' do
|
132
|
+
set(:enable) { true }
|
133
|
+
set(:dirs) { original.dirs + ['app'] }
|
134
|
+
end
|
135
|
+
# ...
|
136
|
+
end
|
137
|
+
```
|
138
|
+
|
139
|
+
### Manual Reloading
|
140
|
+
|
141
|
+
In addition to watching for filesystem changes, a project can be reloaded manually by calling
|
142
|
+
the `reload` func in the reloader. This works even when the reloader is not enabled.
|
143
|
+
|
144
|
+
.config/assembly.rb
|
145
|
+
```ruby
|
146
|
+
Alki do
|
147
|
+
mount :reloader, 'alki/reload'
|
148
|
+
# ...
|
149
|
+
end
|
150
|
+
```
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
instance.reloader.reload # reload instance
|
154
|
+
```
|
155
|
+
|
156
|
+
== Contributing
|
157
|
+
|
158
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/alki-project/alki-reload. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the http://contributor-covenant.org[Contributor Covenant] code of conduct.
|
159
|
+
|
160
|
+
== License
|
161
|
+
|
162
|
+
The gem is available as open source under the terms of the http://opensource.org/licenses/MIT[MIT License].
|
data/alki-reload.gemspec
CHANGED
@@ -23,5 +23,5 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_development_dependency "bundler", "~> 1.13"
|
24
24
|
spec.add_development_dependency "rake", "~> 10.0"
|
25
25
|
spec.add_dependency "listen", "~> 3.0"
|
26
|
-
spec.add_dependency "alki", "~> 0.
|
26
|
+
spec.add_dependency "alki", "~> 0.10"
|
27
27
|
end
|
data/config/assembly.rb
CHANGED
@@ -3,7 +3,15 @@ Alki do
|
|
3
3
|
root.assembly_instance.__reload__
|
4
4
|
end
|
5
5
|
|
6
|
-
set :
|
6
|
+
set :enable, false
|
7
|
+
|
8
|
+
set :main_loops do
|
9
|
+
enable
|
10
|
+
end
|
11
|
+
|
12
|
+
set :watch do
|
13
|
+
enable
|
14
|
+
end
|
7
15
|
|
8
16
|
set :dirs do
|
9
17
|
['lib']
|
@@ -19,13 +27,26 @@ Alki do
|
|
19
27
|
end
|
20
28
|
end
|
21
29
|
|
30
|
+
reference_overlay '%main_loop', :reloadable_reference
|
31
|
+
|
32
|
+
factory :reloadable_reference do
|
33
|
+
require 'alki/reload/reloadable_delegator'
|
34
|
+
-> (ref) {
|
35
|
+
if main_loops
|
36
|
+
Alki::Reload::ReloadableDelegator.new(root.assembly_instance,ref)
|
37
|
+
else
|
38
|
+
ref.call
|
39
|
+
end
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
22
43
|
service :handlers do
|
23
|
-
[
|
44
|
+
[loader_handler,load_path_handler]
|
24
45
|
end
|
25
46
|
|
26
|
-
service :
|
27
|
-
require 'alki/reload/
|
28
|
-
Alki::Reload::
|
47
|
+
service :loader_handler do
|
48
|
+
require 'alki/reload/loader_handler'
|
49
|
+
Alki::Reload::LoaderHandler.new root_dir
|
29
50
|
end
|
30
51
|
|
31
52
|
service :load_path_handler do
|
@@ -1,8 +1,8 @@
|
|
1
|
-
require 'alki/
|
1
|
+
require 'alki/loader'
|
2
2
|
|
3
3
|
module Alki
|
4
4
|
module Reload
|
5
|
-
class
|
5
|
+
class LoaderHandler
|
6
6
|
def initialize(root_dir)
|
7
7
|
@root_dir = File.join(root_dir,'')
|
8
8
|
end
|
@@ -11,17 +11,15 @@ module Alki
|
|
11
11
|
dirs.each do |dir|
|
12
12
|
dir = File.join(dir,'')
|
13
13
|
if path.start_with? dir
|
14
|
-
|
15
|
-
|
16
|
-
return [entry.data[:prefix], entry.data[:name]]
|
17
|
-
end
|
14
|
+
name = Alki::Loader.lookup_name path
|
15
|
+
return name if name
|
18
16
|
end
|
19
17
|
end
|
20
18
|
nil
|
21
19
|
end
|
22
20
|
|
23
21
|
def dirs
|
24
|
-
Alki::
|
22
|
+
Alki::Loader.registered_paths.select do |d|
|
25
23
|
d.start_with?(@root_dir)
|
26
24
|
end
|
27
25
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module Alki
|
4
|
+
module Reload
|
5
|
+
class ReloadableDelegator < Delegator
|
6
|
+
def initialize(instance,ref)
|
7
|
+
@instance = instance
|
8
|
+
@ref = ref
|
9
|
+
end
|
10
|
+
|
11
|
+
def __getobj__
|
12
|
+
if !@obj || @instance_version != @instance.__version__
|
13
|
+
@ref.executor = @instance.assembly_executor
|
14
|
+
@obj = @ref.call
|
15
|
+
@instance_version = @instance.__version__
|
16
|
+
end
|
17
|
+
@obj
|
18
|
+
end
|
19
|
+
|
20
|
+
def method_missing(method,*args,&blk)
|
21
|
+
ref_meth = :"__reference_#{method}__"
|
22
|
+
if respond_to?(ref_meth,true)
|
23
|
+
ReloadableDelegator.new @instance, super(ref_meth, *args, &blk)
|
24
|
+
else
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/alki/reload/unloader.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'alki/support'
|
2
|
-
require 'alki/dsl/registry'
|
3
2
|
|
4
3
|
module Alki
|
5
4
|
module Reload
|
@@ -16,8 +15,9 @@ module Alki
|
|
16
15
|
if path.end_with?('.rb')
|
17
16
|
result = @handlers.lazy.map{|h| h.handle_path path }.find{|r| r != nil}
|
18
17
|
if result
|
19
|
-
add_const consts,
|
20
|
-
|
18
|
+
if add_const consts, result
|
19
|
+
files << path
|
20
|
+
end
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -33,9 +33,15 @@ module Alki
|
|
33
33
|
|
34
34
|
private
|
35
35
|
|
36
|
-
def add_const(consts,
|
37
|
-
unless
|
38
|
-
|
36
|
+
def add_const(consts,name)
|
37
|
+
unless @whitelist.include? name
|
38
|
+
md = name.match(%r{(.*)/(.*)})
|
39
|
+
if md
|
40
|
+
parent = Alki::Support.constantize Alki::Support.classify md[1]
|
41
|
+
name = md[2]
|
42
|
+
else
|
43
|
+
parent = Object
|
44
|
+
end
|
39
45
|
name = Alki::Support.classify(name).to_sym
|
40
46
|
if parent && parent.is_a?(Module) && parent.const_defined?(name,false)
|
41
47
|
consts << [parent,name]
|
@@ -43,10 +49,6 @@ module Alki
|
|
43
49
|
end
|
44
50
|
end
|
45
51
|
end
|
46
|
-
|
47
|
-
def whitelisted?(parent,name)
|
48
|
-
@whitelist.include?(parent ? File.join(parent,name) : name)
|
49
|
-
end
|
50
52
|
end
|
51
53
|
end
|
52
54
|
end
|
data/lib/alki/reload/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alki-reload
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Edlefsen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-12-
|
11
|
+
date: 2016-12-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -58,20 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0.
|
62
|
-
- - ">="
|
63
|
-
- !ruby/object:Gem::Version
|
64
|
-
version: 0.9.1
|
61
|
+
version: '0.10'
|
65
62
|
type: :runtime
|
66
63
|
prerelease: false
|
67
64
|
version_requirements: !ruby/object:Gem::Requirement
|
68
65
|
requirements:
|
69
66
|
- - "~>"
|
70
67
|
- !ruby/object:Gem::Version
|
71
|
-
version: '0.
|
72
|
-
- - ">="
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
version: 0.9.1
|
68
|
+
version: '0.10'
|
75
69
|
description:
|
76
70
|
email:
|
77
71
|
- matt.edlefsen@gmail.com
|
@@ -83,15 +77,16 @@ files:
|
|
83
77
|
- CODE_OF_CONDUCT.md
|
84
78
|
- Gemfile
|
85
79
|
- LICENSE.txt
|
86
|
-
- README.
|
80
|
+
- README.adoc
|
87
81
|
- Rakefile
|
88
82
|
- alki-reload.gemspec
|
89
83
|
- config/assembly.rb
|
90
84
|
- lib/alki/reload.rb
|
91
85
|
- lib/alki/reload/assembly_delegator.rb
|
92
|
-
- lib/alki/reload/dsl_handler.rb
|
93
86
|
- lib/alki/reload/listen_watcher.rb
|
94
87
|
- lib/alki/reload/load_path_handler.rb
|
88
|
+
- lib/alki/reload/loader_handler.rb
|
89
|
+
- lib/alki/reload/reloadable_delegator.rb
|
95
90
|
- lib/alki/reload/reloader.rb
|
96
91
|
- lib/alki/reload/unloader.rb
|
97
92
|
- lib/alki/reload/version.rb
|
data/README.md
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
# Alki::Reload
|
2
|
-
|
3
|
-
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/alki/reload`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
-
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
6
|
-
|
7
|
-
## Installation
|
8
|
-
|
9
|
-
Add this line to your application's Gemfile:
|
10
|
-
|
11
|
-
```ruby
|
12
|
-
gem 'alki-reload'
|
13
|
-
```
|
14
|
-
|
15
|
-
And then execute:
|
16
|
-
|
17
|
-
$ bundle
|
18
|
-
|
19
|
-
Or install it yourself as:
|
20
|
-
|
21
|
-
$ gem install alki-reload
|
22
|
-
|
23
|
-
## Usage
|
24
|
-
|
25
|
-
TODO: Write usage instructions here
|
26
|
-
|
27
|
-
## Development
|
28
|
-
|
29
|
-
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
-
|
31
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
-
|
33
|
-
## Contributing
|
34
|
-
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/alki-reload. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
36
|
-
|
37
|
-
|
38
|
-
## License
|
39
|
-
|
40
|
-
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
41
|
-
|