elastic_beans 0.10.0.alpha4 → 0.10.0.alpha5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ab319bee66fb6845dab2666354b537f014d57922
4
- data.tar.gz: 1a6f05149363a12674100472bba10579d3e18d00
3
+ metadata.gz: d754b33da7a3f07521bc482202e613379f857d34
4
+ data.tar.gz: 18565aa2ae2b834401eb8c6e129dc7db2fa26bf5
5
5
  SHA512:
6
- metadata.gz: 8ef907a6ddabf1243e976d882b22d1524510816ff58690c8141f55866781b77295294aa3b9117d8800828072650e9733786ae0da9c3cd9830f1d1c16dbdb781e
7
- data.tar.gz: c9c517314e4403cfe788ab28667f35a029d388feefaa6f8c3b8100258fb18e6082e4306ad7321a69def8ea3313e6b44577acda3dec2a8d873612b221b4a6ad40
6
+ metadata.gz: 9d701c345a20ac52fa4be4ac428ebc85f7051a176dac0132d70961c7f280e8b4c1d0c37f300b7b8ed0fe21aea8d42b6610f030e44fba1dcf4733472eed4b5060
7
+ data.tar.gz: 2f83cbf28762e060e3b88f158794d496decb39d2c91af4d587f7ea62b2fc3add9b6ff8dfdd0bc9fe8572c77f006114c8b1d34bcd9345e3188210d3d1f4af76d1
@@ -146,8 +146,16 @@ module ElasticBeans
146
146
  prefix: command_key_prefix,
147
147
  max_keys: 100,
148
148
  ).contents
149
- objects.each_with_object([]) { |object, commands|
149
+ objects.each_with_object([]) do |object, commands|
150
150
  begin
151
+ next unless object.key.end_with?('.json')
152
+ begin
153
+ s3.head_object(bucket: bucket_name, key: "#{object.key}.killed")
154
+ next
155
+ rescue ::Aws::S3::Errors::NotFound
156
+ # not killed, move on
157
+ end
158
+
151
159
  response = s3.get_object(bucket: bucket_name, key: object.key)
152
160
  command = ElasticBeans::Exec::Command.from_json(response.body.read)
153
161
  commands << command unless command.freeze_instance?
@@ -155,7 +163,9 @@ module ElasticBeans
155
163
  rescue ::Aws::S3::Errors::NoSuchKey
156
164
  rescue JSON::ParserError
157
165
  end
158
- }
166
+ end
167
+ rescue ::Aws::S3::Errors::AccessDenied
168
+ raise AccessDeniedS3Error.new(bucket: bucket_name, key: "#{command_key_prefix}*")
159
169
  end
160
170
 
161
171
  # Fetches the +ExecQueueUrl+ Output from the application CloudFormation stack.
@@ -165,7 +175,7 @@ module ElasticBeans
165
175
  end
166
176
 
167
177
  # Schedules the given ElasticBeans::Exec::Command or +id+ for termination.
168
- # Removes the metadata for the command and relies on the SQSConsumer to terminate it.
178
+ # Adds a special piece of metadata to kill the command and relies on the SQSConsumer to terminate it.
169
179
  #
170
180
  # Raises an error if the application does not exist.
171
181
  def kill_command(command_or_id)
@@ -179,8 +189,8 @@ module ElasticBeans
179
189
  command_id = command_or_id
180
190
  end
181
191
 
