funktor 0.2.1

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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +6 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +7 -0
  7. data/Gemfile.lock +84 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +154 -0
  10. data/Rakefile +6 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/exe/funktor +13 -0
  14. data/exe/funktor-deploy +8 -0
  15. data/funktor.gemspec +38 -0
  16. data/lib/funktor.rb +63 -0
  17. data/lib/funktor/active_job_handler.rb +52 -0
  18. data/lib/funktor/aws/sqs/event.rb +20 -0
  19. data/lib/funktor/aws/sqs/record.rb +14 -0
  20. data/lib/funktor/cli/application.rb +23 -0
  21. data/lib/funktor/cli/bootstrap.rb +35 -0
  22. data/lib/funktor/cli/generate.rb +0 -0
  23. data/lib/funktor/cli/generate/base.rb +13 -0
  24. data/lib/funktor/cli/generate/work_queue.rb +25 -0
  25. data/lib/funktor/cli/init.rb +78 -0
  26. data/lib/funktor/cli/templates/Gemfile +9 -0
  27. data/lib/funktor/cli/templates/config/environment.yml +4 -0
  28. data/lib/funktor/cli/templates/config/funktor.yml +51 -0
  29. data/lib/funktor/cli/templates/config/package.yml +9 -0
  30. data/lib/funktor/cli/templates/config/ruby_layer.yml +11 -0
  31. data/lib/funktor/cli/templates/function_definitions/active_job_handler.yml +11 -0
  32. data/lib/funktor/cli/templates/function_definitions/incoming_job_handler.yml +11 -0
  33. data/lib/funktor/cli/templates/funktor.yml.tt +51 -0
  34. data/lib/funktor/cli/templates/gitignore +2 -0
  35. data/lib/funktor/cli/templates/handlers/active_job_handler.rb +17 -0
  36. data/lib/funktor/cli/templates/handlers/incoming_job_handler.rb +8 -0
  37. data/lib/funktor/cli/templates/iam_permissions/active_job_queue.yml +8 -0
  38. data/lib/funktor/cli/templates/iam_permissions/incoming_job_queue.yml +8 -0
  39. data/lib/funktor/cli/templates/iam_permissions/ssm.yml +5 -0
  40. data/lib/funktor/cli/templates/package.json +1 -0
  41. data/lib/funktor/cli/templates/resources/active_job_queue.yml +22 -0
  42. data/lib/funktor/cli/templates/resources/cloudwatch_dashboard.yml +518 -0
  43. data/lib/funktor/cli/templates/resources/incoming_job_queue.yml +22 -0
  44. data/lib/funktor/cli/templates/resources/incoming_job_queue_user.yml +26 -0
  45. data/lib/funktor/cli/templates/serverless.yml +54 -0
  46. data/lib/funktor/cli/templates/workers/hello_worker.rb +8 -0
  47. data/lib/funktor/deploy/cli.rb +42 -0
  48. data/lib/funktor/deploy/serverless.rb +60 -0
  49. data/lib/funktor/deploy/serverless_templates/serverless.yml +156 -0
  50. data/lib/funktor/fake_job_queue.rb +15 -0
  51. data/lib/funktor/incoming_job_handler.rb +39 -0
  52. data/lib/funktor/job.rb +76 -0
  53. data/lib/funktor/middleware/metrics.rb +51 -0
  54. data/lib/funktor/middleware_chain.rb +62 -0
  55. data/lib/funktor/testing.rb +69 -0
  56. data/lib/funktor/version.rb +3 -0
  57. data/lib/funktor/worker.rb +86 -0
  58. metadata +173 -0
