activejob-locking 0.4.0 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,21 +1,21 @@
1
- require 'rubygems'
2
- require 'rake'
3
- require 'rake/clean'
4
- require 'rake/testtask'
5
- require 'rubygems/package_task'
6
-
7
- # Set global variable so other tasks can access them
8
- ::PROJECT_ROOT = File.expand_path(".")
9
- ::GEM_NAME = 'activejob-locking'
10
-
11
- # Read the spec file
12
- spec = Gem::Specification.load("#{GEM_NAME}.gemspec")
13
-
14
- # Setup Rake tasks for managing the gem
15
- Gem::PackageTask.new(spec).define
16
-
17
- desc 'Run unit tests.'
18
- Rake::TestTask.new(:test) do |task|
19
- task.test_files = FileList['test/test_*.rb']
20
- task.verbose = true
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rubygems/package_task'
6
+
7
+ # Set global variable so other tasks can access them
8
+ ::PROJECT_ROOT = File.expand_path(".")
9
+ ::GEM_NAME = 'activejob-locking'
10
+
11
+ # Read the spec file
12
+ spec = Gem::Specification.load("#{GEM_NAME}.gemspec")
13
+
14
+ # Setup Rake tasks for managing the gem
15
+ Gem::PackageTask.new(spec).define
16
+
17
+ desc 'Run unit tests.'
18
+ Rake::TestTask.new(:test) do |task|
19
+ task.test_files = FileList['test/test_*.rb']
20
+ task.verbose = true
21
21
  end
@@ -1,23 +1,24 @@
1
- require 'activejob/locking/adapters/base'
2
- require 'activejob/locking/adapters/memory'
3
-
4
- require 'activejob/locking/base'
5
- require 'activejob/locking/unique'
6
- require 'activejob/locking/serialized'
7
-
8
- require 'activejob/locking/options'
9
-
10
- module ActiveJob
11
- module Locking
12
- @options = ActiveJob::Locking::Options.new(adapter: ActiveJob::Locking::Adapters::Memory,
13
- hosts: ['localhost'],
14
- lock_time: 100,
15
- lock_acquire_time: 1,
16
- adapter_options: {})
17
-
18
- def self.options
19
- @options
20
- end
21
- end
22
- end
23
-
1
+ require 'activejob/locking/adapters/base'
2
+ require 'activejob/locking/adapters/memory'
3
+
4
+ require 'activejob/locking/base'
5
+ require 'activejob/locking/unique'
6
+ require 'activejob/locking/serialized'
7
+
8
+ require 'activejob/locking/options'
9
+
10
+ module ActiveJob
11
+ module Locking
12
+ @options = ActiveJob::Locking::Options.new(adapter: ActiveJob::Locking::Adapters::Memory,
13
+ hosts: ['localhost'],
14
+ enqueue_time: 100, # seconds
15
+ lock_time: 100, # seconds
16
+ lock_acquire_time: 1, # seconds
17
+ adapter_options: {})
18
+
19
+ def self.options
20
+ @options
21
+ end
22
+ end
23
+ end
24
+
@@ -1,32 +1,32 @@
1
- module ActiveJob
2
- module Locking
3
- module Adapters
4
- class Base
5
- attr_reader :key, :options, :lock_manager
6
- attr_accessor :lock_token
7
-
8
- def initialize(key, options)
9
- @key = key
10
- @options = options
11
- @lock_manager = self.create_lock_manager
12
- end
13
-
14
- def create_lock_manager
15
- raise('Subclass must implement')
16
- end
17
-
18
- def lock
19
- raise('Subclass must implement')
20
- end
21
-
22
- def unlock
23
- raise('Subclass must implement')
24
- end
25
-
26
- def refresh_lock!(refresh)
27
- raise('Subclass must implement')
28
- end
29
- end
30
- end
31
- end
1
+ module ActiveJob
2
+ module Locking
3
+ module Adapters
4
+ class Base
5
+ attr_reader :key, :options, :lock_manager
6
+ attr_accessor :lock_token
7
+
8
+ def initialize(key, options)
9
+ @key = key
10
+ @options = options
11
+ @lock_manager = self.create_lock_manager
12
+ end
13
+
14
+ def create_lock_manager
15
+ raise('Subclass must implement')
16
+ end
17
+
18
+ def lock
19
+ raise('Subclass must implement')
20
+ end
21
+
22
+ def unlock
23
+ raise('Subclass must implement')
24
+ end
25
+
26
+ def refresh_lock!(refresh)
27
+ raise('Subclass must implement')
28
+ end
29
+ end
30
+ end
31
+ end
32
32
  end
