lspace 0.1 → 0.2
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.
- data/.gitignore +1 -0
- data/Gemfile +3 -0
- data/README.md +3 -3
- data/lib/lspace/class_methods.rb +6 -5
- data/lib/lspace/core_ext.rb +9 -5
- data/lib/lspace/eventmachine.rb +6 -3
- data/lib/lspace.rb +6 -6
- data/lspace.gemspec +2 -1
- data/spec/class_method_spec.rb +6 -6
- data/spec/core_ext_spec.rb +13 -4
- data/spec/eventmachine_spec.rb +6 -6
- data/spec/lspace_spec.rb +1 -0
- metadata +19 -1
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Gemfile.lock
|
data/Gemfile
ADDED
data/README.md
CHANGED
@@ -19,7 +19,7 @@ class DatabaseConnection
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.use_master(&block)
|
22
|
-
LSpace.
|
22
|
+
LSpace.with(:preferred_connection => master_connection) do
|
23
23
|
block.call
|
24
24
|
end
|
25
25
|
end
|
@@ -69,11 +69,11 @@ class Fetcher
|
|
69
69
|
end
|
70
70
|
|
71
71
|
EM::run do
|
72
|
-
LSpace.
|
72
|
+
LSpace.with(:log_prefix => rand(50000)) do
|
73
73
|
Fetcher.new.fetch("http://www.google.com")
|
74
74
|
Fetcher.new.fetch("http://www.yahoo.com")
|
75
75
|
end
|
76
|
-
LSpace.
|
76
|
+
LSpace.with(:log_prefix => rand(50000)) do
|
77
77
|
Fetcher.new.fetch("http://www.microsoft.com")
|
78
78
|
end
|
79
79
|
end
|
data/lib/lspace/class_methods.rb
CHANGED
@@ -19,13 +19,14 @@ class LSpace
|
|
19
19
|
enter new({}, nil), &block
|
20
20
|
end
|
21
21
|
|
22
|
-
# Create a new LSpace with the given keys set to the given values
|
22
|
+
# Create a new LSpace with the given keys set to the given values, and run the
|
23
|
+
# given block in that new LSpace.
|
23
24
|
#
|
24
25
|
# The LSpace will inherit any unspecified keys from the currently active LSpace.
|
25
26
|
#
|
26
27
|
# @example
|
27
|
-
# LSpace.
|
28
|
-
# LSpace.
|
28
|
+
# LSpace.with :user_id => 6 do
|
29
|
+
# LSpace.with :job_id => 7 do
|
29
30
|
# LSpace[:user_id] == 6
|
30
31
|
# LSpace[:job_id] == 7
|
31
32
|
# end
|
@@ -34,7 +35,7 @@ class LSpace
|
|
34
35
|
# @param [Hash] hash The keys to update
|
35
36
|
# @param [Proc] block The logical block to run with the updated LSpace
|
36
37
|
# @see LSpace.enter
|
37
|
-
def self.
|
38
|
+
def self.with(hash={}, &block)
|
38
39
|
enter new(hash, current), &block
|
39
40
|
end
|
40
41
|
|
@@ -66,7 +67,7 @@ class LSpace
|
|
66
67
|
previous = current
|
67
68
|
self.current = lspace
|
68
69
|
|
69
|
-
filters = lspace.hierarchy.take_while{ |lspace| lspace != previous }.
|
70
|
+
filters = lspace.hierarchy.take_while{ |lspace| lspace != previous }.flat_map(&:around_filters)
|
70
71
|
|
71
72
|
filters.inject(block) do |blk, filter|
|
72
73
|
lambda{ filter.call(&blk) }
|
data/lib/lspace/core_ext.rb
CHANGED
@@ -15,7 +15,7 @@ class Module
|
|
15
15
|
# LSpace[:user_id] = 6
|
16
16
|
# Job.new.user == #<User:6>
|
17
17
|
#
|
18
|
-
# @param [Symbol]
|
18
|
+
# @param [Symbol] attrs The accessors to create
|
19
19
|
def lspace_reader(*attrs)
|
20
20
|
attrs.each do |attr|
|
21
21
|
define_method(attr) do
|
@@ -29,7 +29,7 @@ class Module
|
|
29
29
|
# This wraps both the &block parameter, and also any Procs
|
30
30
|
# that are passed into the function directly.
|
31
31
|
#
|
32
|
-
# If you need more complicated logic (
|
32
|
+
# If you need more complicated logic (e.g. wrapping Procs
|
33
33
|
# that are passed to a function in a dictionary) you're
|
34
34
|
# on your own.
|
35
35
|
#
|
@@ -42,17 +42,20 @@ class Module
|
|
42
42
|
# Thread.new{ LSpace[:user_id] == 2 }
|
43
43
|
# end
|
44
44
|
#
|
45
|
-
# @param [Symbol]
|
45
|
+
# @param [Symbol] methods The methods to wrap
|
46
46
|
def in_lspace(*methods)
|
47
47
|
methods.each do |method|
|
48
48
|
method_without_lspace = "#{method}_without_lspace"
|
49
|
+
|
50
|
+
# Idempotence: do nothing if the _without_lspace method already exists.
|
51
|
+
# method_defined? matches public and protected methods; private methods need a separate check.
|
49
52
|
next if method_defined?(method_without_lspace) || private_method_defined?(method_without_lspace)
|
50
53
|
|
51
54
|
alias_method method_without_lspace, method
|
52
55
|
|
53
56
|
define_method(method) do |*args, &block|
|
54
57
|
args.map!{ |a| Proc === a ? a.in_lspace : a }
|
55
|
-
block = block
|
58
|
+
block = block.in_lspace if block
|
56
59
|
__send__(method_without_lspace, *args, &block)
|
57
60
|
end
|
58
61
|
|
@@ -63,7 +66,8 @@ class Module
|
|
63
66
|
end
|
64
67
|
|
65
68
|
class Proc
|
66
|
-
# Preserve LSpace when this Proc is run.
|
69
|
+
# Preserve LSpace when this Proc is run. Returns a new Proc, a closure that
|
70
|
+
# re-enters the current LSpace when it is called.
|
67
71
|
#
|
68
72
|
# @example
|
69
73
|
# todo = LSpace.new :user_id => 2 do
|
data/lib/lspace/eventmachine.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require 'eventmachine'
|
2
2
|
require 'lspace'
|
3
|
+
|
4
|
+
# Optional module to make EventMachine preserve LSpaces in its event callbacks. Not loaded by
|
5
|
+
# default; you must +require 'lspace/eventmachine'+ to use it.
|
3
6
|
module EventMachine
|
4
7
|
|
5
8
|
# Most of the low-level EventMachine stuff goes through singleton methods on the
|
@@ -20,7 +23,7 @@ module EventMachine
|
|
20
23
|
class Connection
|
21
24
|
|
22
25
|
class << self
|
23
|
-
# As EM uses a custom implementation of
|
26
|
+
# As EM uses a custom implementation of new, the only sane way to
|
24
27
|
# set up the LSpace in advance is to override allocate.
|
25
28
|
alias_method :allocate_without_lspace, :allocate
|
26
29
|
end
|
@@ -28,11 +31,11 @@ module EventMachine
|
|
28
31
|
# Overridden allocate which sets up a new LSpace.
|
29
32
|
#
|
30
33
|
# Each connection object is run in its own LSpace, which can be
|
31
|
-
# configured by implementing the {setup_lspace} method.
|
34
|
+
# configured by implementing the {Connection#setup_lspace} method.
|
32
35
|
def self.allocate
|
33
36
|
allocate_without_lspace.instance_eval do
|
34
37
|
extend EventMachine::LSpacePreserver
|
35
|
-
LSpace.
|
38
|
+
LSpace.with do
|
36
39
|
setup_lspace
|
37
40
|
@lspace = LSpace.current
|
38
41
|
end
|
data/lib/lspace.rb
CHANGED
@@ -5,7 +5,7 @@ require File.expand_path('../lspace/class_methods', __FILE__)
|
|
5
5
|
# application's purpose, but still necessary.
|
6
6
|
#
|
7
7
|
# In many ways they are the successor to the Thread-local namespace, but they are designed
|
8
|
-
# to be active during a logical segment of code no
|
8
|
+
# to be active during a logical segment of code, no matter how you slice that code amongst
|
9
9
|
# different Threads or Fibers.
|
10
10
|
#
|
11
11
|
# The API for LSpace encourages creating a new sub-LSpace whenever you want to mutate the
|
@@ -15,7 +15,7 @@ require File.expand_path('../lspace/class_methods', __FILE__)
|
|
15
15
|
#
|
16
16
|
# @example
|
17
17
|
# require 'lspace/thread'
|
18
|
-
# LSpace.
|
18
|
+
# LSpace.with(:job_id => 1) do
|
19
19
|
# Thread.new do
|
20
20
|
# puts "processing #{LSpace[:job_id]}"
|
21
21
|
# end.join
|
@@ -47,8 +47,8 @@ class LSpace
|
|
47
47
|
# of parent LSpaces. If the key is not found anywhere, nil is returned.
|
48
48
|
#
|
49
49
|
# @example
|
50
|
-
# LSpace.
|
51
|
-
# LSpace.
|
50
|
+
# LSpace.with :user_id => 5 do
|
51
|
+
# LSpace.with :user_id => 6 do
|
52
52
|
# LSpace[:user_id] == 6
|
53
53
|
# end
|
54
54
|
# end
|
@@ -65,7 +65,7 @@ class LSpace
|
|
65
65
|
# Update the LSpace-variable with the given name.
|
66
66
|
#
|
67
67
|
# Bear in mind that any code using this LSpace will see this change, and consider
|
68
|
-
# using {LSpace.
|
68
|
+
# using {LSpace.with} instead to localize your changes.
|
69
69
|
#
|
70
70
|
# This method is mostly useful for setting up a new LSpace before any code is
|
71
71
|
# using it, and has no effect on parent LSpaces.
|
@@ -116,7 +116,7 @@ class LSpace
|
|
116
116
|
LSpace.enter(self, &block)
|
117
117
|
end
|
118
118
|
|
119
|
-
#
|
119
|
+
# Wraps a block/proc such that it runs in this LSpace when it is called.
|
120
120
|
#
|
121
121
|
# @see Proc#in_lspace
|
122
122
|
# @see LSpace.preserve
|
data/lspace.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "lspace"
|
3
|
-
s.version = "0.
|
3
|
+
s.version = "0.2"
|
4
4
|
s.platform = Gem::Platform::RUBY
|
5
5
|
s.author = "Conrad Irwin"
|
6
6
|
s.email = "conrad.irwin@gmail.com"
|
@@ -12,5 +12,6 @@ Gem::Specification.new do |s|
|
|
12
12
|
|
13
13
|
s.add_development_dependency 'rspec'
|
14
14
|
s.add_development_dependency 'pry-rescue'
|
15
|
+
s.add_development_dependency 'pry-stack_explorer'
|
15
16
|
s.add_development_dependency 'eventmachine'
|
16
17
|
end
|
data/spec/class_method_spec.rb
CHANGED
@@ -18,16 +18,16 @@ describe LSpace do
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
describe ".
|
21
|
+
describe ".with" do
|
22
22
|
it "should enter a new LSpace with the new variables set" do
|
23
|
-
LSpace.
|
23
|
+
LSpace.with(:foo => 5) do
|
24
24
|
LSpace[:foo].should == 5
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should enter a new LSpace which delegates to the current parent" do
|
29
|
-
LSpace.
|
30
|
-
LSpace.
|
29
|
+
LSpace.with(:foo => 5) do
|
30
|
+
LSpace.with(:bar => 4) do
|
31
31
|
LSpace[:foo].should == 5
|
32
32
|
end
|
33
33
|
end
|
@@ -36,7 +36,7 @@ describe LSpace do
|
|
36
36
|
|
37
37
|
describe ".clean" do
|
38
38
|
it "should enter a new LSpace with no parent" do
|
39
|
-
LSpace.
|
39
|
+
LSpace.with(:foo => 5) do
|
40
40
|
LSpace.clean do
|
41
41
|
LSpace[:foo].should == nil
|
42
42
|
end
|
@@ -45,7 +45,7 @@ describe LSpace do
|
|
45
45
|
end
|
46
46
|
|
47
47
|
describe ".enter" do
|
48
|
-
it "should
|
48
|
+
it "should with LSpace.current" do
|
49
49
|
LSpace.enter(@lspace) do
|
50
50
|
LSpace.current.should == @lspace
|
51
51
|
end
|
data/spec/core_ext_spec.rb
CHANGED
@@ -5,7 +5,7 @@ describe Module do
|
|
5
5
|
it "should define a reader for LSpace" do
|
6
6
|
klass = Class.new{ lspace_reader :user_id }
|
7
7
|
|
8
|
-
LSpace.
|
8
|
+
LSpace.with(:user_id => 8) do
|
9
9
|
klass.new.user_id.should == 8
|
10
10
|
end
|
11
11
|
end
|
@@ -40,7 +40,7 @@ describe Module do
|
|
40
40
|
end
|
41
41
|
|
42
42
|
it "should automatically preserve LSpace for blocks that are passed in" do
|
43
|
-
@task = LSpace.
|
43
|
+
@task = LSpace.with :user_id => 6 do
|
44
44
|
@klass.new{ LSpace[:user_id] }
|
45
45
|
end
|
46
46
|
|
@@ -48,7 +48,7 @@ describe Module do
|
|
48
48
|
end
|
49
49
|
|
50
50
|
it "should automatically preserve LSpace for procs that are passed in" do
|
51
|
-
@task = LSpace.
|
51
|
+
@task = LSpace.with :user_id => 6 do
|
52
52
|
@klass.new proc{ LSpace[:user_id] }
|
53
53
|
end
|
54
54
|
|
@@ -59,13 +59,22 @@ describe Module do
|
|
59
59
|
@klass.private_method_defined?(:private_test).should == true
|
60
60
|
@klass.protected_method_defined?(:protected_test).should == true
|
61
61
|
end
|
62
|
+
|
63
|
+
it "should be idempotent" do
|
64
|
+
@klass.in_lspace :initialize
|
65
|
+
|
66
|
+
LSpace.with :user_id => 9 do
|
67
|
+
@task = @klass.new{ LSpace[:user_id] }
|
68
|
+
end
|
69
|
+
@task.call.should == 9
|
70
|
+
end
|
62
71
|
end
|
63
72
|
end
|
64
73
|
|
65
74
|
describe Proc do
|
66
75
|
describe "#in_lspace" do
|
67
76
|
it "should create a wrapper which preserves the LSpace" do
|
68
|
-
p = LSpace.
|
77
|
+
p = LSpace.with(:job_id => 19) do
|
69
78
|
lambda{ LSpace[:job_id] }.in_lspace
|
70
79
|
end
|
71
80
|
|
data/spec/eventmachine_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe LSpace do
|
|
8
8
|
|
9
9
|
it "should preserve LSpace in deferrable callbacks" do
|
10
10
|
d = Class.new{ include EM::Deferrable }.new
|
11
|
-
LSpace.
|
11
|
+
LSpace.with(:foo => 2) do
|
12
12
|
d.callback do
|
13
13
|
$foo = LSpace[:foo]
|
14
14
|
end
|
@@ -19,7 +19,7 @@ describe LSpace do
|
|
19
19
|
|
20
20
|
it "should preserve LSpace in deferrable errbacks" do
|
21
21
|
d = Class.new{ include EM::Deferrable }.new
|
22
|
-
LSpace.
|
22
|
+
LSpace.with(:foo => 2) do
|
23
23
|
d.errback do
|
24
24
|
$foo = LSpace[:foo]
|
25
25
|
end
|
@@ -30,7 +30,7 @@ describe LSpace do
|
|
30
30
|
|
31
31
|
it "should preserve LSpace in EM::defer operation" do
|
32
32
|
EM::run do
|
33
|
-
LSpace.
|
33
|
+
LSpace.with(:foo => 4) do
|
34
34
|
EM::defer(lambda{
|
35
35
|
$foo = LSpace[:foo]
|
36
36
|
}, proc{
|
@@ -43,7 +43,7 @@ describe LSpace do
|
|
43
43
|
|
44
44
|
it "should preserve LSpace in EM::defer callback" do
|
45
45
|
EM::run do
|
46
|
-
LSpace.
|
46
|
+
LSpace.with(:foo => 4) do
|
47
47
|
EM::defer(lambda{
|
48
48
|
nil
|
49
49
|
}, proc{
|
@@ -58,7 +58,7 @@ describe LSpace do
|
|
58
58
|
it "should preserve LSpace in EM.next_tick" do
|
59
59
|
EM::run do
|
60
60
|
EM::next_tick do
|
61
|
-
LSpace.
|
61
|
+
LSpace.with :foo => 5 do
|
62
62
|
EM::next_tick do
|
63
63
|
$foo = LSpace[:foo]
|
64
64
|
EM::stop
|
@@ -117,7 +117,7 @@ describe LSpace do
|
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
120
|
-
LSpace.
|
120
|
+
LSpace.with(:bar => :baz) do
|
121
121
|
EM::run do
|
122
122
|
EM::start_server '0.0.0.0', 9345, server
|
123
123
|
EM::connect '127.0.0.1', 9345, client
|
data/spec/lspace_spec.rb
CHANGED
@@ -124,6 +124,7 @@ describe LSpace do
|
|
124
124
|
end
|
125
125
|
|
126
126
|
it "should revert the changed LSpace at the end of the block" do
|
127
|
+
LSpace.current.should_not == @lspace
|
127
128
|
lspace = LSpace.current
|
128
129
|
@lspace.wrap{ LSpace.current.should == @lspace }.call
|
129
130
|
LSpace.current.should == lspace
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lspace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.2'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -43,6 +43,22 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: pry-stack_explorer
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
46
62
|
- !ruby/object:Gem::Dependency
|
47
63
|
name: eventmachine
|
48
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -65,6 +81,8 @@ executables: []
|
|
65
81
|
extensions: []
|
66
82
|
extra_rdoc_files: []
|
67
83
|
files:
|
84
|
+
- .gitignore
|
85
|
+
- Gemfile
|
68
86
|
- LICENSE.MIT
|
69
87
|
- README.md
|
70
88
|
- lib/lspace.rb
|