funktor 0.4.7 → 0.5.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/.tool-versions +2 -0
- data/Gemfile.lock +7 -3
- data/funktor-testapp/.envrc +1 -0
- data/funktor-testapp/.gitignore +7 -0
- data/funktor-testapp/Gemfile +25 -0
- data/funktor-testapp/Gemfile.lock +51 -0
- data/funktor-testapp/app/services/job_flood.rb +38 -0
- data/funktor-testapp/app/workers/audit_worker.rb +49 -0
- data/funktor-testapp/app/workers/greetings_worker.rb +3 -0
- data/funktor-testapp/app/workers/hello_worker.rb +18 -0
- data/funktor-testapp/deploy-dev.sh +5 -0
- data/funktor-testapp/funktor_config/boot.rb +17 -0
- data/funktor-testapp/funktor_config/environment.yml +15 -0
- data/funktor-testapp/funktor_config/function_definitions/default_queue_handler.yml +11 -0
- data/funktor-testapp/funktor_config/function_definitions/incoming_job_handler.yml +11 -0
- data/funktor-testapp/funktor_config/function_definitions/job_activator.yml +8 -0
- data/funktor-testapp/funktor_config/function_definitions/random_job_generator.yml +18 -0
- data/funktor-testapp/funktor_config/function_definitions/single_thread_queue_handler.yml +11 -0
- data/funktor-testapp/funktor_config/funktor.yml +114 -0
- data/funktor-testapp/funktor_config/iam_permissions/activity_table.yml +5 -0
- data/funktor-testapp/funktor_config/iam_permissions/default_queue.yml +8 -0
- data/funktor-testapp/funktor_config/iam_permissions/incoming_job_queue.yml +8 -0
- data/funktor-testapp/funktor_config/iam_permissions/jobs_table.yml +5 -0
- data/funktor-testapp/funktor_config/iam_permissions/jobs_table_secondary_index.yml +8 -0
- data/funktor-testapp/funktor_config/iam_permissions/single_thread_queue.yml +8 -0
- data/funktor-testapp/funktor_config/iam_permissions/ssm.yml +5 -0
- data/funktor-testapp/funktor_config/package.yml +11 -0
- data/funktor-testapp/funktor_config/resources/activity_table.yml +22 -0
- data/funktor-testapp/funktor_config/resources/cloudwatch_dashboard.yml +804 -0
- data/funktor-testapp/funktor_config/resources/default_queue.yml +22 -0
- data/funktor-testapp/funktor_config/resources/incoming_job_queue.yml +22 -0
- data/funktor-testapp/funktor_config/resources/incoming_job_queue_user.yml +26 -0
- data/funktor-testapp/funktor_config/resources/jobs_table.yml +44 -0
- data/funktor-testapp/funktor_config/resources/single_thread_queue.yml +22 -0
- data/funktor-testapp/funktor_config/ruby_layer.yml +11 -0
- data/funktor-testapp/funktor_init.yml +61 -0
- data/funktor-testapp/lambda_event_handlers/default_queue_handler.rb +8 -0
- data/funktor-testapp/lambda_event_handlers/incoming_job_handler.rb +8 -0
- data/funktor-testapp/lambda_event_handlers/job_activator.rb +8 -0
- data/funktor-testapp/lambda_event_handlers/random_job_generator.rb +35 -0
- data/funktor-testapp/lambda_event_handlers/single_thread_queue_handler.rb +8 -0
- data/funktor-testapp/package-lock.json +248 -0
- data/funktor-testapp/package.json +8 -0
- data/funktor-testapp/serverless.yml +65 -0
- data/funktor.gemspec +1 -0
- data/lib/active_job/queue_adapters/funktor_adapter.rb +3 -3
- data/lib/funktor.rb +39 -7
- data/lib/funktor/activity_tracker.rb +102 -0
- data/lib/funktor/cli/bootstrap.rb +0 -1
- data/lib/funktor/cli/init.rb +13 -0
- data/lib/funktor/cli/templates/app/workers/hello_worker.rb +1 -1
- data/lib/funktor/cli/templates/funktor_config/environment.yml +4 -0
- data/lib/funktor/cli/templates/funktor_config/function_definitions/job_activator.yml +8 -0
- data/lib/funktor/cli/templates/funktor_config/funktor.yml +28 -2
- data/lib/funktor/cli/templates/funktor_config/iam_permissions/activity_table.yml +5 -0
- data/lib/funktor/cli/templates/funktor_config/iam_permissions/jobs_table.yml +5 -0
- data/lib/funktor/cli/templates/funktor_config/iam_permissions/jobs_table_secondary_index.yml +8 -0
- data/lib/funktor/cli/templates/funktor_config/resources/activity_table.yml +22 -0
- data/lib/funktor/cli/templates/funktor_config/resources/cloudwatch_dashboard.yml +10 -10
- data/lib/funktor/cli/templates/funktor_config/resources/jobs_table.yml +44 -0
- data/lib/funktor/cli/templates/funktor_init.yml.tt +2 -8
- data/lib/funktor/cli/templates/lambda_event_handlers/job_activator.rb +8 -0
- data/lib/funktor/cli/templates/lambda_event_handlers/work_queue_handler.rb +1 -1
- data/lib/funktor/cli/templates/serverless.yml +2 -2
- data/lib/funktor/counter.rb +4 -1
- data/lib/funktor/incoming_job_handler.rb +52 -12
- data/lib/funktor/job.rb +10 -5
- data/lib/funktor/job_activator.rb +98 -0
- data/lib/funktor/job_pusher.rb +0 -2
- data/lib/funktor/middleware/metrics.rb +8 -3
- data/lib/funktor/testing.rb +49 -47
- data/lib/funktor/version.rb +1 -1
- data/lib/funktor/{active_job_handler.rb → work_queue_handler.rb} +17 -15
- data/lib/funktor/worker.rb +0 -7
- metadata +69 -3
@@ -438,7 +438,7 @@ Resources:
|
|
438
438
|
"type": "metric",
|
439
439
|
"properties": {
|
440
440
|
"metrics": [
|
441
|
-
[ "AWS/DynamoDB", "ReturnedItemCount", "TableName", "${self:
|
441
|
+
[ "AWS/DynamoDB", "ReturnedItemCount", "TableName", "${self:custom.funktor.JobsTableName}", "Operation", "Query" ]
|
442
442
|
],
|
443
443
|
"view": "singleValue",
|
444
444
|
"region": "us-east-1",
|
@@ -455,7 +455,7 @@ Resources:
|
|
455
455
|
"type": "metric",
|
456
456
|
"properties": {
|
457
457
|
"metrics": [
|
458
|
-
[ "AWS/Lambda", "Duration", "FunctionName", "${self:
|
458
|
+
[ "AWS/Lambda", "Duration", "FunctionName", "${self:custom.funktor.JobActivatorName}", "Resource", "${self:custom.funktor.JobActivatorName}", { "label": "p10" } ],
|
459
459
|
[ "...", { "label": "p50", "stat": "p50" } ],
|
460
460
|
[ "...", { "label": "p99", "stat": "p99" } ],
|
461
461
|
[ "...", { "label": "Average", "stat": "Average" } ]
|
@@ -480,7 +480,7 @@ Resources:
|
|
480
480
|
"properties": {
|
481
481
|
"period": 60,
|
482
482
|
"metrics": [
|
483
|
-
[ "AWS/Lambda", "Errors", "FunctionName", "${self:
|
483
|
+
[ "AWS/Lambda", "Errors", "FunctionName", "${self:custom.funktor.JobActivatorName}", { "id": "errors", "stat": "Sum", "color": "#d13212" } ],
|
484
484
|
[ ".", "Invocations", ".", ".", { "id": "invocations", "stat": "Sum", "visible": false } ],
|
485
485
|
[ { "expression": "100 - 100 * errors / MAX([errors, invocations])", "label": "Success rate (%)", "id": "availability", "yAxis": "right", "region": "us-east-1" } ]
|
486
486
|
],
|
@@ -505,7 +505,7 @@ Resources:
|
|
505
505
|
"properties": {
|
506
506
|
"period": 60,
|
507
507
|
"metrics": [
|
508
|
-
[ "AWS/Lambda", "Duration", "FunctionName", "${self:
|
508
|
+
[ "AWS/Lambda", "Duration", "FunctionName", "${self:custom.funktor.JobActivatorName}", { "stat": "Minimum" } ],
|
509
509
|
[ "...", { "stat": "Average" } ],
|
510
510
|
[ "...", { "stat": "Maximum" } ]
|
511
511
|
],
|
@@ -524,7 +524,7 @@ Resources:
|
|
524
524
|
"type": "metric",
|
525
525
|
"properties": {
|
526
526
|
"metrics": [
|
527
|
-
[ "AWS/DynamoDB", "ReturnedItemCount", "TableName", "${self:
|
527
|
+
[ "AWS/DynamoDB", "ReturnedItemCount", "TableName", "${self:custom.funktor.JobsTableName}", "Operation", "Query" ]
|
528
528
|
],
|
529
529
|
"view": "timeSeries",
|
530
530
|
"stacked": false,
|
@@ -547,7 +547,7 @@ Resources:
|
|
547
547
|
"properties": {
|
548
548
|
"metrics": [
|
549
549
|
[ { "expression": "m2/PERIOD(m2)", "label": "Consumed Read Capacity Units", "id": "e1", "stat": "Sum", "region": "us-east-1" } ],
|
550
|
-
[ "AWS/DynamoDB", "ConsumedReadCapacityUnits", "TableName", "${self:
|
550
|
+
[ "AWS/DynamoDB", "ConsumedReadCapacityUnits", "TableName", "${self:custom.funktor.JobsTableName}", { "id": "m2", "visible": false } ],
|
551
551
|
[ ".", "ConsumedWriteCapacityUnits", ".", ".", { "yAxis": "left", "id": "m4", "visible": false } ],
|
552
552
|
[ ".", "WriteThrottleEvents", ".", ".", { "yAxis": "right", "id": "m5", "visible": false } ]
|
553
553
|
],
|
@@ -569,7 +569,7 @@ Resources:
|
|
569
569
|
"properties": {
|
570
570
|
"period": 60,
|
571
571
|
"metrics": [
|
572
|
-
[ "AWS/Lambda", "ConcurrentExecutions", "FunctionName", "${self:
|
572
|
+
[ "AWS/Lambda", "ConcurrentExecutions", "FunctionName", "${self:custom.funktor.JobActivatorName}", { "stat": "Maximum" } ]
|
573
573
|
],
|
574
574
|
"region": "us-east-1",
|
575
575
|
"title": "Delayd Job Schedule Concurrent executions",
|
@@ -587,7 +587,7 @@ Resources:
|
|
587
587
|
"properties": {
|
588
588
|
"metrics": [
|
589
589
|
[ { "expression": "m4/PERIOD(m4)", "label": "Consumed Read Capacity Units", "id": "e1", "stat": "Sum", "region": "us-east-1" } ],
|
590
|
-
[ "AWS/DynamoDB", "ConsumedReadCapacityUnits", "TableName", "${self:
|
590
|
+
[ "AWS/DynamoDB", "ConsumedReadCapacityUnits", "TableName", "${self:custom.funktor.JobsTableName}", { "id": "m2", "visible": false } ],
|
591
591
|
[ ".", "ConsumedWriteCapacityUnits", ".", ".", { "yAxis": "left", "id": "m4", "visible": false } ],
|
592
592
|
[ ".", "WriteThrottleEvents", ".", ".", { "yAxis": "right", "id": "m5", "visible": false } ]
|
593
593
|
],
|
@@ -612,7 +612,7 @@ Resources:
|
|
612
612
|
"type": "metric",
|
613
613
|
"properties": {
|
614
614
|
"metrics": [
|
615
|
-
[ "AWS/DynamoDB", "SuccessfulRequestLatency", "TableName", "${self:
|
615
|
+
[ "AWS/DynamoDB", "SuccessfulRequestLatency", "TableName", "${self:custom.funktor.JobsTableName}", "Operation", "PutItem", { "yAxis": "left" } ],
|
616
616
|
[ "...", "Query" ],
|
617
617
|
[ ".", "ThrottledRequests", ".", ".", ".", "PutItem", { "yAxis": "right", "visible": false } ],
|
618
618
|
[ ".", "SuccessfulRequestLatency", ".", ".", ".", "DeleteItem" ],
|
@@ -635,7 +635,7 @@ Resources:
|
|
635
635
|
"type": "metric",
|
636
636
|
"properties": {
|
637
637
|
"metrics": [
|
638
|
-
[ "AWS/DynamoDB", "ThrottledRequests", "TableName", "${self:
|
638
|
+
[ "AWS/DynamoDB", "ThrottledRequests", "TableName", "${self:custom.funktor.JobsTableName}", "Operation", "DeleteItem" ],
|
639
639
|
[ "...", "PutItem" ]
|
640
640
|
],
|
641
641
|
"view": "timeSeries",
|
@@ -0,0 +1,44 @@
|
|
1
|
+
Resources:
|
2
|
+
JobsTable:
|
3
|
+
Type: AWS::DynamoDB::Table
|
4
|
+
Properties:
|
5
|
+
TableName: ${self:custom.funktor.JobsTableName}
|
6
|
+
AttributeDefinitions:
|
7
|
+
- AttributeName: jobShard
|
8
|
+
AttributeType: N
|
9
|
+
- AttributeName: jobId
|
10
|
+
AttributeType: S
|
11
|
+
#- AttributeName: category
|
12
|
+
#AttributeType: S
|
13
|
+
- AttributeName: performAt
|
14
|
+
AttributeType: S
|
15
|
+
- AttributeName: dummy
|
16
|
+
AttributeType: S
|
17
|
+
KeySchema:
|
18
|
+
- AttributeName: jobShard
|
19
|
+
KeyType: HASH
|
20
|
+
- AttributeName: jobId
|
21
|
+
KeyType: RANGE
|
22
|
+
GlobalSecondaryIndexes:
|
23
|
+
- IndexName: performAtIndex
|
24
|
+
KeySchema:
|
25
|
+
- AttributeName: dummy
|
26
|
+
KeyType: HASH
|
27
|
+
- AttributeName: performAt
|
28
|
+
KeyType: RANGE
|
29
|
+
Projection:
|
30
|
+
NonKeyAttributes:
|
31
|
+
- jobId
|
32
|
+
- payload
|
33
|
+
- category
|
34
|
+
ProjectionType: INCLUDE
|
35
|
+
BillingMode: PAY_PER_REQUEST
|
36
|
+
# Set the capacity based on the stage
|
37
|
+
#ProvisionedThroughput:
|
38
|
+
#ReadCapacityUnits: ${self:custom.tableThroughput}
|
39
|
+
#WriteCapacityUnits: ${self:custom.tableThroughput}
|
40
|
+
|
41
|
+
Outputs:
|
42
|
+
JobsTable:
|
43
|
+
Value:
|
44
|
+
Ref: JobsTable
|
@@ -49,6 +49,8 @@ incomingJobHandler:
|
|
49
49
|
# to quickly handle jobs at the beginning of a burst. Uncomment the line below if so.
|
50
50
|
# provisionedConcurrency: 4
|
51
51
|
|
52
|
+
jobActivator:
|
53
|
+
# You probably don't need to adjust the defaults for this one.
|
52
54
|
|
53
55
|
queues:
|
54
56
|
- default:
|
@@ -59,11 +61,3 @@ queues:
|
|
59
61
|
- singleThread:
|
60
62
|
reservedConcurrency: 1
|
61
63
|
|
62
|
-
# TODO - Maybe this shouldn't be surfaced this early?
|
63
|
-
# TODO - This still needs to be wired up to do anything.
|
64
|
-
package:
|
65
|
-
patterns:
|
66
|
-
- Gemfile
|
67
|
-
- Gemfile.lock
|
68
|
-
- app/**
|
69
|
-
- funktor_config/**
|
@@ -3,8 +3,8 @@
|
|
3
3
|
# This file is the main config file for your service.
|
4
4
|
# It's already configured to run Funktor, you just have to deploy it.
|
5
5
|
#
|
6
|
-
# For more info about Funktor:
|
7
|
-
#
|
6
|
+
# For more info about Funktor check the wiki:
|
7
|
+
# https://github.com/Octo-Labs/funktor/wiki
|
8
8
|
#
|
9
9
|
# For more about serverless, check their docs:
|
10
10
|
# docs.serverless.com
|
data/lib/funktor/counter.rb
CHANGED
@@ -11,7 +11,10 @@ module Funktor
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def put_metric_to_stdout(job)
|
14
|
-
puts Funktor.
|
14
|
+
# NOTE : We use raw puts here instead of Funktor.logger.something to avoid getting extra
|
15
|
+
# timestamps or log level information in the log line. We need this specific format to
|
16
|
+
# be the only thing in the line so that CloudWatch can parse the logs and use the data.
|
17
|
+
Funktor.raw_logger.unknown Funktor.dump_json(metric_hash(job))
|
15
18
|
end
|
16
19
|
|
17
20
|
def metric_hash(job)
|
@@ -1,12 +1,17 @@
|
|
1
1
|
require 'aws-sdk-sqs'
|
2
|
+
require 'aws-sdk-dynamodb'
|
2
3
|
require 'active_support/core_ext/string/inflections'
|
3
4
|
|
4
5
|
module Funktor
|
5
6
|
class IncomingJobHandler
|
6
7
|
|
8
|
+
def initialize
|
9
|
+
@tracker = Funktor::ActivityTracker.new
|
10
|
+
end
|
11
|
+
|
7
12
|
def call(event:, context:)
|
8
13
|
event = Funktor::Aws::Sqs::Event.new(event)
|
9
|
-
|
14
|
+
Funktor.logger.debug "event.jobs.count = #{event.jobs.count}"
|
10
15
|
event.jobs.each do |job|
|
11
16
|
dispatch(job)
|
12
17
|
end
|
@@ -16,34 +21,69 @@ module Funktor
|
|
16
21
|
@sqs_client ||= ::Aws::SQS::Client.new
|
17
22
|
end
|
18
23
|
|
24
|
+
def dynamodb_client
|
25
|
+
@dynamodb_client ||= ::Aws::DynamoDB::Client.new
|
26
|
+
end
|
27
|
+
|
19
28
|
def dispatch(job)
|
20
29
|
Funktor.incoming_job_handler_middleware.invoke(job) do
|
21
|
-
|
22
|
-
|
30
|
+
# TODO : This number should be configurable via ENV var
|
31
|
+
if job.delay < 60 # for now we're testing with just one minute * 5 # 5 minutes
|
32
|
+
Funktor.logger.debug "pushing to work queue for delay = #{job.delay}"
|
33
|
+
push_to_work_queue(job)
|
34
|
+
if job.is_retry?
|
35
|
+
@tracker.track(:retryActivated, job)
|
36
|
+
else
|
37
|
+
@tracker.track(:queued, job)
|
38
|
+
end
|
39
|
+
else
|
40
|
+
Funktor.logger.debug "pushing to jobs table for delay = #{job.delay}"
|
41
|
+
push_to_jobs_table(job)
|
42
|
+
if job.is_retry?
|
43
|
+
# do nothing for tracking
|
44
|
+
else
|
45
|
+
@tracker.track(:scheduled, job)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
@tracker.track(:incoming, job)
|
23
49
|
end
|
24
50
|
end
|
25
51
|
|
26
|
-
def active_job_queue
|
27
|
-
ENV['FUNKTOR_ACTIVE_JOB_QUEUE']
|
28
|
-
end
|
29
|
-
|
30
52
|
def queue_for_job(job)
|
31
53
|
queue_name = job.queue || 'default'
|
32
54
|
queue_constant = "FUNKTOR_#{queue_name.underscore.upcase}_QUEUE"
|
33
|
-
|
34
|
-
|
55
|
+
Funktor.logger.debug "queue_constant = #{queue_constant}"
|
56
|
+
Funktor.logger.debug "ENV value = #{ENV[queue_constant]}"
|
35
57
|
ENV[queue_constant] || ENV['FUNKTOR_DEFAULT_QUEUE']
|
36
58
|
end
|
37
59
|
|
38
|
-
def
|
39
|
-
|
60
|
+
def push_to_work_queue(job)
|
61
|
+
Funktor.logger.debug "job = #{job.to_json}"
|
40
62
|
sqs_client.send_message({
|
41
|
-
# TODO : How to get this URL...
|
42
63
|
queue_url: queue_for_job(job),
|
43
64
|
message_body: job.to_json,
|
44
65
|
delay_seconds: job.delay
|
45
66
|
})
|
46
67
|
end
|
47
68
|
|
69
|
+
def delayed_job_table
|
70
|
+
ENV['FUNKTOR_JOBS_TABLE']
|
71
|
+
end
|
72
|
+
|
73
|
+
def push_to_jobs_table(job)
|
74
|
+
perform_at = (Time.now + job.delay).utc
|
75
|
+
resp = dynamodb_client.put_item({
|
76
|
+
item: {
|
77
|
+
payload: job.to_json,
|
78
|
+
jobId: job.job_id,
|
79
|
+
performAt: perform_at.iso8601,
|
80
|
+
jobShard: job.shard,
|
81
|
+
dummy: "dummy",
|
82
|
+
category: job.is_retry? ? "retry" : "scheduled"
|
83
|
+
},
|
84
|
+
table_name: delayed_job_table
|
85
|
+
})
|
86
|
+
end
|
87
|
+
|
48
88
|
end
|
49
89
|
end
|
data/lib/funktor/job.rb
CHANGED
@@ -22,6 +22,11 @@ module Funktor
|
|
22
22
|
job_data["job_id"]
|
23
23
|
end
|
24
24
|
|
25
|
+
def shard
|
26
|
+
# TODO - Should the number of shards be configurable?
|
27
|
+
job_data["job_id"].hash % 64
|
28
|
+
end
|
29
|
+
|
25
30
|
def worker_params
|
26
31
|
job_data["worker_params"]
|
27
32
|
end
|
@@ -30,16 +35,16 @@ module Funktor
|
|
30
35
|
job_data["retries"] || 0
|
31
36
|
end
|
32
37
|
|
38
|
+
def is_retry?
|
39
|
+
job_data["retries"].present?
|
40
|
+
end
|
41
|
+
|
33
42
|
def retries=(retries)
|
34
43
|
job_data["retries"] = retries
|
35
44
|
end
|
36
45
|
|
37
46
|
def delay
|
38
|
-
|
39
|
-
# we can schedule jobs farther in the future than 15 minutes. We do this here in case a
|
40
|
-
# retry sequence goes too long.
|
41
|
-
jdelay = job_data["delay"] || 0
|
42
|
-
return jdelay < 900 ? jdelay : 900
|
47
|
+
job_data["delay"] || 0
|
43
48
|
end
|
44
49
|
|
45
50
|
def delay=(delay)
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'aws-sdk-dynamodb'
|
2
|
+
require 'aws-sdk-sqs'
|
3
|
+
|
4
|
+
module Funktor
|
5
|
+
class JobActivator
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@tracker = Funktor::ActivityTracker.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def dynamodb_client
|
12
|
+
@dynamodb_client ||= ::Aws::DynamoDB::Client.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def sqs_client
|
16
|
+
@sqs_client ||= ::Aws::SQS::Client.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def active_job_queue
|
20
|
+
ENV['FUNKTOR_ACTIVE_JOB_QUEUE']
|
21
|
+
end
|
22
|
+
|
23
|
+
def delayed_job_table
|
24
|
+
ENV['FUNKTOR_JOBS_TABLE']
|
25
|
+
end
|
26
|
+
|
27
|
+
def jobs_to_activate
|
28
|
+
target_time = (Time.now + 90).utc
|
29
|
+
query_params = {
|
30
|
+
expression_attribute_values: {
|
31
|
+
":dummy" => "dummy",
|
32
|
+
":targetTime" => target_time.iso8601
|
33
|
+
},
|
34
|
+
key_condition_expression: "dummy = :dummy AND performAt < :targetTime",
|
35
|
+
projection_expression: "payload, performAt, jobId, jobShard",
|
36
|
+
table_name: delayed_job_table,
|
37
|
+
index_name: "performAtIndex"
|
38
|
+
}
|
39
|
+
resp = dynamodb_client.query(query_params)
|
40
|
+
return resp.items
|
41
|
+
end
|
42
|
+
|
43
|
+
def queue_for_job(job)
|
44
|
+
queue_name = job.queue || 'default'
|
45
|
+
queue_constant = "FUNKTOR_#{queue_name.underscore.upcase}_QUEUE"
|
46
|
+
Funktor.logger.debug "queue_constant = #{queue_constant}"
|
47
|
+
Funktor.logger.debug "ENV value = #{ENV[queue_constant]}"
|
48
|
+
ENV[queue_constant] || ENV['FUNKTOR_DEFAULT_QUEUE']
|
49
|
+
end
|
50
|
+
|
51
|
+
def handle_item(item)
|
52
|
+
job = Funktor::Job.new(item["payload"])
|
53
|
+
Funktor.logger.debug "we created a job from payload"
|
54
|
+
Funktor.logger.debug item["payload"]
|
55
|
+
delay = (Time.parse(item["performAt"]) - Time.now.utc).to_i
|
56
|
+
if delay < 0
|
57
|
+
delay = 0
|
58
|
+
end
|
59
|
+
Funktor.logger.debug "jobShard = #{item['jobShard']}"
|
60
|
+
Funktor.logger.debug "jobId = #{item['jobId']}"
|
61
|
+
# First we delete the item from Dynamo to be sure that another scheduler hasn't gotten to it,
|
62
|
+
# and if that works then send to SQS. This is basically how Sidekiq scheduler works.
|
63
|
+
response = dynamodb_client.delete_item({
|
64
|
+
key: {
|
65
|
+
"jobShard" => item["jobShard"],
|
66
|
+
"jobId" => item["jobId"]
|
67
|
+
},
|
68
|
+
table_name: delayed_job_table,
|
69
|
+
return_values: "ALL_OLD"
|
70
|
+
})
|
71
|
+
if response.attributes # this means the record was still there
|
72
|
+
sqs_client.send_message({
|
73
|
+
# TODO : How to get this URL...
|
74
|
+
queue_url: queue_for_job(job),
|
75
|
+
message_body: item["payload"],
|
76
|
+
delay_seconds: delay
|
77
|
+
})
|
78
|
+
if job.is_retry?
|
79
|
+
@tracker.track(:retryActivated, job)
|
80
|
+
else
|
81
|
+
@tracker.track(:scheduledJobActivated, job)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def call(event:, context:)
|
87
|
+
handled_item_count = 0
|
88
|
+
jobs_to_activate.each do |item|
|
89
|
+
if context.get_remaining_time_in_millis < 5_000 # This lets us exit gracefully and resume on the next round instead of getting forcibly killed.
|
90
|
+
puts "Bailing out due to milliseconds remaining #{context.get_remaining_time_in_millis}"
|
91
|
+
break
|
92
|
+
end
|
93
|
+
handle_item(item)
|
94
|
+
handled_item_count += 1
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/funktor/job_pusher.rb
CHANGED
@@ -10,7 +10,12 @@ module Funktor
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def put_metric_to_stdout(time_diff, job)
|
13
|
-
|
13
|
+
# NOTE : We use raw_logger here instead of Funktor.loggert o avoid getting extra
|
14
|
+
# timestamps or log level information in the log line. We need this specific format to
|
15
|
+
# be the only thing in the line so that CloudWatch can parse the logs and use the data.
|
16
|
+
# 'unknown' is a log level that will always be logged, no matter what is set in the
|
17
|
+
# runtime environment as far as log level.
|
18
|
+
Funktor.raw_logger.unknown Funktor.dump_json(metric_hash(time_diff, job))
|
14
19
|
end
|
15
20
|
|
16
21
|
def metric_hash(time_diff_in_seconds, job)
|
@@ -43,8 +48,8 @@ module Funktor
|
|
43
48
|
end
|
44
49
|
end
|
45
50
|
|
46
|
-
Funktor.
|
47
|
-
config.
|
51
|
+
Funktor.configure_work_queue_handler do |config|
|
52
|
+
config.work_queue_handler_middleware do |chain|
|
48
53
|
chain.add Funktor::Middleware::Metrics
|
49
54
|
end
|
50
55
|
end
|