@@ -1,58 +1,58 @@
1
- module ActiveJob
2
- module Locking
3
- module Adapters
4
- class Memory < Base
5
- @hash = Hash.new
6
- @mutex = Mutex.new
7
-
8
- def self.lock(key)
9
- @mutex.synchronize do
10
- if @hash[key]
11
- false
12
- else
13
- @hash[key] = Time.now
14
- end
15
- end
16
- end
17
-
18
- def self.unlock(key)
19
- @mutex.synchronize do
20
- @hash.delete(key)
21
- end
22
- end
23
-
24
- def self.locked?(key)
25
- @mutex.synchronize do
26
- @hash.include?(key)
27
- end
28
- end
29
-
30
- def self.reset
31
- @mutex.synchronize do
32
- @hash = Hash.new
33
- end
34
- end
35
-
36
- def create_lock_manager
37
- end
38
-
39
- def lock
40
- finish = Time.now + self.options.lock_acquire_time
41
- sleep_time = [5, self.options.lock_acquire_time / 5].min
42
-
43
- begin
44
- lock = self.class.lock(key)
45
- return lock if lock
46
- sleep(sleep_time)
47
- end while Time.now < finish
48
-
49
- false
50
- end
51
-
52
- def unlock
53
- self.class.unlock(self.key)
54
- end
55
- end
56
- end
57
- end
1
+ module ActiveJob
2
+ module Locking
3
+ module Adapters
4
+ class Memory < Base
5
+ @hash = Hash.new
6
+ @mutex = Mutex.new
7
+
8
+ def self.lock(key)
9
+ @mutex.synchronize do
10
+ if @hash[key]
11
+ false
12
+ else
13
+ @hash[key] = Time.now
14
+ end
15
+ end
16
+ end
17
+
18
+ def self.unlock(key)
19
+ @mutex.synchronize do
20
+ @hash.delete(key)
21
+ end
22
+ end
23
+
24
+ def self.locked?(key)
25
+ @mutex.synchronize do
26
+ @hash.include?(key)
27
+ end
28
+ end
29
+
30
+ def self.reset
31
+ @mutex.synchronize do
32
+ @hash = Hash.new
33
+ end
34
+ end
35
+
36
+ def create_lock_manager
37
+ end
38
+
39
+ def lock
40
+ finish = Time.now + self.options.lock_acquire_time
41
+ sleep_time = [5, self.options.lock_acquire_time / 5].min
42
+
43
+ begin
44
+ lock = self.class.lock(key)
45
+ return lock if lock
46
+ sleep(sleep_time)
47
+ end while Time.now < finish
48
+
49
+ false
50
+ end
51
+
52
+ def unlock
53
+ self.class.unlock(self.key)
54
+ end
55
+ end
56
+ end
57
+ end
58
58
  end