@@ -0,0 +1,51 @@
1
+ module Funktor
2
+ module Middleware
3
+ class Metrics
4
+ def call(job)
5
+ start_time = Time.now.utc
6
+ yield
7
+ end_time = Time.now.utc
8
+ time_diff = end_time - start_time
9
+ put_metric_to_stdout(time_diff, job)
10
+ end
11
+
12
+ def put_metric_to_stdout(time_diff, job)
13
+ puts Funktor.dump_json(metric_hash(time_diff, job))
14
+ end
15
+
16
+ def metric_hash(time_diff_in_seconds, job)
17
+ {
18
+ "_aws": {
19
+ "Timestamp": Time.now.strftime('%s%3N').to_i,
20
+ "CloudWatchMetrics": [
21
+ {
22
+ "Namespace": "rails-lambda-experiment", # TODO - We should get this from config or someting
23
+ "Dimensions": [["WorkerClassName"]],
24
+ "Metrics": [ # CPU, Memory, Duration, etc...
25
+ {
26
+ "Name": "Duration",
27
+ "Unit": "Milliseconds"
28
+ }
29
+ ]
30
+ }
31
+ ]
32
+ },
33
+ "WorkerClassName": job.worker_class_name,
34
+ "Duration": time_diff_in_seconds * 1_000
35
+ #"count": value,
36
+ #"requestId": "989ffbf8-9ace-4817-a57c-e4dd734019ee"
37
+ }
38
+ #data[key] = value
39
+ end
40
+
41
+ end
42
+ end
43
+ end
44
+
45
+ Funktor.configure_active_job_handler do |config|
46
+ config.active_job_handler_middleware do |chain|
47
+ chain.add Funktor::Middleware::Metrics
48
+ end
49
+ end
50
+
51
+
@@ -0,0 +1,62 @@
1
+ module Funktor
2
+ class MiddlewareChain
3
+ attr_reader :entries
4
+
5
+ def initialize
6
+ @entries = []
7
+ end
8
+
9
+ def remove(klass)
10
+ entries.delete_if { |entry| entry.klass == klass }
11
+ end
12
+
13
+ def add(klass, *args)
14
+ remove(klass)
15
+ entries << Entry.new(klass, *args)
16
+ end
17
+
18
+ def prepend(klass, *args)
19
+ remove(klass)
20
+ entries.insert(0, Entry.new(klass, *args))
21
+ end
22
+
23
+ def insert_before(oldklass, newklass, *args)
24
+ remove(newklass)
25
+ i = entries.index { |entry| entry.klass == oldklass } || 0
26
+ entries.insert(i, Entry.new(newklass, *args))
27
+ end
28
+
29
+ def insert_after(oldklass, newklass, *args)
30
+ remove(newklass)
31
+ i = entries.index { |entry| entry.klass == oldklass } || entries.count - 1
32
+ entries.insert(i + 1, Entry.new(newklass, *args))
33
+ end
34
+
35
+ def invoke(*args)
36
+ return yield if @entries.empty?
37
+
38
+ middlewares = entries.map(&:instantiate)
39
+ traverse_chain = proc do
40
+ if middlewares.empty?
41
+ yield
42
+ else
43
+ middlewares.shift.call(*args, &traverse_chain)
44
+ end
45
+ end
46
+ traverse_chain.call
47
+ end
48
+
49
+ class Entry
50
+ attr_reader :klass
51
+
52
+ def initialize(klass, *args)
53
+ @klass = klass
54
+ @args = args
55
+ end
56
+
57
+ def instantiate
58
+ @klass.new(*@args)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,69 @@
1
+ require 'funktor/worker'
2
+ require 'funktor/fake_job_queue'
3
+
4
+ module Funktor
5
+ module Worker
6
+ def self.clear_all
7
+ Funktor::FakeJobQueue.clear_all
8
+ end
9
+ module ClassMethods
10
+ def jobs
11
+ Funktor::FakeJobQueue.jobs[self.name]
12
+ end
13
+
14
+ def clear
15
+ jobs.clear
16
+ end
17
+
18
+ def work_all_jobs
19
+ while jobs.any?
20
+ job_data = jobs.shift
21
+ worker = job_data[:worker]
22
+ worker_params = job_data[:payload][:worker_params]
23
+ worker.new.perform(worker_params)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ class Testing
29
+
30
+ def self.inline!(&block)
31
+ Funktor.configure_job_pusher do |config|
32
+ config.job_pusher_middleware do |chain|
33
+ chain.add Funktor::InlineJobPusherMiddleware
34
+ end
35
+ end
36
+ yield
37
+ Funktor.configure_job_pusher do |config|
38
+ config.job_pusher_middleware do |chain|
39
+ chain.remove Funktor::InlineJobPusherMiddleware
40
+ end
41
+ end
42
+ end
43
+ def self.fake!(&block)
44
+ Funktor.configure_job_pusher do |config|
45
+ config.job_pusher_middleware do |chain|
46
+ chain.add Funktor::FakeJobPusherMiddleware
47
+ end
48
+ end
49
+ yield
50
+ Funktor.configure_job_pusher do |config|
51
+ config.job_pusher_middleware do |chain|
52
+ chain.remove Funktor::FakeJobPusherMiddleware
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ class InlineJobPusherMiddleware
59
+ def call(worker, payload)
60
+ worker.new.perform(payload[:worker_params])
61
+ end
62
+ end
63
+
64
+ class FakeJobPusherMiddleware
65
+ def call(worker, payload)
66
+ Funktor::FakeJobQueue.push(worker, payload)
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,3 @@
1
+ module Funktor
2
+ VERSION = "0.2.1"
3
+ end
@@ -0,0 +1,86 @@
1
+ require 'securerandom'
2
+ require 'aws-sdk-sqs'
3
+ require "active_support"
4
+
5
+ module Funktor
6
+ class DelayTooLongError < StandardError; end
7
+ end
8
+
9
+ module Funktor::Worker
10
+ def self.included(base)
11
+ base.extend ClassMethods
12
+ base.class_eval do
13
+ cattr_accessor :funktor_options_hash
14
+ #alias_method :perform_later, :perform_async
15
+ end
16
+ end
17
+
18
+ module ClassMethods
19
+ def funktor_options(options = {})
20
+ self.funktor_options_hash = options
21
+ end
22
+
23
+ def get_funktor_options
24
+ self.funktor_options_hash || {}
25
+ end
26
+
27
+ def custom_queue_url
28
+ get_funktor_options[:queue_url]
29
+ end
30
+
31
+ def queue_url
32
+ # TODO : Should this default to FUNKTOR_ACTIVE_JOB_QUEUE?
33
+ # Depends how e handle this in pro...?
34
+ custom_queue_url || ENV['FUNKTOR_INCOMING_JOB_QUEUE']
35
+ end
36
+
37
+ def perform_async(*worker_params)
38
+ self.perform_in(0, *worker_params)
39
+ end
40
+
41
+ def perform_at(time, *worker_params)
42
+ delay = (time.utc - Time.now.utc).round
43
+ if delay < 0
44
+ delay = 0
45
+ end
46
+ self.perform_in(delay, *worker_params)
47
+ end
48
+
49
+ def perform_in(delay, *worker_params)
50
+ if delay > max_delay
51
+ raise Funktor::DelayTooLongError.new("The delay can't be longer than #{max_delay} seconds. This is a limitation of SQS. Funktor Pro has mechanisms to work around this limitation.")
52
+ end
53
+ self.push_to_incoming_job_queue(delay, *worker_params)
54
+ end
55
+
56
+ def push_to_incoming_job_queue(delay, *worker_params)
57
+ job_id = SecureRandom.uuid
58
+ payload = build_job_payload(job_id, delay, *worker_params)
59
+
60
+ Funktor.job_pusher_middleware.invoke(self, payload) do
61
+ client.send_message({
62
+ queue_url: queue_url,
63
+ message_body: Funktor.dump_json(payload)
64
+ })
65
+ end
66
+ end
67
+
68
+ def max_delay
69
+ 900
70
+ end
71
+
72
+ def client
73
+ @client ||= Aws::SQS::Client.new
74
+ end
75
+
76
+ def build_job_payload(job_id, delay, *worker_params)
77
+ {
78
+ worker: self.name,
79
+ worker_params: worker_params,
80
+ job_id: job_id,
81
+ delay: delay,
82
+ funktor_options: get_funktor_options
83
+ }
84
+ end
85
+ end
86
+ end
metadata ADDED
@@ -0,0 +1,173 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: funktor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Jeremy Green
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-06-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: aws-sdk-sqs
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.37'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.37'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thor
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: webmock
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
+ description: Background processing in AWS Lambda.
84
+ email:
85
+ - jeremy@octolabs.com
86
+ executables:
87
+ - funktor
88
+ - funktor-deploy
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - ".gitignore"
93
+ - ".rspec"
94
+ - ".travis.yml"
95
+ - CODE_OF_CONDUCT.md
96
+ - Gemfile
97
+ - Gemfile.lock
98
+ - LICENSE.txt
99
+ - README.md
100
+ - Rakefile
101
+ - bin/console
102
+ - bin/setup
103
+ - exe/funktor
104
+ - exe/funktor-deploy
105
+ - funktor.gemspec
106
+ - lib/funktor.rb
107
+ - lib/funktor/active_job_handler.rb
108
+ - lib/funktor/aws/sqs/event.rb
109
+ - lib/funktor/aws/sqs/record.rb
110
+ - lib/funktor/cli/application.rb
111
+ - lib/funktor/cli/bootstrap.rb
112
+ - lib/funktor/cli/generate.rb
113
+ - lib/funktor/cli/generate/base.rb
114
+ - lib/funktor/cli/generate/work_queue.rb
115
+ - lib/funktor/cli/init.rb
116
+ - lib/funktor/cli/templates/Gemfile
117
+ - lib/funktor/cli/templates/config/environment.yml
118
+ - lib/funktor/cli/templates/config/funktor.yml
119
+ - lib/funktor/cli/templates/config/package.yml
120
+ - lib/funktor/cli/templates/config/ruby_layer.yml
121
+ - lib/funktor/cli/templates/function_definitions/active_job_handler.yml
122
+ - lib/funktor/cli/templates/function_definitions/incoming_job_handler.yml
123
+ - lib/funktor/cli/templates/funktor.yml.tt
124
+ - lib/funktor/cli/templates/gitignore
125
+ - lib/funktor/cli/templates/handlers/active_job_handler.rb
126
+ - lib/funktor/cli/templates/handlers/incoming_job_handler.rb
127
+ - lib/funktor/cli/templates/iam_permissions/active_job_queue.yml
128
+ - lib/funktor/cli/templates/iam_permissions/incoming_job_queue.yml
129
+ - lib/funktor/cli/templates/iam_permissions/ssm.yml
130
+ - lib/funktor/cli/templates/package.json
131
+ - lib/funktor/cli/templates/resources/active_job_queue.yml
132
+ - lib/funktor/cli/templates/resources/cloudwatch_dashboard.yml
133
+ - lib/funktor/cli/templates/resources/incoming_job_queue.yml
134
+ - lib/funktor/cli/templates/resources/incoming_job_queue_user.yml
135
+ - lib/funktor/cli/templates/serverless.yml
136
+ - lib/funktor/cli/templates/workers/hello_worker.rb
137
+ - lib/funktor/deploy/cli.rb
138
+ - lib/funktor/deploy/serverless.rb
139
+ - lib/funktor/deploy/serverless_templates/serverless.yml
140
+ - lib/funktor/fake_job_queue.rb
141
+ - lib/funktor/incoming_job_handler.rb
142
+ - lib/funktor/job.rb
143
+ - lib/funktor/middleware/metrics.rb
144
+ - lib/funktor/middleware_chain.rb
145
+ - lib/funktor/testing.rb
146
+ - lib/funktor/version.rb
147
+ - lib/funktor/worker.rb
148
+ homepage: https://github.com/Octo-Labs/funktor
149
+ licenses:
150
+ - MIT
151
+ metadata:
152
+ homepage_uri: https://github.com/Octo-Labs/funktor
153
+ source_code_uri: https://github.com/Octo-Labs/funktor
154
+ post_install_message:
155
+ rdoc_options: []
156
+ require_paths:
157
+ - lib
158
+ required_ruby_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: 2.3.0
163
+ required_rubygems_version: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ requirements: []
169
+ rubygems_version: 3.1.4
170
+ signing_key:
171
+ specification_version: 4
172
+ summary: Background processing in AWS Lambda.
173
+ test_files: []