non_blocking_lock 0.1.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.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.sublime-*
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'http://rubygems.org'
2
+ gemspec
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,10 @@
1
+ require "non_blocking_lock/version"
2
+ require "non_blocking_lock/base"
3
+
4
+ if defined? ActiveRecord
5
+ require "non_blocking_lock/mysql2_adapter"
6
+
7
+ ActiveRecord::Base.class_eval do
8
+ include NonBlockingLock
9
+ end
10
+ end
@@ -0,0 +1,52 @@
1
+ module NonBlockingLock
2
+ class LockFailed < ActiveRecord::ActiveRecordError #:nodoc:
3
+ end
4
+
5
+ module ClassMethods
6
+ # name - lock name
7
+ # wait_time - default 1.second
8
+ # &block to execute if lock obtained
9
+ # return false if failed to get lock
10
+ def non_blocking_lock( *args, &block )
11
+ if connection.respond_to?( :non_blocking_lock )
12
+ connection.non_blocking_lock( *args, &block )
13
+ else
14
+ raise ::LockFailed.new( "Not implemented." )
15
+ end
16
+ end
17
+
18
+ # name - lock name
19
+ # wait_time - default 1.second
20
+ # &block to execute if lock obtained
21
+ # raises exception if failed to get lock
22
+ def non_blocking_lock!( *args, &block )
23
+ unless non_blocking_lock( *args, &block )
24
+ raise ::LockFailed.new( "Failed to obtain a lock." )
25
+ end
26
+ end
27
+ end
28
+
29
+ module InstanceMethods
30
+ # name - lock name
31
+ # wait_time - default 1.second
32
+ # &block to execute if lock obtained
33
+ # return false if failed to get lock
34
+ def non_blocking_lock( *args, &block )
35
+ string_id = "_#{self.class}_#{self.id}"
36
+ if args.first.is_a? String
37
+ args[0] += string_id
38
+ else
39
+ args.unshift(string_id)
40
+ end
41
+ self.class.non_blocking_lock( *args, &block )
42
+ end
43
+ end
44
+
45
+ def self.included( base )
46
+ base.extend( ClassMethods )
47
+ base.class_eval do
48
+ include ::NonBlockingLock::ClassMethods
49
+ include ::NonBlockingLock::InstanceMethods
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,27 @@
1
+ require 'active_record/connection_adapters/abstract_mysql_adapter'
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ class Mysql2Adapter < AbstractMysqlAdapter
6
+ # name - lock name
7
+ # wait_time - default 1.second
8
+ # &block to execute if lock obtained
9
+ # return false if failed to get lock
10
+ def non_blocking_lock( name, wait_time=1.0 )
11
+ raise ArgumentError.new("name can't be empty") if name.blank?
12
+ raise ArgumentError.new("wait_time can't be less then 0") if wait_time.to_f <= 0
13
+
14
+ name = quote_string( name )
15
+
16
+ begin
17
+ mysql_result = select_value( "SELECT GET_LOCK('#{name}', #{wait_time.to_f})" )
18
+ mysql_get_lock_obtained = mysql_result.to_s == "1"
19
+ yield if mysql_get_lock_obtained
20
+ return mysql_get_lock_obtained
21
+ ensure
22
+ select_value("SELECT RELEASE_LOCK('#{name}')") if mysql_get_lock_obtained
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module NonBlockingLock
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/non_blocking_lock/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Ryan Funduk"]
6
+ gem.email = ["ryan.funduk@gmail.com"]
7
+ gem.description = %q{A non_blocking_lock implementation for ActiveRecord adapters (well, just Mysql2 right now).}
8
+ gem.summary = %q{}
9
+ gem.homepage = "http://github.com/rfunduk/non_blocking_lock"
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = "non_blocking_lock"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = NonBlockingLock::VERSION
17
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: non_blocking_lock
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ryan Funduk
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-06 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A non_blocking_lock implementation for ActiveRecord adapters (well, just
15
+ Mysql2 right now).
16
+ email:
17
+ - ryan.funduk@gmail.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - Gemfile
24
+ - Rakefile
25
+ - lib/non_blocking_lock.rb
26
+ - lib/non_blocking_lock/base.rb
27
+ - lib/non_blocking_lock/mysql2_adapter.rb
28
+ - lib/non_blocking_lock/version.rb
29
+ - non_blocking_lock.gemspec
30
+ homepage: http://github.com/rfunduk/non_blocking_lock
31
+ licenses: []
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubyforge_project:
50
+ rubygems_version: 1.8.11
51
+ signing_key:
52
+ specification_version: 3
53
+ summary: ''
54
+ test_files: []
55
+ has_rdoc: