distributed-lock-google-cloud-storage 1.0.0 → 1.1.0
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
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ba7bdb482b1bf1a10c8c3933ff8680d980099de2c66fd8cf0f1aac0db7c258d
|
4
|
+
data.tar.gz: 4597cc7ffd7ae791808eb677c875b62f19d48bcd8ff83c63a38a2f4683ec2829
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 323019ce82a1dda8252a9332dca0e024f5801ec5367320ad7e2133712cc55e35060f9fc2fb1bed1545dbfe333477b1498a2e410f4a77551d993ae7838e6f67eb
|
7
|
+
data.tar.gz: 2b7d1b8ff59ddfdd14d100fdd67420e57b54c2c87688ccfbbceff53c6b22561630e1f7c2a5803bb9329650f818134b514d5238264251af944024950a6260047c
|
@@ -11,6 +11,7 @@ require_relative 'utils'
|
|
11
11
|
module DistributedLock
|
12
12
|
module GoogleCloudStorage
|
13
13
|
class Lock
|
14
|
+
# @!visibility private
|
14
15
|
DEFAULT_INSTANCE_IDENTITY_PREFIX_WITHOUT_PID = SecureRandom.hex(12).freeze
|
15
16
|
|
16
17
|
include Utils
|
@@ -65,13 +66,13 @@ module DistributedLock
|
|
65
66
|
# when acquiring the lock fails. Must be at least 0.
|
66
67
|
# @param object_acl [String, nil] A predefined set of access control to apply to the Cloud Storage
|
67
68
|
# object. See the `acl` parameter in
|
68
|
-
# [https://googleapis.dev/ruby/google-cloud-storage/latest/Google/Cloud/Storage/Bucket.html#create_file-instance_method
|
69
|
+
# [Google::Cloud::Storage::Bucket#create_file](https://googleapis.dev/ruby/google-cloud-storage/latest/Google/Cloud/Storage/Bucket.html#create_file-instance_method)
|
69
70
|
# for acceptable values.
|
70
71
|
# @param cloud_storage_options [Hash, nil] Additional options to pass to
|
71
|
-
#
|
72
|
+
# [Google::Cloud::Storage.new](https://googleapis.dev/ruby/google-cloud-storage/latest/Google/Cloud/Storage.html#new-class_method).
|
72
73
|
# See its documentation to learn which options are available.
|
73
74
|
# @param cloud_storage_bucket_options [Hash, nil] Additional options to pass to
|
74
|
-
#
|
75
|
+
# [Google::Cloud::Storage::Project#bucket](https://googleapis.dev/ruby/google-cloud-storage/latest/Google/Cloud/Storage/Project.html#bucket-instance_method).
|
75
76
|
# See its documentation to learn which options are available.
|
76
77
|
#
|
77
78
|
# @note The logger must either be thread-safe, or all writes to this logger by anything besides
|
@@ -119,6 +120,7 @@ module DistributedLock
|
|
119
120
|
@owner = nil
|
120
121
|
@metageneration = nil
|
121
122
|
@refresher_thread = nil
|
123
|
+
@refresher_error = nil
|
122
124
|
|
123
125
|
# The refresher generation is incremented every time we shutdown
|
124
126
|
# the refresher thread. It allows the refresher thread to know
|
@@ -256,7 +258,7 @@ module DistributedLock
|
|
256
258
|
# obtained by some other instance identity, waits until it becomes available,
|
257
259
|
# or until timeout.
|
258
260
|
#
|
259
|
-
# Accepts the same parameters as #lock.
|
261
|
+
# Accepts the same parameters as {#lock}.
|
260
262
|
#
|
261
263
|
# @return The block's return value.
|
262
264
|
# @raise [AlreadyLockedError] This Lock instance — according to its internal state — believes
|
@@ -273,10 +275,10 @@ module DistributedLock
|
|
273
275
|
|
274
276
|
# Pretends like we've never obtained this lock, abandoning our internal state about the lock.
|
275
277
|
#
|
276
|
-
# Shuts down background lock refreshing, and ensures that
|
277
|
-
#
|
278
|
+
# Shuts down background lock refreshing, and ensures that {#locked_according_to_internal_state?}
|
279
|
+
# returns false.
|
278
280
|
#
|
279
|
-
# Does not modify any server data, so #locked_according_to_server? may still return true.
|
281
|
+
# Does not modify any server data, so {#locked_according_to_server?} may still return true.
|
280
282
|
#
|
281
283
|
# @return [void]
|
282
284
|
def abandon
|
@@ -302,15 +304,19 @@ module DistributedLock
|
|
302
304
|
# Returns whether the lock is healthy. A lock is considered healthy until
|
303
305
|
# we fail to refresh the lock too many times consecutively.
|
304
306
|
#
|
305
|
-
# Failure to refresh could happen for many reasons
|
306
|
-
#
|
307
|
+
# Failure to refresh could happen for many reasons. Some failures are temporary, such
|
308
|
+
# as network problems. Others are permanent, such as the lock object being forcefully
|
309
|
+
# deleted by someone else.
|
307
310
|
#
|
308
|
-
#
|
311
|
+
# Upon encountering a permanent failure, the lock is immediately declared unhealthy.
|
312
|
+
# Upon encountering a temporary failure, the lock is declared unhealthy after encountering
|
313
|
+
# a temporary error `max_refresh_fails` times consecutively.
|
309
314
|
#
|
310
315
|
# It only makes sense to call this method after having obtained this lock.
|
311
316
|
#
|
312
317
|
# @return [Boolean]
|
313
318
|
# @raise [NotLockedError] This lock was not obtained.
|
319
|
+
# @see #last_refresh_error
|
314
320
|
def healthy?
|
315
321
|
@state_mutex.synchronize do
|
316
322
|
raise NotLockedError, 'Not locked' if !unsynced_locked_according_to_internal_state?
|
@@ -318,7 +324,9 @@ module DistributedLock
|
|
318
324
|
end
|
319
325
|
end
|
320
326
|
|
321
|
-
# Checks whether the lock is healthy. See #healthy? for the definition of "healthy".
|
327
|
+
# Checks whether the lock is healthy. See {#healthy?} for the definition of "healthy".
|
328
|
+
# Use {#last_refresh_error} to query the last error that caused the lock to be declared
|
329
|
+
# unhealthy.
|
322
330
|
#
|
323
331
|
# It only makes sense to call this method after having obtained this lock.
|
324
332
|
#
|
@@ -329,6 +337,19 @@ module DistributedLock
|
|
329
337
|
raise LockUnhealthyError, 'Lock is not healthy' if !healthy?
|
330
338
|
end
|
331
339
|
|
340
|
+
# Returns the last error that caused the lock to be declared unhealthy.
|
341
|
+
#
|
342
|
+
# Don't use this method to check whether the lock is _currently_ healthy.
|
343
|
+
# If this lock has ever been unhealthy, then this method returns a non-nil value
|
344
|
+
# even if the lock is currently healthy.
|
345
|
+
#
|
346
|
+
# @return [StandardError, nil]
|
347
|
+
def last_refresh_error
|
348
|
+
@state_mutex.synchronize do
|
349
|
+
@refresher_error
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
332
353
|
|
333
354
|
private
|
334
355
|
|
@@ -429,9 +450,7 @@ module DistributedLock
|
|
429
450
|
def delete_lock_object(expected_metageneration)
|
430
451
|
file = @bucket.file(@path, skip_lookup: true)
|
431
452
|
file.delete(if_metageneration_match: expected_metageneration)
|
432
|
-
rescue Google::Cloud::NotFoundError
|
433
|
-
false
|
434
|
-
rescue Google::Cloud::FailedPreconditionError
|
453
|
+
rescue Google::Cloud::NotFoundError, Google::Cloud::FailedPreconditionError
|
435
454
|
false
|
436
455
|
end
|
437
456
|
|
@@ -563,7 +582,17 @@ module DistributedLock
|
|
563
582
|
end
|
564
583
|
log_debug { "Done refreshing lock. metageneration=#{file.metageneration}" }
|
565
584
|
true
|
585
|
+
|
566
586
|
rescue => e
|
587
|
+
@state_mutex.synchronize do
|
588
|
+
if @refresher_generation != refresher_generation
|
589
|
+
log_debug { 'Abort refreshing lock' }
|
590
|
+
return true
|
591
|
+
end
|
592
|
+
|
593
|
+
@refresher_error = e
|
594
|
+
end
|
595
|
+
|
567
596
|
log_error { "Error refreshing lock: #{e}" }
|
568
597
|
[false, permanent_failure]
|
569
598
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: distributed-lock-google-cloud-storage
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hongli Lai
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-09-
|
11
|
+
date: 2021-09-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-cloud-storage
|