lambda_punch 0.0.8 → 1.0.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/.gitignore +2 -1
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +133 -1
- data/README.md +14 -2
- data/Rakefile +1 -1
- data/lambda_punch.gemspec +3 -0
- data/lib/lambda_punch.rb +14 -1
- data/lib/lambda_punch/logger.rb +9 -9
- data/lib/lambda_punch/queue.rb +1 -6
- data/lib/lambda_punch/rails/active_job.rb +16 -0
- data/lib/lambda_punch/railtie.rb +2 -1
- data/lib/lambda_punch/version.rb +1 -1
- data/lib/lambda_punch/worker.rb +23 -6
- metadata +45 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb70c0a40e9a90e863ea43325168469cfefb1a1c6825a9eced81de68314674c6
|
4
|
+
data.tar.gz: d31d67d900e3021aec70b88ce46fd119f11a1ee5e7b7f14f0c7fcee58a57a053
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d92d93bd3e0dc94f80b73409181ee1702f44d3b4b77161861da63d10852134413de9e137f33e4848b3cbb83a0ca457a2d84de79643461a3fe8ecb42b3f4a95ed
|
7
|
+
data.tar.gz: e374f48513db58003daa361352cdbfa499048e5006b578cf36d97d043a3973dd0f7410e18a668afc2d7f03d683b562a867d69e0ea0ec90c3041491808e2afc4e
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
lambda_punch (0.0
|
4
|
+
lambda_punch (1.0.0)
|
5
5
|
concurrent-ruby
|
6
6
|
rake
|
7
7
|
rb-inotify
|
@@ -10,13 +10,142 @@ PATH
|
|
10
10
|
GEM
|
11
11
|
remote: https://rubygems.org/
|
12
12
|
specs:
|
13
|
+
actioncable (6.1.4)
|
14
|
+
actionpack (= 6.1.4)
|
15
|
+
activesupport (= 6.1.4)
|
16
|
+
nio4r (~> 2.0)
|
17
|
+
websocket-driver (>= 0.6.1)
|
18
|
+
actionmailbox (6.1.4)
|
19
|
+
actionpack (= 6.1.4)
|
20
|
+
activejob (= 6.1.4)
|
21
|
+
activerecord (= 6.1.4)
|
22
|
+
activestorage (= 6.1.4)
|
23
|
+
activesupport (= 6.1.4)
|
24
|
+
mail (>= 2.7.1)
|
25
|
+
actionmailer (6.1.4)
|
26
|
+
actionpack (= 6.1.4)
|
27
|
+
actionview (= 6.1.4)
|
28
|
+
activejob (= 6.1.4)
|
29
|
+
activesupport (= 6.1.4)
|
30
|
+
mail (~> 2.5, >= 2.5.4)
|
31
|
+
rails-dom-testing (~> 2.0)
|
32
|
+
actionpack (6.1.4)
|
33
|
+
actionview (= 6.1.4)
|
34
|
+
activesupport (= 6.1.4)
|
35
|
+
rack (~> 2.0, >= 2.0.9)
|
36
|
+
rack-test (>= 0.6.3)
|
37
|
+
rails-dom-testing (~> 2.0)
|
38
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
39
|
+
actiontext (6.1.4)
|
40
|
+
actionpack (= 6.1.4)
|
41
|
+
activerecord (= 6.1.4)
|
42
|
+
activestorage (= 6.1.4)
|
43
|
+
activesupport (= 6.1.4)
|
44
|
+
nokogiri (>= 1.8.5)
|
45
|
+
actionview (6.1.4)
|
46
|
+
activesupport (= 6.1.4)
|
47
|
+
builder (~> 3.1)
|
48
|
+
erubi (~> 1.4)
|
49
|
+
rails-dom-testing (~> 2.0)
|
50
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
51
|
+
activejob (6.1.4)
|
52
|
+
activesupport (= 6.1.4)
|
53
|
+
globalid (>= 0.3.6)
|
54
|
+
activemodel (6.1.4)
|
55
|
+
activesupport (= 6.1.4)
|
56
|
+
activerecord (6.1.4)
|
57
|
+
activemodel (= 6.1.4)
|
58
|
+
activesupport (= 6.1.4)
|
59
|
+
activestorage (6.1.4)
|
60
|
+
actionpack (= 6.1.4)
|
61
|
+
activejob (= 6.1.4)
|
62
|
+
activerecord (= 6.1.4)
|
63
|
+
activesupport (= 6.1.4)
|
64
|
+
marcel (~> 1.0.0)
|
65
|
+
mini_mime (>= 1.1.0)
|
66
|
+
activesupport (6.1.4)
|
67
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
68
|
+
i18n (>= 1.6, < 2)
|
69
|
+
minitest (>= 5.1)
|
70
|
+
tzinfo (~> 2.0)
|
71
|
+
zeitwerk (~> 2.3)
|
72
|
+
builder (3.2.4)
|
73
|
+
coderay (1.1.3)
|
13
74
|
concurrent-ruby (1.1.9)
|
75
|
+
crass (1.0.6)
|
76
|
+
erubi (1.10.0)
|
14
77
|
ffi (1.15.3)
|
78
|
+
globalid (0.4.2)
|
79
|
+
activesupport (>= 4.2.0)
|
80
|
+
i18n (1.8.10)
|
81
|
+
concurrent-ruby (~> 1.0)
|
82
|
+
loofah (2.10.0)
|
83
|
+
crass (~> 1.0.2)
|
84
|
+
nokogiri (>= 1.5.9)
|
85
|
+
mail (2.7.1)
|
86
|
+
mini_mime (>= 0.1.1)
|
87
|
+
marcel (1.0.1)
|
88
|
+
method_source (1.0.0)
|
89
|
+
mini_mime (1.1.0)
|
15
90
|
minitest (5.14.4)
|
91
|
+
minitest-focus (1.3.1)
|
92
|
+
minitest (>= 4, < 6)
|
93
|
+
nio4r (2.5.7)
|
94
|
+
nokogiri (1.11.7-x86_64-darwin)
|
95
|
+
racc (~> 1.4)
|
96
|
+
nokogiri (1.11.7-x86_64-linux)
|
97
|
+
racc (~> 1.4)
|
98
|
+
pry (0.14.1)
|
99
|
+
coderay (~> 1.1)
|
100
|
+
method_source (~> 1.0)
|
101
|
+
racc (1.5.2)
|
102
|
+
rack (2.2.3)
|
103
|
+
rack-test (1.1.0)
|
104
|
+
rack (>= 1.0, < 3)
|
105
|
+
rails (6.1.4)
|
106
|
+
actioncable (= 6.1.4)
|
107
|
+
actionmailbox (= 6.1.4)
|
108
|
+
actionmailer (= 6.1.4)
|
109
|
+
actionpack (= 6.1.4)
|
110
|
+
actiontext (= 6.1.4)
|
111
|
+
actionview (= 6.1.4)
|
112
|
+
activejob (= 6.1.4)
|
113
|
+
activemodel (= 6.1.4)
|
114
|
+
activerecord (= 6.1.4)
|
115
|
+
activestorage (= 6.1.4)
|
116
|
+
activesupport (= 6.1.4)
|
117
|
+
bundler (>= 1.15.0)
|
118
|
+
railties (= 6.1.4)
|
119
|
+
sprockets-rails (>= 2.0.0)
|
120
|
+
rails-dom-testing (2.0.3)
|
121
|
+
activesupport (>= 4.2.0)
|
122
|
+
nokogiri (>= 1.6)
|
123
|
+
rails-html-sanitizer (1.3.0)
|
124
|
+
loofah (~> 2.3)
|
125
|
+
railties (6.1.4)
|
126
|
+
actionpack (= 6.1.4)
|
127
|
+
activesupport (= 6.1.4)
|
128
|
+
method_source
|
129
|
+
rake (>= 0.13)
|
130
|
+
thor (~> 1.0)
|
16
131
|
rake (13.0.3)
|
17
132
|
rb-inotify (0.10.1)
|
18
133
|
ffi (~> 1.0)
|
134
|
+
sprockets (4.0.2)
|
135
|
+
concurrent-ruby (~> 1.0)
|
136
|
+
rack (> 1, < 3)
|
137
|
+
sprockets-rails (3.2.2)
|
138
|
+
actionpack (>= 4.0)
|
139
|
+
activesupport (>= 4.0)
|
140
|
+
sprockets (>= 3.0.0)
|
141
|
+
thor (1.1.0)
|
19
142
|
timeout (0.1.1)
|
143
|
+
tzinfo (2.0.4)
|
144
|
+
concurrent-ruby (~> 1.0)
|
145
|
+
websocket-driver (0.7.5)
|
146
|
+
websocket-extensions (>= 0.1.0)
|
147
|
+
websocket-extensions (0.1.5)
|
148
|
+
zeitwerk (2.4.2)
|
20
149
|
|
21
150
|
PLATFORMS
|
22
151
|
x86_64-darwin-19
|
@@ -25,6 +154,9 @@ PLATFORMS
|
|
25
154
|
DEPENDENCIES
|
26
155
|
lambda_punch!
|
27
156
|
minitest
|
157
|
+
minitest-focus
|
158
|
+
pry
|
159
|
+
rails
|
28
160
|
rake
|
29
161
|
|
30
162
|
BUNDLED WITH
|
data/README.md
CHANGED
@@ -72,7 +72,11 @@ end
|
|
72
72
|
|
73
73
|
### ActiveJob
|
74
74
|
|
75
|
-
|
75
|
+
You can use LambdaPunch with Rails' ActiveJob. **For a more robust background job solution, please consider using AWS SQS with the [Lambdakiq](https://github.com/customink/lambdakiq) gem.**
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
config.active_job.queue_adapter = :lambda_punch
|
79
|
+
```
|
76
80
|
|
77
81
|
### Timeouts
|
78
82
|
|
@@ -80,7 +84,7 @@ Your function's timeout is the max amount to handle the request and process all
|
|
80
84
|
|
81
85
|
If your application integrates with API Gateway (which has a 30 second timeout) then it is possible your function can be set with a higher timeout to perform background work. Since work is done after each invoke, the LambdaPunch queue should be empty when your function receives the `SHUTDOWN` event. If jobs are in the queue when this happens they will have two seconds max to work them down before being lost.
|
82
86
|
|
83
|
-
**For a more robust background job solution, please consider using AWS SQS with the [Lambdakiq](https://github.com/customink/lambdakiq) gem
|
87
|
+
**For a more robust background job solution, please consider using AWS SQS with the [Lambdakiq](https://github.com/customink/lambdakiq) gem.**
|
84
88
|
|
85
89
|
### Logging
|
86
90
|
|
@@ -92,6 +96,14 @@ Environment:
|
|
92
96
|
LAMBDA_PUNCH_LOG_LEVEL: debug
|
93
97
|
```
|
94
98
|
|
99
|
+
### Errors
|
100
|
+
|
101
|
+
As jobs are worked off the queue, all job errors are simply logged. If you want to customize this, you can set your own error handler.
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
LambdaPunch.error_handler = lambda { |e| ... }
|
105
|
+
```
|
106
|
+
|
95
107
|
## 📊 CloudWatch Metrics
|
96
108
|
|
97
109
|
When using Extensions, your function's CloudWatch `Duration` metrics will be the sum of your response time combined with your extension's execution time. For example, if your request takes `200ms` to respond but your background task takes `1000ms` your duration will be a combined `1200ms`. For more details see the _"Performance impact and extension overhead"_ section of the [Lambda Extensions API
|
data/Rakefile
CHANGED
data/lambda_punch.gemspec
CHANGED
@@ -22,4 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_dependency "rake"
|
23
23
|
spec.add_dependency "rb-inotify"
|
24
24
|
spec.add_dependency "timeout"
|
25
|
+
spec.add_development_dependency "minitest-focus"
|
26
|
+
spec.add_development_dependency "pry"
|
27
|
+
spec.add_development_dependency "rails"
|
25
28
|
end
|
data/lib/lambda_punch.rb
CHANGED
@@ -13,7 +13,10 @@ require 'lambda_punch/server'
|
|
13
13
|
require 'lambda_punch/worker'
|
14
14
|
require 'lambda_punch/version'
|
15
15
|
require 'lambda_punch/notifier'
|
16
|
-
|
16
|
+
if defined?(Rails)
|
17
|
+
require 'lambda_punch/railtie'
|
18
|
+
require 'lambda_punch/rails/active_job'
|
19
|
+
end
|
17
20
|
|
18
21
|
module LambdaPunch
|
19
22
|
|
@@ -45,6 +48,16 @@ module LambdaPunch
|
|
45
48
|
Notifier.handled!(context)
|
46
49
|
end
|
47
50
|
|
51
|
+
def error_handler
|
52
|
+
@error_handler ||= lambda do |e|
|
53
|
+
logger.error "Queue#call::error => #{e.message}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def error_handler=(func)
|
58
|
+
@error_handler = func
|
59
|
+
end
|
60
|
+
|
48
61
|
extend self
|
49
62
|
|
50
63
|
end
|
data/lib/lambda_punch/logger.rb
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
module LambdaPunch
|
2
2
|
class Logger
|
3
3
|
|
4
|
+
attr_reader :level
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@level = (ENV['LAMBDA_PUNCH_LOG_LEVEL'] || 'error').upcase.to_sym
|
8
|
+
end
|
9
|
+
|
4
10
|
def logger
|
5
11
|
@logger ||= ::Logger.new(STDOUT).tap do |l|
|
6
|
-
l.level =
|
12
|
+
l.level = logger_level
|
7
13
|
l.formatter = proc { |_s, _d, _p, m| "[LambdaPunch] #{m}\n" }
|
8
14
|
end
|
9
15
|
end
|
10
16
|
|
11
|
-
def level=(value)
|
12
|
-
@level = value.to_s
|
13
|
-
@logger = nil
|
14
|
-
end
|
15
|
-
|
16
17
|
private
|
17
18
|
|
18
|
-
def
|
19
|
-
|
20
|
-
::Logger.const_defined?(l) ? ::Logger.const_get(l) : ::Logger::ERROR
|
19
|
+
def logger_level
|
20
|
+
::Logger.const_defined?(@level) ? ::Logger.const_get(@level) : ::Logger::ERROR
|
21
21
|
end
|
22
22
|
|
23
23
|
end
|
data/lib/lambda_punch/queue.rb
CHANGED
@@ -18,8 +18,7 @@ module LambdaPunch
|
|
18
18
|
begin
|
19
19
|
job.call
|
20
20
|
rescue => e
|
21
|
-
|
22
|
-
# ...
|
21
|
+
LambdaPunch.error_handler.call(e)
|
23
22
|
end
|
24
23
|
end
|
25
24
|
true
|
@@ -33,9 +32,5 @@ module LambdaPunch
|
|
33
32
|
self.class.jobs
|
34
33
|
end
|
35
34
|
|
36
|
-
def logger
|
37
|
-
LambdaPunch.logger
|
38
|
-
end
|
39
|
-
|
40
35
|
end
|
41
36
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ActiveJob
|
2
|
+
module QueueAdapters
|
3
|
+
class LambdaPunchAdapter
|
4
|
+
|
5
|
+
def enqueue(job, options = {})
|
6
|
+
job_data = job.serialize
|
7
|
+
LambdaPunch.push { ActiveJob::Base.execute(job_data) }
|
8
|
+
end
|
9
|
+
|
10
|
+
def enqueue_at(job, timestamp)
|
11
|
+
enqueue(job)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/lambda_punch/railtie.rb
CHANGED
data/lib/lambda_punch/version.rb
CHANGED
data/lib/lambda_punch/worker.rb
CHANGED
@@ -64,7 +64,7 @@ module LambdaPunch
|
|
64
64
|
# also ensures any clean up is done. For example, closing file notifications.
|
65
65
|
#
|
66
66
|
def call
|
67
|
-
|
67
|
+
timeout { @notifier.process unless invoked? }
|
68
68
|
rescue Timeout::Error
|
69
69
|
logger.error "Worker#call => Function timeout reached."
|
70
70
|
ensure
|
@@ -76,10 +76,11 @@ module LambdaPunch
|
|
76
76
|
|
77
77
|
# The Notifier's watch handler would set this instance variable to `true`. We also return `true`
|
78
78
|
# if the extension's invoke palyload event has a `requestId` matching what the handler has written
|
79
|
-
# to the `LambdaPunch::Notifier` file location. See also `request_ids_match?` method.
|
79
|
+
# to the `LambdaPunch::Notifier` file location. See also `request_ids_match?` method. Lastly if
|
80
|
+
# the timeout
|
80
81
|
#
|
81
82
|
def invoked?
|
82
|
-
@invoked || request_ids_match?
|
83
|
+
@invoked || request_ids_match? || timed_out?
|
83
84
|
end
|
84
85
|
|
85
86
|
# The unique AWS reqeust id that both the extension and handler receive for each invoke. This one
|
@@ -102,13 +103,29 @@ module LambdaPunch
|
|
102
103
|
request_id_payload == (request_id_notifier || Notifier.request_id)
|
103
104
|
end
|
104
105
|
|
105
|
-
#
|
106
|
+
# A safe timeout method which accounts for a 0 or negative timeout value.
|
106
107
|
#
|
107
108
|
def timeout
|
109
|
+
@timeout = timeout_seconds
|
110
|
+
if timed_out?
|
111
|
+
yield
|
112
|
+
else
|
113
|
+
Timeout.timeout(@timeout) { yield }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Helps guard for deadline milliseconds in the past.
|
118
|
+
#
|
119
|
+
def timed_out?
|
120
|
+
@timeout == 0 || @timeout < 0
|
121
|
+
end
|
122
|
+
|
123
|
+
# The function's timeout in seconds using the `INVOKE` event payload's `deadlineMs` value.
|
124
|
+
#
|
125
|
+
def timeout_seconds
|
108
126
|
deadline_milliseconds = @event_payload['deadlineMs']
|
109
127
|
deadline = Time.at(deadline_milliseconds / 1000.0)
|
110
|
-
|
111
|
-
deadline_timeout > 0 ? deadline_timeout : 0
|
128
|
+
deadline - Time.now
|
112
129
|
end
|
113
130
|
|
114
131
|
# Our `LambdaPunch::Notifier` instance callback.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lambda_punch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ken Collins
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-07-
|
11
|
+
date: 2021-07-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -66,6 +66,48 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest-focus
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rails
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
69
111
|
description: 'LambdaPunch: Async Processing using Lambda Extensions'
|
70
112
|
email:
|
71
113
|
- ken@metaskills.net
|
@@ -99,6 +141,7 @@ files:
|
|
99
141
|
- lib/lambda_punch/logger.rb
|
100
142
|
- lib/lambda_punch/notifier.rb
|
101
143
|
- lib/lambda_punch/queue.rb
|
144
|
+
- lib/lambda_punch/rails/active_job.rb
|
102
145
|
- lib/lambda_punch/railtie.rb
|
103
146
|
- lib/lambda_punch/server.rb
|
104
147
|
- lib/lambda_punch/tasks/install.rake
|