langis 0.1.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.
- data/Gemfile +14 -0
- data/LICENSE +202 -0
- data/NOTICE +4 -0
- data/README.md +533 -0
- data/Rakefile +57 -0
- data/VERSION +1 -0
- data/generators/langis_config_generator.rb +7 -0
- data/generators/templates/langis_config.rb +44 -0
- data/lib/langis.rb +60 -0
- data/lib/langis/dsl.rb +346 -0
- data/lib/langis/engine.rb +146 -0
- data/lib/langis/middleware.rb +135 -0
- data/lib/langis/rackish.rb +118 -0
- data/lib/langis/sinks.rb +138 -0
- data/spec/langis/dsl_spec.rb +301 -0
- data/spec/langis/engine_spec.rb +168 -0
- data/spec/langis/middleware_spec.rb +196 -0
- data/spec/langis/rackish_spec.rb +33 -0
- data/spec/langis/sinks/delayed_job_sink_spec.rb +227 -0
- data/spec/langis/sinks/redis_resque_sink_spec.rb +232 -0
- data/spec/redis.conf +132 -0
- data/spec/spec_helper.rb +8 -0
- metadata +171 -0
@@ -0,0 +1,196 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
# Helper Rackish App to save the environment from the most recent call.
|
4
|
+
class LastEnvApp
|
5
|
+
attr_reader :env
|
6
|
+
def initialize
|
7
|
+
@env = {}
|
8
|
+
end
|
9
|
+
def call(env)
|
10
|
+
@env = env
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'EnvFieldTransform' do
|
15
|
+
it 'should call to_json on a default Langis::MESSAGE_KEY header field' do
|
16
|
+
to_json_value = 'some random json value'
|
17
|
+
call_env = {
|
18
|
+
Langis::MESSAGE_KEY => to_json_value
|
19
|
+
}
|
20
|
+
message_mock = mock 'message'
|
21
|
+
message_mock.should_receive(:to_json).and_return(to_json_value)
|
22
|
+
env = {
|
23
|
+
Langis::MESSAGE_KEY => message_mock
|
24
|
+
}
|
25
|
+
app_mock = mock 'app'
|
26
|
+
app_mock.should_receive(:call).with(call_env)
|
27
|
+
@middleware = Langis::Middleware::EnvFieldTransform.new app_mock
|
28
|
+
@middleware.call(env)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should call to_json on a "custom" header field' do
|
32
|
+
fieldname = "custom_field"
|
33
|
+
to_json_value = 'some random json value'
|
34
|
+
call_env = {
|
35
|
+
fieldname => to_json_value
|
36
|
+
}
|
37
|
+
message_mock = mock 'message'
|
38
|
+
message_mock.should_receive(:to_json).and_return(to_json_value)
|
39
|
+
env = {
|
40
|
+
fieldname => message_mock
|
41
|
+
}
|
42
|
+
app_mock = mock 'app'
|
43
|
+
app_mock.should_receive(:call).with(call_env)
|
44
|
+
@middleware = Langis::Middleware::EnvFieldTransform.new(
|
45
|
+
app_mock,
|
46
|
+
:key => fieldname)
|
47
|
+
@middleware.call(env)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should call to_json on a "custom" header field with args' do
|
51
|
+
fieldname = "custom_field"
|
52
|
+
to_json_value = 'some random json value'
|
53
|
+
to_args = [1, 2, 3, 4, 5]
|
54
|
+
call_env = {
|
55
|
+
fieldname => to_json_value
|
56
|
+
}
|
57
|
+
message_mock = mock 'message'
|
58
|
+
message_mock.should_receive(:to_json).
|
59
|
+
with(*to_args).
|
60
|
+
and_return(to_json_value)
|
61
|
+
env = {
|
62
|
+
fieldname => message_mock
|
63
|
+
}
|
64
|
+
app_mock = mock 'app'
|
65
|
+
app_mock.should_receive(:call).with(call_env)
|
66
|
+
@middleware = Langis::Middleware::EnvFieldTransform.new(
|
67
|
+
app_mock,
|
68
|
+
:to_args => to_args,
|
69
|
+
:key => fieldname)
|
70
|
+
@middleware.call(env)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should call "custom_to_method" on a "custom" header field' do
|
74
|
+
fieldname = "custom_field"
|
75
|
+
to_value = 'some random value'
|
76
|
+
call_env = {
|
77
|
+
fieldname => to_value
|
78
|
+
}
|
79
|
+
message_mock = mock 'message'
|
80
|
+
message_mock.should_receive(:custom_to_method).and_return(to_value)
|
81
|
+
env = {
|
82
|
+
fieldname => message_mock
|
83
|
+
}
|
84
|
+
app_mock = mock 'app'
|
85
|
+
app_mock.should_receive(:call).with(call_env)
|
86
|
+
@middleware = Langis::Middleware::EnvFieldTransform.new(
|
87
|
+
app_mock,
|
88
|
+
:to_method => :custom_to_method,
|
89
|
+
:key => fieldname)
|
90
|
+
@middleware.call(env)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe 'Parameterizer' do
|
95
|
+
it 'should form an empty list' do
|
96
|
+
app = LastEnvApp.new
|
97
|
+
middleware = Langis::Middleware::Parameterizer.new app
|
98
|
+
middleware.call {}
|
99
|
+
app.env[Langis::MESSAGE_KEY].should eql []
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should form a static list' do
|
103
|
+
app = LastEnvApp.new
|
104
|
+
middleware = Langis::Middleware::Parameterizer.new app, '1', '2', '3'
|
105
|
+
middleware.call {}
|
106
|
+
app.env[Langis::MESSAGE_KEY].should eql ['1', '2', '3']
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should execute callables to form parameters using env values' do
|
110
|
+
app = LastEnvApp.new
|
111
|
+
middleware = Langis::Middleware::Parameterizer.new app,
|
112
|
+
'1',
|
113
|
+
lambda { |env|
|
114
|
+
env['input2']
|
115
|
+
},
|
116
|
+
lambda { |env|
|
117
|
+
env['input3']
|
118
|
+
},
|
119
|
+
'4'
|
120
|
+
middleware.call 'input2' => '2', 'input3' => '3'
|
121
|
+
app.env[Langis::MESSAGE_KEY].should eql ['1', '2', '3', '4']
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should save to an alternate key' do
|
125
|
+
app = LastEnvApp.new
|
126
|
+
middleware = Langis::Middleware::Parameterizer.new app,
|
127
|
+
'1',
|
128
|
+
lambda { |env|
|
129
|
+
env['input2']
|
130
|
+
},
|
131
|
+
'3',
|
132
|
+
:env_key => 'A'
|
133
|
+
middleware.call 'input2' => '2'
|
134
|
+
app.env['A'].should eql ['1', '2', '3']
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe 'MessageTypeFilter' do
|
139
|
+
it 'should filter an unlisted type' do
|
140
|
+
message_type_1 = 'MyMessageType1'
|
141
|
+
message_type_2 = 'MyMessageType2'
|
142
|
+
message_type_3 = 'MyMessageType3'
|
143
|
+
message_type_4 = 'MyMessageType4'
|
144
|
+
env = {
|
145
|
+
Langis::MESSAGE_TYPE_KEY => message_type_1
|
146
|
+
}
|
147
|
+
# Set up a mock that won't receive any calls.
|
148
|
+
app_mock = mock 'app'
|
149
|
+
@middleware = Langis::Middleware::MessageTypeFilter.new(
|
150
|
+
app_mock,
|
151
|
+
message_type_2,
|
152
|
+
message_type_3,
|
153
|
+
message_type_4)
|
154
|
+
@middleware.call(env)
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'should allow a listed type through' do
|
158
|
+
message_type_1 = 'MyMessageType1'
|
159
|
+
message_type_2 = 'MyMessageType2'
|
160
|
+
message_type_3 = 'MyMessageType3'
|
161
|
+
message_type_4 = 'MyMessageType4'
|
162
|
+
env = {
|
163
|
+
Langis::MESSAGE_TYPE_KEY => message_type_3
|
164
|
+
}
|
165
|
+
app_mock = mock 'app'
|
166
|
+
app_mock.should_receive(:call).with(env)
|
167
|
+
@middleware = Langis::Middleware::MessageTypeFilter.new(
|
168
|
+
app_mock,
|
169
|
+
message_type_2,
|
170
|
+
message_type_3,
|
171
|
+
message_type_4)
|
172
|
+
@middleware.call(env)
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'should not let anything through' do
|
176
|
+
message_type_1 = 'MyMessageType1'
|
177
|
+
message_type_2 = 'MyMessageType2'
|
178
|
+
message_type_3 = 'MyMessageType3'
|
179
|
+
env1 = {
|
180
|
+
Langis::MESSAGE_TYPE_KEY => message_type_1
|
181
|
+
}
|
182
|
+
env2 = {
|
183
|
+
Langis::MESSAGE_TYPE_KEY => message_type_1
|
184
|
+
}
|
185
|
+
env3 = {
|
186
|
+
Langis::MESSAGE_TYPE_KEY => message_type_1
|
187
|
+
}
|
188
|
+
|
189
|
+
# Set up a mock that won't receive any calls.
|
190
|
+
app_mock = mock 'app'
|
191
|
+
@middleware = Langis::Middleware::MessageTypeFilter.new app_mock
|
192
|
+
@middleware.call(env1)
|
193
|
+
@middleware.call(env2)
|
194
|
+
@middleware.call(env3)
|
195
|
+
end
|
196
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Langis::Rackish::RackishJob do
|
4
|
+
before :all do
|
5
|
+
Langis::Rackish::RackishJob.register_rackish_app('my_app', lambda { |env|
|
6
|
+
[200, {}, ["Hello World, #{env['name']}"]]
|
7
|
+
})
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should raise an error on an unregistered app' do
|
11
|
+
lambda {
|
12
|
+
Langis::Rackish::RackishJob.perform 'unregistered_app'
|
13
|
+
}.should raise_error(Langis::Rackish::NotFoundError)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should properly call a registered app using class method' do
|
17
|
+
result = Langis::Rackish::RackishJob.perform 'my_app', 'name' => 'Langis'
|
18
|
+
result.should eql [200, {}, ["Hello World, Langis"]]
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should properly call a registered app using instance method' do
|
22
|
+
rackish_job = Langis::Rackish::RackishJob.new 'my_app', 'name' => 'Langis'
|
23
|
+
result = rackish_job.perform
|
24
|
+
result.should eql [200, {}, ["Hello World, Langis"]]
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should handle a nil env by instance method' do
|
28
|
+
rackish_job = Langis::Rackish::RackishJob.new 'my_app', nil
|
29
|
+
result = rackish_job.perform
|
30
|
+
result.should eql [200, {}, ["Hello World, "]]
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
include Temping
|
4
|
+
|
5
|
+
# We create a plain no-op DelayedJob job class.
|
6
|
+
class MyJob < Struct.new(:message)
|
7
|
+
def perform
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# A helper class to test transforms
|
13
|
+
class Transformable
|
14
|
+
def initialize(message, args)
|
15
|
+
@message = message
|
16
|
+
@args = args
|
17
|
+
end
|
18
|
+
|
19
|
+
def transformer(*args)
|
20
|
+
raise 'Transform Arguments mismatch' unless @args == args
|
21
|
+
return @message
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'DelayedJobSink' do
|
26
|
+
before :all do
|
27
|
+
# We have to set up the Delayed::Job constant for this test
|
28
|
+
Delayed::Worker.backend = :active_record
|
29
|
+
|
30
|
+
create_model :delayed_jobs do
|
31
|
+
with_columns do |table|
|
32
|
+
table.integer :priority, :default => 0
|
33
|
+
table.integer :attempts, :default => 0
|
34
|
+
table.text :handler
|
35
|
+
table.string :last_error
|
36
|
+
table.datetime :run_at
|
37
|
+
table.datetime :locked_at
|
38
|
+
table.datetime :failed_at
|
39
|
+
table.string :locked_by
|
40
|
+
table.timestamps
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
after :each do
|
46
|
+
DelayedJob.all.each do |job|
|
47
|
+
job.delete
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should create a delayed job' do
|
52
|
+
my_message = 'Hello World'
|
53
|
+
env = {
|
54
|
+
Langis::MESSAGE_KEY => my_message
|
55
|
+
}
|
56
|
+
sink = Langis::Sinks.delayed_job(MyJob)
|
57
|
+
sink.call(env)
|
58
|
+
delayed_jobs = DelayedJob.all
|
59
|
+
delayed_jobs.size.should eql 1
|
60
|
+
delayed_job = delayed_jobs[0]
|
61
|
+
delayed_job.priority.should eql 0
|
62
|
+
delayed_job.run_at.should_not be_nil
|
63
|
+
my_job = YAML::load delayed_job.handler
|
64
|
+
my_job.message.should eql my_message
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should create a delayed job with alternate priority' do
|
68
|
+
my_priority = 10239
|
69
|
+
my_message = 'Hello World'
|
70
|
+
env = {
|
71
|
+
Langis::MESSAGE_KEY => my_message
|
72
|
+
}
|
73
|
+
sink = Langis::Sinks.delayed_job(MyJob, :priority => my_priority)
|
74
|
+
sink.call(env)
|
75
|
+
delayed_jobs = DelayedJob.all
|
76
|
+
delayed_jobs.size.should eql 1
|
77
|
+
delayed_job = delayed_jobs[0]
|
78
|
+
delayed_job.priority.should eql my_priority
|
79
|
+
delayed_job.run_at.should_not be_nil
|
80
|
+
my_job = YAML::load delayed_job.handler
|
81
|
+
my_job.message.should eql my_message
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should create a delayed job with alternate run_at' do
|
85
|
+
my_run_at = Time.now
|
86
|
+
my_message = 'Hello World'
|
87
|
+
env = {
|
88
|
+
Langis::MESSAGE_KEY => my_message
|
89
|
+
}
|
90
|
+
sink = Langis::Sinks.delayed_job(MyJob, :run_at => my_run_at)
|
91
|
+
sink.call(env)
|
92
|
+
delayed_jobs = DelayedJob.all
|
93
|
+
delayed_jobs.size.should eql 1
|
94
|
+
delayed_job = delayed_jobs[0]
|
95
|
+
delayed_job.priority.should eql 0
|
96
|
+
delayed_job.run_at.to_s.should eql my_run_at.to_s
|
97
|
+
my_job = YAML::load delayed_job.handler
|
98
|
+
my_job.message.should eql my_message
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should create a delayed job with message from alternate key' do
|
102
|
+
my_message = 'Hello World'
|
103
|
+
my_alternate_key = 'MyAlternateKey'
|
104
|
+
env = {
|
105
|
+
my_alternate_key => my_message
|
106
|
+
}
|
107
|
+
sink = Langis::Sinks.delayed_job(MyJob, :env_key => my_alternate_key)
|
108
|
+
sink.call(env)
|
109
|
+
delayed_jobs = DelayedJob.all
|
110
|
+
delayed_jobs.size.should eql 1
|
111
|
+
delayed_job = delayed_jobs[0]
|
112
|
+
delayed_job.priority.should eql 0
|
113
|
+
delayed_job.run_at.should_not be_nil
|
114
|
+
my_job = YAML::load delayed_job.handler
|
115
|
+
my_job.message.should eql my_message
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'should create a delayed job with a message transform' do
|
119
|
+
transform_message = "Hello Transformed World"
|
120
|
+
transform_arguments = [1,2,3,4]
|
121
|
+
my_message = Transformable.new(
|
122
|
+
transform_message,
|
123
|
+
transform_arguments)
|
124
|
+
env = {
|
125
|
+
Langis::MESSAGE_KEY => my_message
|
126
|
+
}
|
127
|
+
sink = Langis::Sinks.delayed_job(MyJob,
|
128
|
+
:transform => :transformer,
|
129
|
+
:transform_args => transform_arguments)
|
130
|
+
sink.call(env)
|
131
|
+
delayed_jobs = DelayedJob.all
|
132
|
+
delayed_jobs.size.should eql 1
|
133
|
+
delayed_job = delayed_jobs[0]
|
134
|
+
delayed_job.priority.should eql 0
|
135
|
+
delayed_job.run_at.should_not be_nil
|
136
|
+
my_job = YAML::load delayed_job.handler
|
137
|
+
my_job.message.should eql transform_message
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'should create a delayed job with a message transform, with nil args' do
|
141
|
+
transform_message = "Hello Transformed World"
|
142
|
+
transform_arguments = []
|
143
|
+
my_message = Transformable.new(
|
144
|
+
transform_message,
|
145
|
+
transform_arguments)
|
146
|
+
env = {
|
147
|
+
Langis::MESSAGE_KEY => my_message
|
148
|
+
}
|
149
|
+
sink = Langis::Sinks.delayed_job(MyJob,
|
150
|
+
:transform => :transformer,
|
151
|
+
:transform_args => nil)
|
152
|
+
sink.call(env)
|
153
|
+
delayed_jobs = DelayedJob.all
|
154
|
+
delayed_jobs.size.should eql 1
|
155
|
+
delayed_job = delayed_jobs[0]
|
156
|
+
delayed_job.priority.should eql 0
|
157
|
+
delayed_job.run_at.should_not be_nil
|
158
|
+
my_job = YAML::load delayed_job.handler
|
159
|
+
my_job.message.should eql transform_message
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should create a delayed job with a message transform, without args' do
|
163
|
+
transform_message = "Hello Transformed World"
|
164
|
+
transform_arguments = []
|
165
|
+
my_message = Transformable.new(
|
166
|
+
transform_message,
|
167
|
+
transform_arguments)
|
168
|
+
env = {
|
169
|
+
Langis::MESSAGE_KEY => my_message
|
170
|
+
}
|
171
|
+
sink = Langis::Sinks.delayed_job(MyJob,
|
172
|
+
:transform => :transformer)
|
173
|
+
sink.call(env)
|
174
|
+
delayed_jobs = DelayedJob.all
|
175
|
+
delayed_jobs.size.should eql 1
|
176
|
+
delayed_job = delayed_jobs[0]
|
177
|
+
delayed_job.priority.should eql 0
|
178
|
+
delayed_job.run_at.should_not be_nil
|
179
|
+
my_job = YAML::load delayed_job.handler
|
180
|
+
my_job.message.should eql transform_message
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'should create a delayed job with a message transform, non Array arg' do
|
184
|
+
transform_message = "Hello Transformed World"
|
185
|
+
one_arg = "ITSY BITSY ONE"
|
186
|
+
transform_arguments = [one_arg]
|
187
|
+
my_message = Transformable.new(
|
188
|
+
transform_message,
|
189
|
+
transform_arguments)
|
190
|
+
env = {
|
191
|
+
Langis::MESSAGE_KEY => my_message
|
192
|
+
}
|
193
|
+
sink = Langis::Sinks.delayed_job(MyJob,
|
194
|
+
:transform => :transformer,
|
195
|
+
:transform_args => one_arg)
|
196
|
+
sink.call(env)
|
197
|
+
delayed_jobs = DelayedJob.all
|
198
|
+
delayed_jobs.size.should eql 1
|
199
|
+
delayed_job = delayed_jobs[0]
|
200
|
+
delayed_job.priority.should eql 0
|
201
|
+
delayed_job.run_at.should_not be_nil
|
202
|
+
my_job = YAML::load delayed_job.handler
|
203
|
+
my_job.message.should eql transform_message
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'should create a delayed job with all options changed' do
|
207
|
+
my_message = 'Hello World'
|
208
|
+
my_priority = 10239
|
209
|
+
my_alternate_key = 'MyAlternateKey'
|
210
|
+
my_run_at = Time.now
|
211
|
+
env = {
|
212
|
+
my_alternate_key => my_message
|
213
|
+
}
|
214
|
+
sink = Langis::Sinks.delayed_job(MyJob,
|
215
|
+
:env_key => my_alternate_key,
|
216
|
+
:priority => my_priority,
|
217
|
+
:run_at => my_run_at)
|
218
|
+
sink.call(env)
|
219
|
+
delayed_jobs = DelayedJob.all
|
220
|
+
delayed_jobs.size.should eql 1
|
221
|
+
delayed_job = delayed_jobs[0]
|
222
|
+
delayed_job.priority.should eql my_priority
|
223
|
+
delayed_job.run_at.to_s.should eql my_run_at.to_s
|
224
|
+
my_job = YAML::load delayed_job.handler
|
225
|
+
my_job.message.should eql my_message
|
226
|
+
end
|
227
|
+
end
|