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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cec6cd5684a1a7ff22f75898d909f3189337f981d965c71d06cc53f447f2dda1
4
- data.tar.gz: 9825e8239cea26f6b2affe8b5387a1e12f377fa0ffb6a3371bbc6a7bcc5f3910
3
+ metadata.gz: eb70c0a40e9a90e863ea43325168469cfefb1a1c6825a9eced81de68314674c6
4
+ data.tar.gz: d31d67d900e3021aec70b88ce46fd119f11a1ee5e7b7f14f0c7fcee58a57a053
5
5
  SHA512:
6
- metadata.gz: ac0557df20c73e7ff75b082a14d63e8f96e57dc1bbd288a4670e11fb1f4d402688fa17a01f9215fee5db5798b371b73d9f6fe9dfe692b5c4e8bb6c59d9577240
7
- data.tar.gz: cea1aa8e78d416966a7d876e1035f12026e3b442cad4f95dd0935d145b012eef766a7c1a1a11332680fde1bf87af3e89023dae657130f487e00c849e2cf610f6
6
+ metadata.gz: d92d93bd3e0dc94f80b73409181ee1702f44d3b4b77161861da63d10852134413de9e137f33e4848b3cbb83a0ca457a2d84de79643461a3fe8ecb42b3f4a95ed
7
+ data.tar.gz: e374f48513db58003daa361352cdbfa499048e5006b578cf36d97d043a3973dd0f7410e18a668afc2d7f03d683b562a867d69e0ea0ec90c3041491808e2afc4e
data/.gitignore CHANGED
@@ -1,5 +1,5 @@
1
1
  /.bundle/*
2
- /vendor/bunlde/*
2
+ /vendor/bundle
3
3
  /.yardoc
4
4
  /_yardoc/
5
5
  /coverage/
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ Gemfile.lock
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [1.0.0] - 2021-07-05
2
+
3
+ ### Added
4
+
5
+ - Rails ActiveJob support.
6
+
1
7
  ## [0.0.8] - 2021-06-28
2
8
 
3
9
  - Guard against early notifier.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- lambda_punch (0.0.8)
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
- 🚧 COMING SOON 🚧 - A simple ActiveJob adapter...
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. A drop-in replacement for [Sidekiq](https://github.com/mperham/sidekiq) when running Rails in AWS Lambda using the [Lamby](https://lamby.custominktech.com/) 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
@@ -4,7 +4,7 @@ require "rake/testtask"
4
4
  Rake::TestTask.new(:test) do |t|
5
5
  t.libs << "test"
6
6
  t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
7
+ t.test_files = FileList["test/cases/*_test.rb"]
8
8
  end
9
9
 
10
10
  task default: :test
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
- require 'lambda_punch/railtie' if defined?(Rails)
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
@@ -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 = 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 level
19
- l = (@level || ENV['LAMBDA_PUNCH_LOG_LEVEL'] || 'error').upcase.to_sym
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
@@ -18,8 +18,7 @@ module LambdaPunch
18
18
  begin
19
19
  job.call
20
20
  rescue => e
21
- logger.error "Queue#call::error => #{e.message}"
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
@@ -1,6 +1,7 @@
1
1
  require 'rails'
2
2
  require 'rails/engine'
3
-
3
+ require 'active_job'
4
+
4
5
  module LambdaPunch
5
6
  class Railtie < Rails::Railtie
6
7
  railtie_name :lambda_punch
@@ -1,3 +1,3 @@
1
1
  module LambdaPunch
2
- VERSION = "0.0.8"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -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
- Timeout.timeout(timeout) { @notifier.process unless invoked? }
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
- # The function's timeout in seconds using the `INVOKE` event payload's `deadlineMs` value.
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
- deadline_timeout = deadline - Time.now
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.8
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-01 00:00:00.000000000 Z
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