funktor 0.5.0 → 0.6.3
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/Gemfile.lock +26 -11
- data/funktor-testapp/Gemfile.lock +2 -2
- data/funktor-testapp/app/services/job_flood.rb +1 -1
- data/funktor-testapp/app/workers/single_thread_audit_worker.rb +3 -0
- data/funktor-testapp/funktor_config/environment.yml +2 -2
- data/funktor-testapp/funktor_config/function_definitions/default_queue_handler.yml +3 -1
- data/funktor-testapp/funktor_config/function_definitions/incoming_job_handler.yml +3 -1
- data/funktor-testapp/funktor_config/function_definitions/job_activator.yml +1 -2
- data/funktor-testapp/funktor_config/function_definitions/low_concurrency_queue_handler.yml +13 -0
- data/funktor-testapp/funktor_config/funktor.yml +25 -25
- data/funktor-testapp/funktor_config/iam_permissions/{single_thread_queue.yml → low_concurrency_queue.yml} +1 -1
- data/funktor-testapp/funktor_config/resources/cloudwatch_dashboard.yml +22 -17
- data/funktor-testapp/funktor_config/resources/default_queue.yml +2 -2
- data/funktor-testapp/funktor_config/resources/incoming_job_queue.yml +2 -2
- data/funktor-testapp/funktor_config/resources/jobs_table.yml +16 -4
- data/funktor-testapp/funktor_config/resources/low_concurrency_queue.yml +22 -0
- data/funktor-testapp/funktor_init.yml +16 -8
- data/funktor-testapp/lambda_event_handlers/{single_thread_queue_handler.rb → low_concurrency_queue_handler.rb} +0 -0
- data/funktor-testapp/serverless.yml +4 -3
- data/funktor.gemspec +3 -1
- data/lib/funktor/activity_tracker.rb +6 -2
- data/lib/funktor/cli/templates/funktor_config/function_definitions/incoming_job_handler.yml +3 -1
- data/lib/funktor/cli/templates/funktor_config/function_definitions/job_activator.yml +1 -2
- data/lib/funktor/cli/templates/funktor_config/function_definitions/work_queue_handler.yml +3 -1
- data/lib/funktor/cli/templates/funktor_config/funktor.yml +6 -6
- data/lib/funktor/cli/templates/funktor_config/resources/cloudwatch_dashboard.yml +3 -2
- data/lib/funktor/cli/templates/funktor_config/resources/incoming_job_queue.yml +2 -2
- data/lib/funktor/cli/templates/funktor_config/resources/jobs_table.yml +16 -4
- data/lib/funktor/cli/templates/funktor_config/resources/work_queue.yml +2 -2
- data/lib/funktor/cli/templates/funktor_init.yml.tt +14 -8
- data/lib/funktor/cli/templates/serverless.yml +1 -0
- data/lib/funktor/incoming_job_handler.rb +11 -15
- data/lib/funktor/job.rb +50 -5
- data/lib/funktor/job_activator.rb +52 -26
- data/lib/funktor/shard_utils.rb +6 -0
- data/lib/funktor/testing.rb +1 -0
- data/lib/funktor/version.rb +1 -1
- data/lib/funktor/web/application.rb +139 -0
- data/lib/funktor/web/views/index.erb +3 -0
- data/lib/funktor/web/views/layout.erb +58 -0
- data/lib/funktor/web/views/processing.erb +29 -0
- data/lib/funktor/web/views/queued.erb +29 -0
- data/lib/funktor/web/views/retries.erb +35 -0
- data/lib/funktor/web/views/scheduled.erb +26 -0
- data/lib/funktor/web/views/stats.erb +9 -0
- data/lib/funktor/web/views/table_stats_with_buttons.erb +11 -0
- data/lib/funktor/web.rb +1 -0
- data/lib/funktor/work_queue_handler.rb +41 -0
- data/lib/funktor/worker/funktor_options.rb +3 -1
- data/lib/funktor/worker.rb +8 -11
- data/lib/funktor.rb +16 -16
- metadata +46 -6
- data/funktor-testapp/funktor_config/function_definitions/single_thread_queue_handler.yml +0 -11
- data/funktor-testapp/funktor_config/resources/single_thread_queue.yml +0 -22
@@ -3,11 +3,11 @@ Resources:
|
|
3
3
|
Type: AWS::SQS::Queue
|
4
4
|
Properties:
|
5
5
|
QueueName: ${self:custom.funktor.DefaultQueueName}
|
6
|
-
VisibilityTimeout:
|
6
|
+
VisibilityTimeout: ${self:custom.funktor.DefaultQueueHandler.visibilityTimeout}
|
7
7
|
RedrivePolicy:
|
8
8
|
deadLetterTargetArn:
|
9
9
|
"Fn::GetAtt": [ DefaultDeadLetterQueue, Arn ]
|
10
|
-
maxReceiveCount:
|
10
|
+
maxReceiveCount: ${self:custom.funktor.DefaultQueueHandler.maxReceiveCount}
|
11
11
|
DefaultDeadLetterQueue:
|
12
12
|
Type: AWS::SQS::Queue
|
13
13
|
Properties:
|
@@ -3,11 +3,11 @@ Resources:
|
|
3
3
|
Type: AWS::SQS::Queue
|
4
4
|
Properties:
|
5
5
|
QueueName: ${self:custom.funktor.IncomingJobQueueName}
|
6
|
-
VisibilityTimeout:
|
6
|
+
VisibilityTimeout: ${self:custom.funktor.IncomingJobHandler.visibilityTimeout}
|
7
7
|
RedrivePolicy:
|
8
8
|
deadLetterTargetArn:
|
9
9
|
"Fn::GetAtt": [ IncomingJobDeadLetterQueue, Arn ]
|
10
|
-
maxReceiveCount:
|
10
|
+
maxReceiveCount: ${self:custom.funktor.IncomingJobHandler.maxReceiveCount}
|
11
11
|
IncomingJobDeadLetterQueue:
|
12
12
|
Type: AWS::SQS::Queue
|
13
13
|
Properties:
|
@@ -8,11 +8,11 @@ Resources:
|
|
8
8
|
AttributeType: N
|
9
9
|
- AttributeName: jobId
|
10
10
|
AttributeType: S
|
11
|
-
|
12
|
-
|
11
|
+
- AttributeName: category
|
12
|
+
AttributeType: S
|
13
13
|
- AttributeName: performAt
|
14
14
|
AttributeType: S
|
15
|
-
- AttributeName:
|
15
|
+
- AttributeName: queueable
|
16
16
|
AttributeType: S
|
17
17
|
KeySchema:
|
18
18
|
- AttributeName: jobShard
|
@@ -22,7 +22,19 @@ Resources:
|
|
22
22
|
GlobalSecondaryIndexes:
|
23
23
|
- IndexName: performAtIndex
|
24
24
|
KeySchema:
|
25
|
-
- AttributeName:
|
25
|
+
- AttributeName: queueable
|
26
|
+
KeyType: HASH
|
27
|
+
- AttributeName: performAt
|
28
|
+
KeyType: RANGE
|
29
|
+
Projection:
|
30
|
+
NonKeyAttributes:
|
31
|
+
- jobId
|
32
|
+
- payload
|
33
|
+
- category
|
34
|
+
ProjectionType: INCLUDE
|
35
|
+
- IndexName: categoryIndex
|
36
|
+
KeySchema:
|
37
|
+
- AttributeName: category
|
26
38
|
KeyType: HASH
|
27
39
|
- AttributeName: performAt
|
28
40
|
KeyType: RANGE
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Resources:
|
2
|
+
LowConcurrencyQueue:
|
3
|
+
Type: AWS::SQS::Queue
|
4
|
+
Properties:
|
5
|
+
QueueName: ${self:custom.funktor.LowConcurrencyQueueName}
|
6
|
+
VisibilityTimeout: ${self:custom.funktor.LowConcurrencyQueueHandler.visibilityTimeout}
|
7
|
+
RedrivePolicy:
|
8
|
+
deadLetterTargetArn:
|
9
|
+
"Fn::GetAtt": [ LowConcurrencyDeadLetterQueue, Arn ]
|
10
|
+
maxReceiveCount: ${self:custom.funktor.LowConcurrencyQueueHandler.maxReceiveCount}
|
11
|
+
LowConcurrencyDeadLetterQueue:
|
12
|
+
Type: AWS::SQS::Queue
|
13
|
+
Properties:
|
14
|
+
QueueName: ${self:custom.funktor.LowConcurrencyDeadJobQueueName}
|
15
|
+
|
16
|
+
Outputs:
|
17
|
+
LowConcurrencyQueueUrl:
|
18
|
+
Value:
|
19
|
+
Ref: LowConcurrencyQueue
|
20
|
+
LowConcurrencyDeadLetterQueueUrl:
|
21
|
+
Value:
|
22
|
+
Ref: LowConcurrencyDeadLetterQueue
|
@@ -10,7 +10,7 @@ handlerDefaults:
|
|
10
10
|
# to a handler at one time, so you'll want this to be at least 10x the maximum time you
|
11
11
|
# expect to spend for one message. We default to a high number here to allow for the
|
12
12
|
# times when things go weird.
|
13
|
-
|
13
|
+
functionTimeout: 300
|
14
14
|
|
15
15
|
# reservedConcurrency represents the maximum number of concurrent executions.
|
16
16
|
# Usually you'll want to leave this as null so that handlers can scale infinitely
|
@@ -29,19 +29,21 @@ handlerDefaults:
|
|
29
29
|
memorySize: 256
|
30
30
|
|
31
31
|
# You can set the batch size. Max of 10_000 for normal queues, 10 for FIFO.
|
32
|
-
batchSize:
|
32
|
+
batchSize: 1
|
33
33
|
|
34
34
|
# How many seconds should AWS wait for a batch to fill up before executing lambda?
|
35
35
|
# For immediate execution set the batch size to 1.
|
36
|
-
maximumBatchingWindow :
|
36
|
+
maximumBatchingWindow : 0
|
37
37
|
|
38
38
|
# Visibility timeout should only come into play in the case of Funktor errors.
|
39
39
|
# Application level errors should be handled by Funktor retry mechanisms.
|
40
40
|
# The visibility timeout should be at least as long as the function timeout, and up to 6 times larger.
|
41
|
-
visibilityTimeout:
|
41
|
+
visibilityTimeout: 1800
|
42
42
|
|
43
|
-
#
|
44
|
-
|
43
|
+
# Max recieve count affects how many times a job will retry that has been throttled at the SQS -> Lambda boundary.
|
44
|
+
# Amazon recommend this be at least 5, but I've found that higher numbers are better to avoid legit jobs ending
|
45
|
+
# up in the dead letter queue
|
46
|
+
maxReceiveCount: 20
|
45
47
|
|
46
48
|
# Incoming Job Handler
|
47
49
|
incomingJobHandler:
|
@@ -49,6 +51,8 @@ incomingJobHandler:
|
|
49
51
|
# to quickly handle jobs at the beginning of a burst. Uncomment the line below if so.
|
50
52
|
# provisionedConcurrency: 4
|
51
53
|
|
54
|
+
jobActivator:
|
55
|
+
# You probably don't need to adjust the defaults for this one.
|
52
56
|
|
53
57
|
queues:
|
54
58
|
- default:
|
@@ -56,6 +60,10 @@ queues:
|
|
56
60
|
# memorySize: 512
|
57
61
|
# TODO - Is it advisable to use FIFO queuues with Funktor? Maybe this isn't really even supported by CloudFormation?
|
58
62
|
# fifo: false
|
59
|
-
-
|
60
|
-
|
63
|
+
- lowConcurrency:
|
64
|
+
# BEWARE - Setting very low concurrency values (5 or lower) can contribute to "SQS Overpull", so you probably don't
|
65
|
+
# want to have any queues with extremely low concurrency.
|
66
|
+
# Details about "SQS Overpull" can be found in this article:
|
67
|
+
# https://zaccharles.medium.com/reproducing-the-sqs-trigger-and-lambda-concurrency-limit-issue-f4c09d384a18
|
68
|
+
reservedConcurrency: 10
|
61
69
|
|
File without changes
|
@@ -26,12 +26,13 @@ provider:
|
|
26
26
|
lambdaHashingVersion: 20201221
|
27
27
|
environment: ${file(funktor_config/environment.yml)}
|
28
28
|
versionFunctions: false # Reduces the amount of storage used since all Lambdas together are limited to 75GB
|
29
|
+
logRetentionInDays: 7
|
29
30
|
iamRoleStatements:
|
30
31
|
- ${file(funktor_config/iam_permissions/activity_table.yml)}
|
31
32
|
- ${file(funktor_config/iam_permissions/default_queue.yml)}
|
32
33
|
- ${file(funktor_config/iam_permissions/incoming_job_queue.yml)}
|
33
34
|
- ${file(funktor_config/iam_permissions/ssm.yml)}
|
34
|
-
- ${file(funktor_config/iam_permissions/
|
35
|
+
- ${file(funktor_config/iam_permissions/low_concurrency_queue.yml)}
|
35
36
|
- ${file(funktor_config/iam_permissions/jobs_table.yml)}
|
36
37
|
- ${file(funktor_config/iam_permissions/jobs_table_secondary_index.yml)}
|
37
38
|
|
@@ -49,7 +50,7 @@ functions:
|
|
49
50
|
IncomingJobHandler: ${file(funktor_config/function_definitions/incoming_job_handler.yml)}
|
50
51
|
DefaultQueueHandler: ${file(funktor_config/function_definitions/default_queue_handler.yml)}
|
51
52
|
JobActivator: ${file(funktor_config/function_definitions/job_activator.yml)}
|
52
|
-
|
53
|
+
LowConcurrencyQueueHandler: ${file(funktor_config/function_definitions/low_concurrency_queue_handler.yml)}
|
53
54
|
RandomJobGenerator: ${file(funktor_config/function_definitions/random_job_generator.yml)}
|
54
55
|
|
55
56
|
resources:
|
@@ -58,7 +59,7 @@ resources:
|
|
58
59
|
- ${file(funktor_config/resources/cloudwatch_dashboard.yml)}
|
59
60
|
- ${file(funktor_config/resources/default_queue.yml)}
|
60
61
|
- ${file(funktor_config/resources/incoming_job_queue.yml)}
|
61
|
-
- ${file(funktor_config/resources/
|
62
|
+
- ${file(funktor_config/resources/low_concurrency_queue.yml)}
|
62
63
|
- ${file(funktor_config/resources/jobs_table.yml)}
|
63
64
|
|
64
65
|
plugins:
|
data/funktor.gemspec
CHANGED
@@ -32,10 +32,12 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.add_dependency 'aws-sdk-sqs', '~> 1.37'
|
33
33
|
spec.add_dependency 'aws-sdk-dynamodb', '~> 1.62'
|
34
34
|
spec.add_dependency "activesupport" # TODO - Can we build our own verison of cattr_accessor to avoid this?
|
35
|
-
spec.add_dependency "thor" # Thor drives the CLI
|
35
|
+
spec.add_dependency "thor" # Thor drives the CLI TODO - should this just be a dev dependency?
|
36
36
|
|
37
37
|
spec.add_development_dependency 'activejob', '>= 5.1.5'
|
38
38
|
spec.add_development_dependency 'simplecov'
|
39
39
|
spec.add_development_dependency 'webmock'
|
40
40
|
spec.add_development_dependency 'pry-byebug'
|
41
|
+
spec.add_development_dependency 'sinatra'
|
42
|
+
spec.add_development_dependency 'timecop'
|
41
43
|
end
|
@@ -14,7 +14,9 @@ module Funktor
|
|
14
14
|
bailingOut: 'failed',
|
15
15
|
retrying: 'retries',
|
16
16
|
retryActivated: 'queued',
|
17
|
-
scheduledJobActivated:
|
17
|
+
scheduledJobActivated: nil,
|
18
|
+
scheduledJobDeleted: 'scheduledJobDeleted',
|
19
|
+
retryDeleted: 'retryDeleted'
|
18
20
|
#scheduledJobPushedToActive: 'active',
|
19
21
|
#activeJobPushed: 'active',
|
20
22
|
#scheduledJobPushed: 'scheduled'
|
@@ -30,7 +32,9 @@ module Funktor
|
|
30
32
|
bailingOut: 'processing',
|
31
33
|
retrying: 'processing',
|
32
34
|
retryActivated: 'retries',
|
33
|
-
scheduledJobActivated: 'scheduled'
|
35
|
+
scheduledJobActivated: 'scheduled',
|
36
|
+
scheduledJobDeleted: 'scheduled',
|
37
|
+
retryDeleted: 'retries'
|
34
38
|
#scheduledJobPushedToActive: 'scheduled',
|
35
39
|
#activeJobPushed: nil,
|
36
40
|
#scheduledJobPushed: nil
|
@@ -1,10 +1,12 @@
|
|
1
1
|
handler: lambda_event_handlers/incoming_job_handler.call
|
2
|
-
timeout: ${self:custom.funktor.IncomingJobHandler.
|
2
|
+
timeout: ${self:custom.funktor.IncomingJobHandler.functionTimeout, 30}
|
3
3
|
reservedConcurrency: ${self:custom.funktor.IncomingJobHandler.reservedConcurrency, null}
|
4
4
|
provisionedConcurrency: ${self:custom.funktor.IncomingJobHandler.provisionedConcurrency, null}
|
5
5
|
memorySize: ${self:custom.funktor.IncomingJobHandler.memorySize, 256}
|
6
6
|
events:
|
7
7
|
- sqs:
|
8
|
+
batchSize: ${self:custom.funktor.IncomingJobHandler.batchSize, 1}
|
9
|
+
maximumBatchingWindow: ${self:custom.funktor.IncomingJobHandler.maximumBatchingWindow, 0}
|
8
10
|
arn:
|
9
11
|
Fn::GetAtt:
|
10
12
|
- IncomingJobQueue
|
@@ -1,8 +1,7 @@
|
|
1
1
|
handler: lambda_event_handlers/job_activator.call
|
2
|
-
timeout: ${self:custom.funktor.JobActivator.
|
2
|
+
timeout: ${self:custom.funktor.JobActivator.functionTimeout, 30}
|
3
3
|
reservedConcurrency: ${self:custom.funktor.JobActivator.reservedConcurrency, null}
|
4
4
|
provisionedConcurrency: ${self:custom.funktor.JobActivator.provisionedConcurrency, null}
|
5
5
|
memorySize: ${self:custom.funktor.JobActivator.memorySize, 256}
|
6
|
-
#reservedConcurrency: 1
|
7
6
|
events:
|
8
7
|
- schedule: rate(1 minute)
|
@@ -1,10 +1,12 @@
|
|
1
1
|
handler: lambda_event_handlers/<%= work_queue_name.underscore %>_queue_handler.call
|
2
|
-
timeout: ${self:custom.funktor.<%= work_queue_name.camelize %>QueueHandler.
|
2
|
+
timeout: ${self:custom.funktor.<%= work_queue_name.camelize %>QueueHandler.functionTimeout, 900}
|
3
3
|
reservedConcurrency: ${self:custom.funktor.<%= work_queue_name.camelize %>QueueHandler.reservedConcurrency, null}
|
4
4
|
provisionedConcurrency: ${self:custom.funktor.<%= work_queue_name.camelize %>QueueHandler.provisionedConcurrency, null}
|
5
5
|
memorySize: ${self:custom.funktor.<%= work_queue_name.camelize %>QueueHandler.memorySize, 256}
|
6
6
|
events:
|
7
7
|
- sqs:
|
8
|
+
batchSize: ${self:custom.funktor.<%= work_queue_name.camelize %>QueueHandler.batchSize, 1}
|
9
|
+
maximumBatchingWindow: ${self:custom.funktor.<%= work_queue_name.camelize %>QueueHandler.maximumBatchingWindow, 0}
|
8
10
|
arn:
|
9
11
|
Fn::GetAtt:
|
10
12
|
- <%= work_queue_name.camelize %>Queue
|
@@ -3,7 +3,7 @@ IncomingJobHandler:
|
|
3
3
|
# to a handler at one time, so you'll want this to be at least 10x the maximum time you
|
4
4
|
# expect to spend for one message. The incoming job handler usually will be pretty fast,
|
5
5
|
# but we default to a high number here to allow for the times when things go weird.
|
6
|
-
|
6
|
+
functionTimeout: <%= incoming_config_value 'functionTimeout' %>
|
7
7
|
# reservedConcurrency represents the maximum number of concurrent executions.
|
8
8
|
# For the incoming job handler you probably don't want to limit it because you
|
9
9
|
# want to get things onto work queues as quickly as possible.
|
@@ -19,14 +19,14 @@ IncomingJobHandler:
|
|
19
19
|
batchSize: <%= incoming_config_value 'batchSize' %>
|
20
20
|
maximumBatchingWindow: <%= incoming_config_value 'maximumBatchingWindow' %>
|
21
21
|
visibilityTimeout: <%= incoming_config_value 'visibilityTimeout' %>
|
22
|
-
|
22
|
+
maxReceiveCount: <%= incoming_config_value 'maxReceiveCount' %>
|
23
23
|
|
24
24
|
JobActivator:
|
25
25
|
# timeout is how long the handler can possibly run. Up to 10 messages may be delivered
|
26
26
|
# to a handler at one time, so you'll want this to be at least 10x the maximum time you
|
27
27
|
# expect to spend for one message. The job activator usually will be pretty fast,
|
28
28
|
# but we default to a high number here to allow for the times when things go weird.
|
29
|
-
|
29
|
+
functionTimeout: <%= activator_config_value 'functionTimeout' %>
|
30
30
|
# reservedConcurrency represents the maximum number of concurrent executions.
|
31
31
|
# For the job activator you probably don't want to limit it because you
|
32
32
|
# want to get things onto work queues as quickly as possible when they're ready.
|
@@ -42,7 +42,7 @@ JobActivator:
|
|
42
42
|
batchSize: <%= activator_config_value 'batchSize' %>
|
43
43
|
maximumBatchingWindow: <%= activator_config_value 'maximumBatchingWindow' %>
|
44
44
|
visibilityTimeout: <%= activator_config_value 'visibilityTimeout' %>
|
45
|
-
|
45
|
+
maxReceiveCount: <%= activator_config_value 'maxReceiveCount' %>
|
46
46
|
|
47
47
|
|
48
48
|
|
@@ -52,7 +52,7 @@ JobActivator:
|
|
52
52
|
# to a handler at one time, so you'll want this to be at least 10x the maximum time you
|
53
53
|
# expect to spend for one message. The active job handler may be slow if your jobs are
|
54
54
|
# doing a lot of work, so we default to the maximum here.
|
55
|
-
|
55
|
+
functionTimeout: <%= queue_config_value queue_name, 'functionTimeout' %>
|
56
56
|
# reservedConcurrency represents the maximum number of concurrent executions.
|
57
57
|
# For the active job handler you may want to limit it if you have resource limitations
|
58
58
|
# like database connections that you need to avoid exhausting.
|
@@ -69,7 +69,7 @@ JobActivator:
|
|
69
69
|
batchSize: <%= queue_config_value queue_name, 'batchSize' %>
|
70
70
|
maximumBatchingWindow: <%= queue_config_value queue_name, 'maximumBatchingWindow' %>
|
71
71
|
visibilityTimeout: <%= queue_config_value queue_name, 'visibilityTimeout' %>
|
72
|
-
|
72
|
+
maxReceiveCount: <%= queue_config_value queue_name, 'maxReceiveCount' %>
|
73
73
|
|
74
74
|
<%- end -%>
|
75
75
|
|
@@ -74,7 +74,7 @@ Resources:
|
|
74
74
|
"properties": {
|
75
75
|
"metrics": [
|
76
76
|
<%- queue_names.each do |queue_name| -%>
|
77
|
-
[ "<%= app_name %>", "Duration", "Queue", "<%= queue_name %>" ],
|
77
|
+
[ "<%= app_name %>", "Duration", "Queue", "<%= queue_name.underscore %>" ],
|
78
78
|
[ "...", { "stat": "p99" } ]<%= queue_name == queue_names.last ? "" : "," %>
|
79
79
|
<%- end -%>
|
80
80
|
],
|
@@ -95,7 +95,7 @@ Resources:
|
|
95
95
|
"properties": {
|
96
96
|
"metrics": [
|
97
97
|
<%- queue_names.each do |queue_name| -%>
|
98
|
-
[ "<%= app_name %>", "processed", "Queue", "<%= queue_name %>" ],
|
98
|
+
[ "<%= app_name %>", "processed", "Queue", "<%= queue_name.underscore %>" ],
|
99
99
|
[ ".", "failed", ".", "." ]<%= queue_name == queue_names.last ? "" : "," %>
|
100
100
|
<%- end -%>
|
101
101
|
],
|
@@ -616,6 +616,7 @@ Resources:
|
|
616
616
|
[ "...", "Query" ],
|
617
617
|
[ ".", "ThrottledRequests", ".", ".", ".", "PutItem", { "yAxis": "right", "visible": false } ],
|
618
618
|
[ ".", "SuccessfulRequestLatency", ".", ".", ".", "DeleteItem" ],
|
619
|
+
[ ".", "SuccessfulRequestLatency", ".", ".", ".", "UpdateItem" ],
|
619
620
|
[ ".", "ThrottledRequests", ".", ".", ".", ".", { "yAxis": "right", "visible": false } ]
|
620
621
|
],
|
621
622
|
"view": "timeSeries",
|
@@ -3,11 +3,11 @@ Resources:
|
|
3
3
|
Type: AWS::SQS::Queue
|
4
4
|
Properties:
|
5
5
|
QueueName: ${self:custom.funktor.IncomingJobQueueName}
|
6
|
-
VisibilityTimeout:
|
6
|
+
VisibilityTimeout: ${self:custom.funktor.IncomingJobHandler.visibilityTimeout}
|
7
7
|
RedrivePolicy:
|
8
8
|
deadLetterTargetArn:
|
9
9
|
"Fn::GetAtt": [ IncomingJobDeadLetterQueue, Arn ]
|
10
|
-
maxReceiveCount:
|
10
|
+
maxReceiveCount: ${self:custom.funktor.IncomingJobHandler.maxReceiveCount}
|
11
11
|
IncomingJobDeadLetterQueue:
|
12
12
|
Type: AWS::SQS::Queue
|
13
13
|
Properties:
|
@@ -8,11 +8,11 @@ Resources:
|
|
8
8
|
AttributeType: N
|
9
9
|
- AttributeName: jobId
|
10
10
|
AttributeType: S
|
11
|
-
|
12
|
-
|
11
|
+
- AttributeName: category
|
12
|
+
AttributeType: S
|
13
13
|
- AttributeName: performAt
|
14
14
|
AttributeType: S
|
15
|
-
- AttributeName:
|
15
|
+
- AttributeName: queueable
|
16
16
|
AttributeType: S
|
17
17
|
KeySchema:
|
18
18
|
- AttributeName: jobShard
|
@@ -22,7 +22,19 @@ Resources:
|
|
22
22
|
GlobalSecondaryIndexes:
|
23
23
|
- IndexName: performAtIndex
|
24
24
|
KeySchema:
|
25
|
-
- AttributeName:
|
25
|
+
- AttributeName: queueable
|
26
|
+
KeyType: HASH
|
27
|
+
- AttributeName: performAt
|
28
|
+
KeyType: RANGE
|
29
|
+
Projection:
|
30
|
+
NonKeyAttributes:
|
31
|
+
- jobId
|
32
|
+
- payload
|
33
|
+
- category
|
34
|
+
ProjectionType: INCLUDE
|
35
|
+
- IndexName: categoryIndex
|
36
|
+
KeySchema:
|
37
|
+
- AttributeName: category
|
26
38
|
KeyType: HASH
|
27
39
|
- AttributeName: performAt
|
28
40
|
KeyType: RANGE
|
@@ -3,11 +3,11 @@ Resources:
|
|
3
3
|
Type: AWS::SQS::Queue
|
4
4
|
Properties:
|
5
5
|
QueueName: ${self:custom.funktor.<%= work_queue_name.camelize %>QueueName}
|
6
|
-
VisibilityTimeout:
|
6
|
+
VisibilityTimeout: ${self:custom.funktor.<%= work_queue_name.camelize %>QueueHandler.visibilityTimeout}
|
7
7
|
RedrivePolicy:
|
8
8
|
deadLetterTargetArn:
|
9
9
|
"Fn::GetAtt": [ <%= work_queue_name.camelize %>DeadLetterQueue, Arn ]
|
10
|
-
maxReceiveCount:
|
10
|
+
maxReceiveCount: ${self:custom.funktor.<%= work_queue_name.camelize %>QueueHandler.maxReceiveCount}
|
11
11
|
<%= work_queue_name.camelize %>DeadLetterQueue:
|
12
12
|
Type: AWS::SQS::Queue
|
13
13
|
Properties:
|
@@ -10,7 +10,7 @@ handlerDefaults:
|
|
10
10
|
# to a handler at one time, so you'll want this to be at least 10x the maximum time you
|
11
11
|
# expect to spend for one message. We default to a high number here to allow for the
|
12
12
|
# times when things go weird.
|
13
|
-
|
13
|
+
functionTimeout: 300
|
14
14
|
|
15
15
|
# reservedConcurrency represents the maximum number of concurrent executions.
|
16
16
|
# Usually you'll want to leave this as null so that handlers can scale infinitely
|
@@ -29,19 +29,21 @@ handlerDefaults:
|
|
29
29
|
memorySize: 256
|
30
30
|
|
31
31
|
# You can set the batch size. Max of 10_000 for normal queues, 10 for FIFO.
|
32
|
-
batchSize:
|
32
|
+
batchSize: 1
|
33
33
|
|
34
34
|
# How many seconds should AWS wait for a batch to fill up before executing lambda?
|
35
35
|
# For immediate execution set the batch size to 1.
|
36
|
-
maximumBatchingWindow :
|
36
|
+
maximumBatchingWindow : 0
|
37
37
|
|
38
38
|
# Visibility timeout should only come into play in the case of Funktor errors.
|
39
39
|
# Application level errors should be handled by Funktor retry mechanisms.
|
40
40
|
# The visibility timeout should be at least as long as the function timeout, and up to 6 times larger.
|
41
|
-
visibilityTimeout:
|
41
|
+
visibilityTimeout: 1800
|
42
42
|
|
43
|
-
#
|
44
|
-
|
43
|
+
# Max recieve count affects how many times a job will retry that has been throttled at the SQS -> Lambda boundary.
|
44
|
+
# Amazon recommend this be at least 5, but I've found that higher numbers are better to avoid legit jobs ending
|
45
|
+
# up in the dead letter queue
|
46
|
+
maxReceiveCount: 20
|
45
47
|
|
46
48
|
# Incoming Job Handler
|
47
49
|
incomingJobHandler:
|
@@ -58,6 +60,10 @@ queues:
|
|
58
60
|
# memorySize: 512
|
59
61
|
# TODO - Is it advisable to use FIFO queuues with Funktor? Maybe this isn't really even supported by CloudFormation?
|
60
62
|
# fifo: false
|
61
|
-
-
|
62
|
-
|
63
|
+
- lowConcurrency:
|
64
|
+
# BEWARE - Setting very low concurrency values (5 or lower) can contribute to "SQS Overpull", so you probably don't
|
65
|
+
# want to have any queues with extremely low concurrency.
|
66
|
+
# Details about "SQS Overpull" can be found in this article:
|
67
|
+
# https://zaccharles.medium.com/reproducing-the-sqs-trigger-and-lambda-concurrency-limit-issue-f4c09d384a18
|
68
|
+
reservedConcurrency: 10
|
63
69
|
|