funktor 0.4.6 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/.tool-versions +2 -0
  3. data/Gemfile.lock +24 -5
  4. data/funktor-testapp/.envrc +1 -0
  5. data/funktor-testapp/.gitignore +7 -0
  6. data/funktor-testapp/Gemfile +25 -0
  7. data/funktor-testapp/Gemfile.lock +51 -0
  8. data/funktor-testapp/app/services/job_flood.rb +38 -0
  9. data/funktor-testapp/app/workers/audit_worker.rb +49 -0
  10. data/funktor-testapp/app/workers/greetings_worker.rb +3 -0
  11. data/funktor-testapp/app/workers/hello_worker.rb +18 -0
  12. data/funktor-testapp/app/workers/single_thread_audit_worker.rb +3 -0
  13. data/funktor-testapp/deploy-dev.sh +5 -0
  14. data/funktor-testapp/funktor_config/boot.rb +17 -0
  15. data/funktor-testapp/funktor_config/environment.yml +15 -0
  16. data/funktor-testapp/funktor_config/function_definitions/default_queue_handler.yml +13 -0
  17. data/funktor-testapp/funktor_config/function_definitions/incoming_job_handler.yml +13 -0
  18. data/funktor-testapp/funktor_config/function_definitions/job_activator.yml +7 -0
  19. data/funktor-testapp/funktor_config/function_definitions/low_concurrency_queue_handler.yml +13 -0
  20. data/funktor-testapp/funktor_config/function_definitions/random_job_generator.yml +18 -0
  21. data/funktor-testapp/funktor_config/funktor.yml +114 -0
  22. data/funktor-testapp/funktor_config/iam_permissions/activity_table.yml +5 -0
  23. data/funktor-testapp/funktor_config/iam_permissions/default_queue.yml +8 -0
  24. data/funktor-testapp/funktor_config/iam_permissions/incoming_job_queue.yml +8 -0
  25. data/funktor-testapp/funktor_config/iam_permissions/jobs_table.yml +5 -0
  26. data/funktor-testapp/funktor_config/iam_permissions/jobs_table_secondary_index.yml +8 -0
  27. data/funktor-testapp/funktor_config/iam_permissions/low_concurrency_queue.yml +8 -0
  28. data/funktor-testapp/funktor_config/iam_permissions/ssm.yml +5 -0
  29. data/funktor-testapp/funktor_config/package.yml +11 -0
  30. data/funktor-testapp/funktor_config/resources/activity_table.yml +22 -0
  31. data/funktor-testapp/funktor_config/resources/cloudwatch_dashboard.yml +809 -0
  32. data/funktor-testapp/funktor_config/resources/default_queue.yml +22 -0
  33. data/funktor-testapp/funktor_config/resources/incoming_job_queue.yml +22 -0
  34. data/funktor-testapp/funktor_config/resources/incoming_job_queue_user.yml +26 -0
  35. data/funktor-testapp/funktor_config/resources/jobs_table.yml +56 -0
  36. data/funktor-testapp/funktor_config/resources/low_concurrency_queue.yml +22 -0
  37. data/funktor-testapp/funktor_config/ruby_layer.yml +11 -0
  38. data/funktor-testapp/funktor_init.yml +69 -0
  39. data/funktor-testapp/lambda_event_handlers/default_queue_handler.rb +8 -0
  40. data/funktor-testapp/lambda_event_handlers/incoming_job_handler.rb +8 -0
  41. data/funktor-testapp/lambda_event_handlers/job_activator.rb +8 -0
  42. data/funktor-testapp/lambda_event_handlers/low_concurrency_queue_handler.rb +8 -0
  43. data/funktor-testapp/lambda_event_handlers/random_job_generator.rb +35 -0
  44. data/funktor-testapp/package-lock.json +248 -0
  45. data/funktor-testapp/package.json +8 -0
  46. data/funktor-testapp/serverless.yml +66 -0
  47. data/funktor.gemspec +4 -1
  48. data/lib/active_job/queue_adapters/funktor_adapter.rb +3 -3
  49. data/lib/funktor/activity_tracker.rb +106 -0
  50. data/lib/funktor/cli/bootstrap.rb +0 -1
  51. data/lib/funktor/cli/init.rb +13 -0
  52. data/lib/funktor/cli/templates/app/workers/hello_worker.rb +1 -1
  53. data/lib/funktor/cli/templates/funktor_config/environment.yml +4 -0
  54. data/lib/funktor/cli/templates/funktor_config/function_definitions/incoming_job_handler.yml +3 -1
  55. data/lib/funktor/cli/templates/funktor_config/function_definitions/job_activator.yml +7 -0
  56. data/lib/funktor/cli/templates/funktor_config/function_definitions/work_queue_handler.yml +3 -1
  57. data/lib/funktor/cli/templates/funktor_config/funktor.yml +32 -6
  58. data/lib/funktor/cli/templates/funktor_config/iam_permissions/activity_table.yml +5 -0
  59. data/lib/funktor/cli/templates/funktor_config/iam_permissions/jobs_table.yml +5 -0
  60. data/lib/funktor/cli/templates/funktor_config/iam_permissions/jobs_table_secondary_index.yml +8 -0
  61. data/lib/funktor/cli/templates/funktor_config/resources/activity_table.yml +22 -0
  62. data/lib/funktor/cli/templates/funktor_config/resources/cloudwatch_dashboard.yml +13 -12
  63. data/lib/funktor/cli/templates/funktor_config/resources/incoming_job_queue.yml +2 -2
  64. data/lib/funktor/cli/templates/funktor_config/resources/jobs_table.yml +56 -0
  65. data/lib/funktor/cli/templates/funktor_config/resources/work_queue.yml +2 -2
  66. data/lib/funktor/cli/templates/funktor_init.yml.tt +16 -16
  67. data/lib/funktor/cli/templates/lambda_event_handlers/job_activator.rb +8 -0
  68. data/lib/funktor/cli/templates/lambda_event_handlers/work_queue_handler.rb +1 -1
  69. data/lib/funktor/cli/templates/serverless.yml +3 -2
  70. data/lib/funktor/counter.rb +4 -1
  71. data/lib/funktor/incoming_job_handler.rb +54 -18
  72. data/lib/funktor/job.rb +57 -7
  73. data/lib/funktor/job_activator.rb +124 -0
  74. data/lib/funktor/job_pusher.rb +0 -2
  75. data/lib/funktor/middleware/metrics.rb +8 -3
  76. data/lib/funktor/shard_utils.rb +6 -0
  77. data/lib/funktor/testing.rb +52 -29
  78. data/lib/funktor/version.rb +1 -1
  79. data/lib/funktor/web/application.rb +139 -0
  80. data/lib/funktor/web/views/index.erb +3 -0
  81. data/lib/funktor/web/views/layout.erb +58 -0
  82. data/lib/funktor/web/views/processing.erb +29 -0
  83. data/lib/funktor/web/views/queued.erb +29 -0
  84. data/lib/funktor/web/views/retries.erb +35 -0
  85. data/lib/funktor/web/views/scheduled.erb +26 -0
  86. data/lib/funktor/web/views/stats.erb +9 -0
  87. data/lib/funktor/web/views/table_stats_with_buttons.erb +11 -0
  88. data/lib/funktor/web.rb +1 -0
  89. data/lib/funktor/work_queue_handler.rb +101 -0
  90. data/lib/funktor/worker/funktor_options.rb +3 -1
  91. data/lib/funktor/worker.rb +8 -18
  92. data/lib/funktor.rb +52 -20
  93. metadata +109 -3
  94. data/lib/funktor/active_job_handler.rb +0 -58