@@ -1,26 +1,26 @@
1
- require 'redis-semaphore'
2
-
3
- module ActiveJob
4
- module Locking
5
- module Adapters
6
- class RedisSemaphore < Base
7
- def create_lock_manager
8
- mapped_options = {host: self.options.hosts.first,
9
- resources: 1,
10
- stale_client_timeout: self.options.lock_time}.merge(self.options.adapter_options)
11
-
12
- Redis::Semaphore.new(self.key, mapped_options)
13
- end
14
-
15
- def lock
16
- self.lock_token = self.lock_manager.lock(self.options.lock_acquire_time)
17
- end
18
-
19
- def unlock
20
- self.lock_manager.signal(self.lock_token)
21
- self.lock_token = nil
22
- end
23
- end
24
- end
25
- end
26
- end
1
+ require 'redis-semaphore'
2
+
3
+ module ActiveJob
4
+ module Locking
5
+ module Adapters
6
+ class RedisSemaphore < Base
7
+ def create_lock_manager
8
+ mapped_options = {host: self.options.hosts.first,
9
+ resources: 1,
10
+ stale_client_timeout: self.options.lock_time}.merge(self.options.adapter_options)
11
+
12
+ Redis::Semaphore.new(self.key, mapped_options)
13
+ end
14
+
15
+ def lock
16
+ self.lock_token = self.lock_manager.lock(self.options.lock_acquire_time)
17
+ end
18
+
19
+ def unlock
20
+ self.lock_manager.signal(self.lock_token)
21
+ self.lock_token = nil
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,26 +1,26 @@
1
- require 'redlock'
2
-
3
- module ActiveJob
4
- module Locking
5
- module Adapters
6
- class Redlock < Base
7
- def create_lock_manager
8
- mapped_options = self.options.adapter_options
9
- mapped_options[:retry_count] = 2 # Try to get the lock and then try again when timeout is expiring--
10
- mapped_options[:retry_delay] = self.options.lock_acquire_time * 1000 # convert from seconds to milliseconds
11
-
12
- ::Redlock::Client.new(self.options.hosts, mapped_options)
13
- end
14
-
15
- def lock
16
- self.lock_token = self.lock_manager.lock(self.key, self.options.lock_time * 1000)
17
- end
18
-
19
- def unlock
20
- self.lock_manager.unlock(self.lock_token)
21
- self.lock_token = nil
22
- end
23
- end
24
- end
25
- end
26
- end
1
+ require 'redlock'
2
+
3
+ module ActiveJob
4
+ module Locking
5
+ module Adapters
6
+ class Redlock < Base
7
+ def create_lock_manager
8
+ mapped_options = self.options.adapter_options
9
+ mapped_options[:retry_count] = 2 # Try to get the lock and then try again when timeout is expiring--
10
+ mapped_options[:retry_delay] = self.options.lock_acquire_time * 1000 # convert from seconds to milliseconds
11
+
12
+ ::Redlock::Client.new(self.options.hosts, mapped_options)
13
+ end
14
+
15
+ def lock
16
+ self.lock_token = self.lock_manager.lock(self.key, self.options.lock_time * 1000)
17
+ end
18
+
19
+ def unlock
20
+ self.lock_manager.unlock(self.lock_token.symbolize_keys)
21
+ self.lock_token = nil
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,25 +1,25 @@
1
- require 'suo'
2
-
3
- module ActiveJob
4
- module Locking
5
- module Adapters
6
- class SuoRedis < Base
7
- def create_lock_manager
8
- mapped_options = {connection: {host: self.options.hosts.first},
9
- stale_lock_expiration: self.options.lock_time,
10
- acquisition_timeout: self.options.lock_acquire_time}
11
-
12
- Suo::Client::Redis.new(self.key, mapped_options)
13
- end
14
-
15
- def lock
16
- self.lock_token = self.lock_manager.lock
17
- end
18
-
19
- def unlock
20
- self.lock_manager.unlock(self.lock_token)
21
- end
22
- end
23
- end
24
- end
25
- end
1
+ require 'suo'
2
+
3
+ module ActiveJob
4
+ module Locking
5
+ module Adapters
6
+ class SuoRedis < Base
7
+ def create_lock_manager
8
+ mapped_options = {connection: {host: self.options.hosts.first},
9
+ stale_lock_expiration: self.options.lock_time,
10
+ acquisition_timeout: self.options.lock_acquire_time}
11
+
12
+ Suo::Client::Redis.new(self.key, mapped_options)
13
+ end
14
+
15
+ def lock
16
+ self.lock_token = self.lock_manager.lock
17
+ end
18
+
19
+ def unlock
20
+ self.lock_manager.unlock(self.lock_token)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,51 +1,55 @@
1
- module ActiveJob
2
- module Locking
3
- module Base
4
- extend ::ActiveSupport::Concern
5
-
6
- module ClassMethods
7
- def lock_options
8
- @lock_options ||= ActiveJob::Locking::Options.new
9
- end
10
- delegate :adapter, :hosts, :lock_time, :lock_acquire_time, :adapter_options, to: :lock_options
11
- delegate :adapter=, :hosts=, :lock_time=, :lock_acquire_time=, :adapter_options=, to: :lock_options
12
- end
13
-
14
- included do
15
- # We need to serialize the lock token that some gems create because it could be released in a different process
16
- def serialize
17
- result = super
18
- result['lock_token'] = self.adapter.lock_token
19
- result
20
- end
21
-
22
- def deserialize(job_data)
23
- super
24
- self.adapter.lock_token = job_data['lock_token']
25
- end
26
-
27
- def lock_key(*args)
28
- [self.class.name, serialize_arguments(self.arguments)].join('/')
29
- end
30
-
31
- def adapter
32
- @adapter ||= begin
33
- # Make sure arguments are deserialized so calling lock key is safe
34
- deserialize_arguments_if_needed
35
-
36
- # Merge local and global options
37
- merged_options = ActiveJob::Locking.options.dup.merge(self.class.lock_options)
38
-
39
- # Get the key
40
- base_key = self.lock_key(*self.arguments)
41
- key = "activejoblocking:#{base_key}"
42
-
43
- # Remember the lock might be acquired in one process and released in another
44
- merged_options.adapter.new(key, merged_options)
45
- end
46
- @adapter
47
- end
48
- end
49
- end
50
- end
1
+ module ActiveJob
2
+ module Locking
3
+ module Base
4
+ extend ::ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ def lock_options
8
+ @lock_options ||= ActiveJob::Locking::Options.new
9
+ end
10
+ delegate :adapter, :enqueue_time, :hosts, :lock_time, :lock_acquire_time, :adapter_options, to: :lock_options
11
+ delegate :adapter=, :enqueue_time=, :hosts=, :lock_time=, :lock_acquire_time=, :adapter_options=, to: :lock_options
12
+ end
13
+
14
+ included do
15
+ # We need to serialize the lock token that some gems create because it could be released in a different process
16
+ def serialize
17
+ result = super
18
+ result['lock_token'] = self.adapter.lock_token
19
+ result
20
+ end
21
+
22
+ def deserialize(job_data)
23
+ super
24
+ self.adapter.lock_token = job_data['lock_token']
25
+ end
26
+
27
+ def lock_key(*args)
28
+ [self.class.name, serialize_arguments(self.arguments)].join('/')
29
+ end
30
+
31
+ def adapter
32
+ @adapter ||= begin
33
+ # Make sure arguments are deserialized so calling lock key is safe
34
+ begin
35
+ deserialize_arguments_if_needed
36
+ rescue => exception
37
+ rescue_with_handler(exception) || raise
38
+ end
39
+
40
+ # Merge local and global options
41
+ merged_options = ActiveJob::Locking.options.dup.merge(self.class.lock_options)
42
+
43
+ # Get the key
44
+ base_key = self.lock_key(*self.arguments)
45
+ key = "activejoblocking:#{base_key}"
46
+
47
+ # Remember the lock might be acquired in one process and released in another
48
+ merged_options.adapter.new(key, merged_options)
49
+ end
50
+ @adapter
51
+ end
52
+ end
53
+ end
54
+ end
51
55
  end