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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.tool-versions +2 -0
  3. data/Gemfile.lock +7 -3
  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/deploy-dev.sh +5 -0
  13. data/funktor-testapp/funktor_config/boot.rb +17 -0
  14. data/funktor-testapp/funktor_config/environment.yml +15 -0
  15. data/funktor-testapp/funktor_config/function_definitions/default_queue_handler.yml +11 -0
  16. data/funktor-testapp/funktor_config/function_definitions/incoming_job_handler.yml +11 -0
  17. data/funktor-testapp/funktor_config/function_definitions/job_activator.yml +8 -0
  18. data/funktor-testapp/funktor_config/function_definitions/random_job_generator.yml +18 -0
  19. data/funktor-testapp/funktor_config/function_definitions/single_thread_queue_handler.yml +11 -0
  20. data/funktor-testapp/funktor_config/funktor.yml +114 -0
  21. data/funktor-testapp/funktor_config/iam_permissions/activity_table.yml +5 -0
  22. data/funktor-testapp/funktor_config/iam_permissions/default_queue.yml +8 -0
  23. data/funktor-testapp/funktor_config/iam_permissions/incoming_job_queue.yml +8 -0
  24. data/funktor-testapp/funktor_config/iam_permissions/jobs_table.yml +5 -0
  25. data/funktor-testapp/funktor_config/iam_permissions/jobs_table_secondary_index.yml +8 -0
  26. data/funktor-testapp/funktor_config/iam_permissions/single_thread_queue.yml +8 -0
  27. data/funktor-testapp/funktor_config/iam_permissions/ssm.yml +5 -0
  28. data/funktor-testapp/funktor_config/package.yml +11 -0
  29. data/funktor-testapp/funktor_config/resources/activity_table.yml +22 -0
  30. data/funktor-testapp/funktor_config/resources/cloudwatch_dashboard.yml +804 -0
  31. data/funktor-testapp/funktor_config/resources/default_queue.yml +22 -0
  32. data/funktor-testapp/funktor_config/resources/incoming_job_queue.yml +22 -0
  33. data/funktor-testapp/funktor_config/resources/incoming_job_queue_user.yml +26 -0
  34. data/funktor-testapp/funktor_config/resources/jobs_table.yml +44 -0
  35. data/funktor-testapp/funktor_config/resources/single_thread_queue.yml +22 -0
  36. data/funktor-testapp/funktor_config/ruby_layer.yml +11 -0
  37. data/funktor-testapp/funktor_init.yml +61 -0
  38. data/funktor-testapp/lambda_event_handlers/default_queue_handler.rb +8 -0
  39. data/funktor-testapp/lambda_event_handlers/incoming_job_handler.rb +8 -0
  40. data/funktor-testapp/lambda_event_handlers/job_activator.rb +8 -0
  41. data/funktor-testapp/lambda_event_handlers/random_job_generator.rb +35 -0
  42. data/funktor-testapp/lambda_event_handlers/single_thread_queue_handler.rb +8 -0
  43. data/funktor-testapp/package-lock.json +248 -0
  44. data/funktor-testapp/package.json +8 -0
  45. data/funktor-testapp/serverless.yml +65 -0
  46. data/funktor.gemspec +1 -0
  47. data/lib/active_job/queue_adapters/funktor_adapter.rb +3 -3
  48. data/lib/funktor.rb +39 -7
  49. data/lib/funktor/activity_tracker.rb +102 -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/job_activator.yml +8 -0
  55. data/lib/funktor/cli/templates/funktor_config/funktor.yml +28 -2
  56. data/lib/funktor/cli/templates/funktor_config/iam_permissions/activity_table.yml +5 -0
  57. data/lib/funktor/cli/templates/funktor_config/iam_permissions/jobs_table.yml +5 -0
  58. data/lib/funktor/cli/templates/funktor_config/iam_permissions/jobs_table_secondary_index.yml +8 -0
  59. data/lib/funktor/cli/templates/funktor_config/resources/activity_table.yml +22 -0
  60. data/lib/funktor/cli/templates/funktor_config/resources/cloudwatch_dashboard.yml +10 -10
  61. data/lib/funktor/cli/templates/funktor_config/resources/jobs_table.yml +44 -0
  62. data/lib/funktor/cli/templates/funktor_init.yml.tt +2 -8
  63. data/lib/funktor/cli/templates/lambda_event_handlers/job_activator.rb +8 -0
  64. data/lib/funktor/cli/templates/lambda_event_handlers/work_queue_handler.rb +1 -1
  65. data/lib/funktor/cli/templates/serverless.yml +2 -2
  66. data/lib/funktor/counter.rb +4 -1
  67. data/lib/funktor/incoming_job_handler.rb +52 -12
  68. data/lib/funktor/job.rb +10 -5
  69. data/lib/funktor/job_activator.rb +98 -0
  70. data/lib/funktor/job_pusher.rb +0 -2
  71. data/lib/funktor/middleware/metrics.rb +8 -3
  72. data/lib/funktor/testing.rb +49 -47
  73. data/lib/funktor/version.rb +1 -1
  74. data/lib/funktor/{active_job_handler.rb → work_queue_handler.rb} +17 -15
  75. data/lib/funktor/worker.rb +0 -7
  76. metadata +69 -3
