funktor 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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: []