@@ -0,0 +1,22 @@
1
+ Resources:
2
+ DefaultQueue:
3
+ Type: AWS::SQS::Queue
4
+ Properties:
5
+ QueueName: ${self:custom.funktor.DefaultQueueName}
6
+ VisibilityTimeout: ${self:custom.funktor.DefaultQueueHandler.visibilityTimeout}
7
+ RedrivePolicy:
8
+ deadLetterTargetArn:
9
+ "Fn::GetAtt": [ DefaultDeadLetterQueue, Arn ]
10
+ maxReceiveCount: ${self:custom.funktor.DefaultQueueHandler.maxReceiveCount}
11
+ DefaultDeadLetterQueue:
12
+ Type: AWS::SQS::Queue
13
+ Properties:
14
+ QueueName: ${self:custom.funktor.DefaultDeadJobQueueName}
15
+
16
+ Outputs:
17
+ DefaultQueueUrl:
18
+ Value:
19
+ Ref: DefaultQueue
20
+ DefaultDeadLetterQueueUrl:
21
+ Value:
22
+ Ref: DefaultDeadLetterQueue
@@ -0,0 +1,22 @@
1
+ Resources:
2
+ IncomingJobQueue:
3
+ Type: AWS::SQS::Queue
4
+ Properties:
5
+ QueueName: ${self:custom.funktor.IncomingJobQueueName}
6
+ VisibilityTimeout: ${self:custom.funktor.IncomingJobHandler.visibilityTimeout}
7
+ RedrivePolicy:
8
+ deadLetterTargetArn:
9
+ "Fn::GetAtt": [ IncomingJobDeadLetterQueue, Arn ]
10
+ maxReceiveCount: ${self:custom.funktor.IncomingJobHandler.maxReceiveCount}
11
+ IncomingJobDeadLetterQueue:
12
+ Type: AWS::SQS::Queue
13
+ Properties:
14
+ QueueName: ${self:custom.funktor.IncomingDeadJobQueueName}
15
+
16
+ Outputs:
17
+ IncomingJobQueueUrl:
18
+ Value:
19
+ Ref: IncomingJobQueue
20
+ IncomingJobDeadLetterQueueUrl:
21
+ Value:
22
+ Ref: IncomingJobDeadLetterQueue
@@ -0,0 +1,26 @@
1
+ Resources:
2
+ IncomingJobQueueUser:
3
+ Type: AWS::IAM::User
4
+ Properties:
5
+ Policies:
6
+ - PolicyName: incoming-job-queue-access
7
+ PolicyDocument:
8
+ Version: '2012-10-17'
9
+ Statement:
10
+ - Effect: Allow
11
+ Action:
12
+ - sqs:*
13
+ Resource:
14
+ - "Fn::GetAtt": [ IncomingJobQueue, Arn ]
15
+
16
+ IncomingJobQueueUserAccessKey:
17
+ Type: AWS::IAM::AccessKey
18
+ Properties:
19
+ UserName: !Ref IncomingJobQueueUser
20
+
21
+
22
+ Outputs:
23
+ AccessKeyID:
24
+ Value: !Ref IncomingJobQueueUserAccessKey
25
+ SecretAccessKey:
26
+ Value: !GetAtt IncomingJobQueueUserAccessKey.SecretAccessKey
@@ -0,0 +1,56 @@
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: queueable
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: 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
38
+ KeyType: HASH
39
+ - AttributeName: performAt
40
+ KeyType: RANGE
41
+ Projection:
42
+ NonKeyAttributes:
43
+ - jobId
44
+ - payload
45
+ - category
46
+ ProjectionType: INCLUDE
47
+ BillingMode: PAY_PER_REQUEST
48
+ # Set the capacity based on the stage
49
+ #ProvisionedThroughput:
50
+ #ReadCapacityUnits: ${self:custom.tableThroughput}
51
+ #WriteCapacityUnits: ${self:custom.tableThroughput}
52
+
53
+ Outputs:
54
+ JobsTable:
55
+ Value:
56
+ Ref: JobsTable
@@ -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
@@ -0,0 +1,11 @@
1
+ use_docker: false
2
+ #docker_yums:
3
+ #- postgresql-devel
4
+ #native_libs:
5
+ #- /usr/lib64/libpq.so.5
6
+ #- /usr/lib64/libldap_r-2.4.so.2
7
+ #- /usr/lib64/liblber-2.4.so.2
8
+ #- /usr/lib64/libsasl2.so.3
9
+ #- /usr/lib64/libssl3.so
10
+ #- /usr/lib64/libsmime3.so
11
+ #- /usr/lib64/libnss3.so
@@ -0,0 +1,69 @@
1
+ # ℹ️ WARNING: This file doesn't control anything directly. It's used to allow you to set/maintain config options in a central place.
2
+ # When you make changes to this file you should run `funktor init` again to propagate the changes to the 'active' configuration files.
3
+ appName: funktor-testapp
4
+ runtime: ruby2.7
5
+
6
+ # These values will be applied to any funktor handlers that don't specify custom values.
7
+ # TODO - These still need to be wired up to do anything.
8
+ handlerDefaults:
9
+ # timeout is how long the handler can possibly run. Up to 10 messages may be delivered
10
+ # to a handler at one time, so you'll want this to be at least 10x the maximum time you
11
+ # expect to spend for one message. We default to a high number here to allow for the
12
+ # times when things go weird.
13
+ functionTimeout: 300
14
+
15
+ # reservedConcurrency represents the maximum number of concurrent executions.
16
+ # Usually you'll want to leave this as null so that handlers can scale infinitely
17
+ # (within your account limits). If you need to restrict concurrency to prevent
18
+ # resource exhaustion you should do it at the queue level.
19
+ reservedConcurrency: null
20
+
21
+ # provisionedConcurrency represents the number of lambda functions that will always
22
+ # be available. You probably want to set this on individual queues if you're going
23
+ # to use it.
24
+ provisionedConcurrency: null
25
+
26
+ # Use memory_size to adjust the reousrces (both memory and CPU) available.
27
+ # We default to 256 as a reasonable trade off on saving money but getting
28
+ # reasonable performance.
29
+ memorySize: 256
30
+
31
+ # You can set the batch size. Max of 10_000 for normal queues, 10 for FIFO.
32
+ batchSize: 1
33
+
34
+ # How many seconds should AWS wait for a batch to fill up before executing lambda?
35
+ # For immediate execution set the batch size to 1.
36
+ maximumBatchingWindow : 0
37
+
38
+ # Visibility timeout should only come into play in the case of Funktor errors.
39
+ # Application level errors should be handled by Funktor retry mechanisms.
40
+ # The visibility timeout should be at least as long as the function timeout, and up to 6 times larger.
41
+ visibilityTimeout: 1800
42
+
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
47
+
48
+ # Incoming Job Handler
49
+ incomingJobHandler:
50
+ # If your jobs are bursty AND time-sensitive you might want to have some lambdas pre-provisioned
51
+ # to quickly handle jobs at the beginning of a burst. Uncomment the line below if so.
52
+ # provisionedConcurrency: 4
53
+
54
+ jobActivator:
55
+ # You probably don't need to adjust the defaults for this one.
56
+
57
+ queues:
58
+ - default:
59
+ # Set queue specific config options here
60
+ # memorySize: 512
61
+ # TODO - Is it advisable to use FIFO queuues with Funktor? Maybe this isn't really even supported by CloudFormation?
62
+ # fifo: false
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
69
+
@@ -0,0 +1,8 @@
1
+ require_relative '../funktor_config/boot'
2
+
3
+ $handler = Funktor::WorkQueueHandler.new
4
+
5
+ def call(event:, context:)
6
+ $handler.call(event: event, context: context)
7
+ end
8
+
@@ -0,0 +1,8 @@
1
+ require_relative '../funktor_config/boot'
2
+
3
+ $handler = Funktor::IncomingJobHandler.new
4
+
5
+ def call(event:, context:)
6
+ $handler.call(event: event, context: context)
7
+ end
8
+
@@ -0,0 +1,8 @@
1
+ require_relative '../funktor_config/boot'
2
+
3
+ $handler = Funktor::JobActivator.new
4
+
5
+ def call(event:, context:)
6
+ $handler.call(event: event, context: context)
7
+ end
8
+
@@ -0,0 +1,8 @@
1
+ require_relative '../funktor_config/boot'
2
+
3
+ $handler = Funktor::WorkQueueHandler.new
4
+
5
+ def call(event:, context:)
6
+ $handler.call(event: event, context: context)
7
+ end
8
+
@@ -0,0 +1,35 @@
1
+ require_relative '../funktor_config/boot'
2
+
3
+
4
+ # This class runs on a schedule (every minute, by default) and generates a series of jobs to be
5
+ # run over the next few minutes.
6
+ class RandomJobGenerator
7
+
8
+ def self.call(event:, context:)
9
+ job_count = 0
10
+ jobs_to_generate = rand(ENV['MIN_RANDOM_JOBS_PER_MINUTE'].to_i..ENV['MAX_RANDOM_JOBS_PER_MINUTE'].to_i)
11
+ sleep_delay = 53.0/jobs_to_generate # Calculate our sleep based on the target rates
12
+ puts "jobs_to_generate = #{jobs_to_generate} and sleep_delay = #{sleep_delay}"
13
+ while context.get_remaining_time_in_millis > 5_000 do # This lets us exit gracefully and resume on the next round instead of getting forcibly killed.
14
+ delay = rand(0..ENV['MAX_JOB_DELAY_IN_SECONDS'].to_f) # Schedule the job for sometime between now and MAX_JOB_DELAY
15
+ job_sleep = rand(0..ENV['MAX_JOB_LENGTH_IN_SECONDS'].to_f) # Then sleep for up to MAX_SLEEP_DELAY
16
+ error_percentage = ENV['ERROR_PERCENTAGE'].to_i
17
+
18
+ # Schedule a job to be performed after our randomly generated delay
19
+ [HelloWorker, GreetingsWorker].sample.perform_in(delay, {
20
+ mode: 'later',
21
+ message: 'msg: from random job generator - ' + SecureRandom.hex,
22
+ delay: delay,
23
+ error_percentage: error_percentage,
24
+ job_sleep: job_sleep
25
+ })
26
+ job_count += 1
27
+ puts "message delay = #{delay} and sleep delay = #{sleep_delay} - job_count = #{job_count}"
28
+
29
+ # Now sleep before generating the next job
30
+ sleep(sleep_delay)
31
+ end
32
+ end
33
+
34
+ end
35
+
@@ -0,0 +1,248 @@
1
+ {
2
+ "name": "funktor-testapp",
3
+ "version": "0.1.0",
4
+ "lockfileVersion": 1,
5
+ "requires": true,
6
+ "dependencies": {
7
+ "balanced-match": {
8
+ "version": "1.0.2",
9
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
10
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
11
+ "dev": true
12
+ },
13
+ "bluebird": {
14
+ "version": "3.7.2",
15
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
16
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
17
+ "dev": true
18
+ },
19
+ "brace-expansion": {
20
+ "version": "1.1.11",
21
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
22
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
23
+ "dev": true,
24
+ "requires": {
25
+ "balanced-match": "^1.0.0",
26
+ "concat-map": "0.0.1"
27
+ }
28
+ },
29
+ "concat-map": {
30
+ "version": "0.0.1",
31
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
32
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
33
+ "dev": true
34
+ },
35
+ "core-util-is": {
36
+ "version": "1.0.2",
37
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
38
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
39
+ "dev": true
40
+ },
41
+ "fs-extra": {
42
+ "version": "8.1.0",
43
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
44
+ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
45
+ "dev": true,
46
+ "requires": {
47
+ "graceful-fs": "^4.2.0",
48
+ "jsonfile": "^4.0.0",
49
+ "universalify": "^0.1.0"
50
+ }
51
+ },
52
+ "fs.realpath": {
53
+ "version": "1.0.0",
54
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
55
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
56
+ "dev": true
57
+ },
58
+ "glob": {
59
+ "version": "7.1.7",
60
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
61
+ "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
62
+ "dev": true,
63
+ "requires": {
64
+ "fs.realpath": "^1.0.0",
65
+ "inflight": "^1.0.4",
66
+ "inherits": "2",
67
+ "minimatch": "^3.0.4",
68
+ "once": "^1.3.0",
69
+ "path-is-absolute": "^1.0.0"
70
+ }
71
+ },
72
+ "graceful-fs": {
73
+ "version": "4.2.6",
74
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
75
+ "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
76
+ "dev": true
77
+ },
78
+ "immediate": {
79
+ "version": "3.0.6",
80
+ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
81
+ "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=",
82
+ "dev": true
83
+ },
84
+ "inflight": {
85
+ "version": "1.0.6",
86
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
87
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
88
+ "dev": true,
89
+ "requires": {
90
+ "once": "^1.3.0",
91
+ "wrappy": "1"
92
+ }
93
+ },
94
+ "inherits": {
95
+ "version": "2.0.4",
96
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
97
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
98
+ "dev": true
99
+ },
100
+ "isarray": {
101
+ "version": "1.0.0",
102
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
103
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
104
+ "dev": true
105
+ },
106
+ "jsonfile": {
107
+ "version": "4.0.0",
108
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
109
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
110
+ "dev": true,
111
+ "requires": {
112
+ "graceful-fs": "^4.1.6"
113
+ }
114
+ },
115
+ "jszip": {
116
+ "version": "3.7.0",
117
+ "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.0.tgz",
118
+ "integrity": "sha512-Y2OlFIzrDOPWUnpU0LORIcDn2xN7rC9yKffFM/7pGhQuhO+SUhfm2trkJ/S5amjFvem0Y+1EALz/MEPkvHXVNw==",
119
+ "dev": true,
120
+ "requires": {
121
+ "lie": "~3.3.0",
122
+ "pako": "~1.0.2",
123
+ "readable-stream": "~2.3.6",
124
+ "set-immediate-shim": "~1.0.1"
125
+ }
126
+ },
127
+ "lie": {
128
+ "version": "3.3.0",
129
+ "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
130
+ "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
131
+ "dev": true,
132
+ "requires": {
133
+ "immediate": "~3.0.5"
134
+ }
135
+ },
136
+ "minimatch": {
137
+ "version": "3.0.4",
138
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
139
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
140
+ "dev": true,
141
+ "requires": {
142
+ "brace-expansion": "^1.1.7"
143
+ }
144
+ },
145
+ "once": {
146
+ "version": "1.4.0",
147
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
148
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
149
+ "dev": true,
150
+ "requires": {
151
+ "wrappy": "1"
152
+ }
153
+ },
154
+ "pako": {
155
+ "version": "1.0.11",
156
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
157
+ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
158
+ "dev": true
159
+ },
160
+ "path-is-absolute": {
161
+ "version": "1.0.1",
162
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
163
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
164
+ "dev": true
165
+ },
166
+ "process-nextick-args": {
167
+ "version": "2.0.1",
168
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
169
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
170
+ "dev": true
171
+ },
172
+ "readable-stream": {
173
+ "version": "2.3.7",
174
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
175
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
176
+ "dev": true,
177
+ "requires": {
178
+ "core-util-is": "~1.0.0",
179
+ "inherits": "~2.0.3",
180
+ "isarray": "~1.0.0",
181
+ "process-nextick-args": "~2.0.0",
182
+ "safe-buffer": "~5.1.1",
183
+ "string_decoder": "~1.1.1",
184
+ "util-deprecate": "~1.0.1"
185
+ }
186
+ },
187
+ "rimraf": {
188
+ "version": "3.0.2",
189
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
190
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
191
+ "dev": true,
192
+ "requires": {
193
+ "glob": "^7.1.3"
194
+ }
195
+ },
196
+ "safe-buffer": {
197
+ "version": "5.1.2",
198
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
199
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
200
+ "dev": true
201
+ },
202
+ "serverless-ruby-layer": {
203
+ "version": "1.5.0",
204
+ "resolved": "https://registry.npmjs.org/serverless-ruby-layer/-/serverless-ruby-layer-1.5.0.tgz",
205
+ "integrity": "sha512-hyhHmqHEPErGhPHH6QPb64ZziiFvX3PcwxKiaMQk2h30mYAvXaLEzFPpEImvvR39LOb/x+PIrjENa0iZUcXD3A==",
206
+ "dev": true,
207
+ "requires": {
208
+ "bluebird": "^3.5.5",
209
+ "fs-extra": "^8.1.0",
210
+ "jszip": "^3.1.0",
211
+ "rimraf": "^3.0.2"
212
+ }
213
+ },
214
+ "set-immediate-shim": {
215
+ "version": "1.0.1",
216
+ "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
217
+ "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
218
+ "dev": true
219
+ },
220
+ "string_decoder": {
221
+ "version": "1.1.1",
222
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
223
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
224
+ "dev": true,
225
+ "requires": {
226
+ "safe-buffer": "~5.1.0"
227
+ }
228
+ },
229
+ "universalify": {
230
+ "version": "0.1.2",
231
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
232
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
233
+ "dev": true
234
+ },
235
+ "util-deprecate": {
236
+ "version": "1.0.2",
237
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
238
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
239
+ "dev": true
240
+ },
241
+ "wrappy": {
242
+ "version": "1.0.2",
243
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
244
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
245
+ "dev": true
246
+ }
247
+ }
248
+ }