@@ -0,0 +1,22 @@
1
+ Resources:
2
+ DefaultQueue:
3
+ Type: AWS::SQS::Queue
4
+ Properties:
5
+ QueueName: ${self:custom.funktor.DefaultQueueName}
6
+ VisibilityTimeout: 300
7
+ RedrivePolicy:
8
+ deadLetterTargetArn:
9
+ "Fn::GetAtt": [ DefaultDeadLetterQueue, Arn ]
10
+ maxReceiveCount: 5
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: 300
7
+ RedrivePolicy:
8
+ deadLetterTargetArn:
9
+ "Fn::GetAtt": [ IncomingJobDeadLetterQueue, Arn ]
10
+ maxReceiveCount: 5
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,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
@@ -0,0 +1,22 @@
1
+ Resources:
2
+ SingleThreadQueue:
3
+ Type: AWS::SQS::Queue
4
+ Properties:
5
+ QueueName: ${self:custom.funktor.SingleThreadQueueName}
6
+ VisibilityTimeout: 300
7
+ RedrivePolicy:
8
+ deadLetterTargetArn:
9
+ "Fn::GetAtt": [ SingleThreadDeadLetterQueue, Arn ]
10
+ maxReceiveCount: 5
11
+ SingleThreadDeadLetterQueue:
12
+ Type: AWS::SQS::Queue
13
+ Properties:
14
+ QueueName: ${self:custom.funktor.SingleThreadDeadJobQueueName}
15
+
16
+ Outputs:
17
+ SingleThreadQueueUrl:
18
+ Value:
19
+ Ref: SingleThreadQueue
20
+ SingleThreadDeadLetterQueueUrl:
21
+ Value:
22
+ Ref: SingleThreadDeadLetterQueue
@@ -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,61 @@
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
+ timeout: 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: 10
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 : 1
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: 900
42
+
43
+ # Set log rentention to save money
44
+ logRetentionInDays: 30
45
+
46
+ # Incoming Job Handler
47
+ incomingJobHandler:
48
+ # If your jobs are bursty AND time-sensitive you might want to have some lambdas pre-provisioned
49
+ # to quickly handle jobs at the beginning of a burst. Uncomment the line below if so.
50
+ # provisionedConcurrency: 4
51
+
52
+
53
+ queues:
54
+ - default:
55
+ # Set queue specific config options here
56
+ # memorySize: 512
57
+ # TODO - Is it advisable to use FIFO queuues with Funktor? Maybe this isn't really even supported by CloudFormation?
58
+ # fifo: false
59
+ - singleThread:
60
+ reservedConcurrency: 1
61
+
@@ -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,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,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,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
+ }