182
- key = "#{command_key_prefix}#{command_id}.json"
183
- s3.delete_object(
192
+ key = "#{command_key_prefix}#{command_id}.json.killed"
193
+ s3.put_object(
184
194
  bucket: bucket_name,
185
195
  key: key,
186
196
  )
@@ -13,7 +13,7 @@ You can find an enqueued command's ID by running `ps`.
13
13
 
14
14
  Commands are run in an "exec" environment, separate from your webserver or worker environments.
15
15
  When they are enqueued, metadata is created in S3 and removed when the command is complete.
16
- Removing that metadata cancels the command.
16
+ Adding a special piece of metadata cancels the command.
17
17
  The command is sent a SIGTERM, and then a SIGKILL if it has not yet died.
18
18
 
19
19
  Requires AWS credentials to be set in the environment, i.e. AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.
@@ -31,9 +31,10 @@ class SQSConsumer
31
31
  sleep(LOOP_PERIOD)
32
32
  if (message = receive_message)
33
33
  command = command_from_message(message)
34
- unless metadata_exists?(command: command)
34
+ if killing_command?(command)
35
35
  delete_message(message)
36
- log_command("Skipping command ID=#{command['id']} `#{command['command']}' because it was killed")
36
+ log("Skipping command ID=#{command['id']} `#{command['command']}' because it was killed")
37
+ remove_metadata(command: command)
37
38
  next
38
39
  end
39
40
 
@@ -137,6 +138,53 @@ class SQSConsumer
137
138
  @killed
138
139
  end
139
140
 
141
+ def killing_command?(command)
142
+ metadata = command['metadata']
143
+ if metadata && metadata['bucket'] && metadata['key']
144
+ s3.head_object(
145
+ bucket: metadata['bucket'],
146
+ key: "#{metadata['key']}.killed",
147
+ )
148
+ true
149
+ end
150
+ rescue ::Aws::S3::Errors::NotFound
151
+ false
152
+ rescue StandardError => e
153
+ log("[metadata_exists] #{e.class.name}: #{e.message}\n#{e.backtrace.join("\n")}")
154
+ end
155
+
156
+ def kill_command(command, force: false)
157
+ if force
158
+ signal = "KILL"
159
+ else
160
+ signal = "TERM"
161
+ end
162
+
163
+ log_command(
164
+ "Sending signal '#{signal}' to" \
165
+ " command ID=#{command['id']} `#{command['command']}' on host #{`hostname`.chomp} pid #{command_pid}" \
166
+ " because it was killed"
167
+ )
168
+ Process.kill(signal, command_pid)
169
+
170
+ unless force
171
+ # give the command a little bit to die
172
+ sleep(TERM_TIMEOUT)
173
+ end
174
+ end
175
+
176
+ def while_killed(command)
177
+ catch(:killed) do
178
+ loop do
179
+ sleep(KILL_PERIOD)
180
+
181
+ if killing_command?(command)
182
+ yield if block_given?
183
+ end
184
+ end
185
+ end
186
+ end
187
+
140
188
  def receive_message
141
189
  sqs.receive_message(
142
190
  queue_url: queue_url,
@@ -171,62 +219,19 @@ class SQSConsumer
171
219
  log("[update_metadata] #{e.class.name}: #{e.message}\n#{e.backtrace.join("\n")}")
172
220
  end
173
221
 
174
- def metadata_exists?(command:)
222
+ def remove_metadata(command:)
175
223
  metadata = command['metadata']
176
224
  if metadata && metadata['bucket'] && metadata['key']
177
- s3.head_object(
225
+ s3.delete_object(
178
226
  bucket: metadata['bucket'],
179
227
  key: metadata['key'],
180
228
  )
181
- true
182
- end
183
- rescue ::Aws::S3::Errors::NotFound
184
- false
185
- rescue StandardError => e
186
- log("[metadata_exists] #{e.class.name}: #{e.message}\n#{e.backtrace.join("\n")}")
187
- end
188
-
189
- def remove_metadata(command:)
190
- metadata = command['metadata']
191
- if metadata && metadata['bucket'] && metadata['key']
192
229
  s3.delete_object(
193
230
  bucket: metadata['bucket'],
194
- key: metadata['key'],
231
+ key: "#{metadata['key']}.killed",
195
232
  )
196
233
  end
197
234
  rescue StandardError => e
198
235
  log("[remove_metadata] #{e.class.name}: #{e.message}\n#{e.backtrace.join("\n")}")
199
236
  end
200
-
201
- def kill_command(command, force: false)
202
- if force
203
- signal = "KILL"
204
- else
205
- signal = "TERM"
206
- end
207
-
208
- log_command(
209
- "Sending signal '#{signal}' to" \
210
- " command ID=#{command['id']} `#{command['command']}' on host #{`hostname`.chomp} pid #{command_pid}" \
211
- " because it was killed"
212
- )
213
- Process.kill(signal, command_pid)
214
-
215
- unless force
216
- # give the command a little bit to die
217
- sleep(TERM_TIMEOUT)
218
- end
219
- end
220
-
221
- def while_killed(command)
222
- catch(:killed) do
223
- loop do
224
- sleep(KILL_PERIOD)
225
-
226
- if !metadata_exists?(command: command)
227
- yield if block_given?
228
- end
229
- end
230
- end
231
- end
232
237
  end
@@ -1,3 +1,3 @@
1
1
  module ElasticBeans
2
- VERSION = "0.10.0.alpha4"
2
+ VERSION = "0.10.0.alpha5"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elastic_beans
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0.alpha4
4
+ version: 0.10.0.alpha5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Stegman
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-04-25 00:00:00.000000000 Z
11
+ date: 2017-04-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk