redis-helper 1.1.0 → 1.2.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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -2
- data/README.md +7 -0
- data/appveyor.yml +31 -0
- data/bin/console +2 -9
- data/lib/redis/helper.rb +23 -0
- data/lib/redis/helper/lock.rb +80 -0
- data/lib/redis/helper/version.rb +1 -1
- data/redis-helper.gemspec +1 -0
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2ca31e77c5ef65597d7c6a3d85645d01b82bf27
|
4
|
+
data.tar.gz: 24d3c3c8890f4838dacfdbb0136b1e4e4a22fafc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0af9c99539da831f765713ab402f0c5b7a21623a7cec03703c681f4ae28362f0e9e6ac691aa335918e37f4e816312bdd28a4cf772f0dbb221cc43443af86c1cd
|
7
|
+
data.tar.gz: 0a6a4a5de54c157ab64c9a1aca82ab8b5de5e8dbaa1474d94983b24723f0b6ae8951356848b8a157880459f03cda260fca2243a00df342fb4c2cbb57c16f3946
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Redis::Helper
|
2
2
|
|
3
|
+
[](https://rubygems.org/gems/redis-helper)
|
4
|
+
[](https://rubygems.org/gems/redis-helper)
|
5
|
+
[](https://gemnasium.com/Narazaka/redis-helper)
|
6
|
+
[](http://inch-ci.org/github/Narazaka/redis-helper)
|
7
|
+
[](https://travis-ci.org/Narazaka/redis-helper)
|
8
|
+
[](https://ci.appveyor.com/project/Narazaka/redis-helper)
|
9
|
+
|
3
10
|
Redisを扱うクラスで利用するモジュール
|
4
11
|
|
5
12
|
Redis::Objectsがmulti使えないとかアレっていう [@i2bskn](https://github.com/i2bskn) さん等の想いのカケラ。
|
data/appveyor.yml
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
version: "{build}"
|
2
|
+
branches:
|
3
|
+
except:
|
4
|
+
- gh-pages
|
5
|
+
install:
|
6
|
+
# redis
|
7
|
+
- nuget install redis-64 -excludeversion
|
8
|
+
- redis-64\tools\redis-server.exe --service-install
|
9
|
+
- redis-64\tools\redis-server.exe --service-start
|
10
|
+
# ruby
|
11
|
+
- set RUBY_HOME=C:\Ruby%ruby_version%
|
12
|
+
- set PATH=%RUBY_HOME%\bin;%PATH%
|
13
|
+
- |
|
14
|
+
%RUBY_HOME%\DevKit\devkitvars.bat
|
15
|
+
- ruby --version
|
16
|
+
- gem --version
|
17
|
+
- gem update --system
|
18
|
+
- gem install bundler --no-document
|
19
|
+
- bundle --version
|
20
|
+
- bundle config --local path vendor/bundle
|
21
|
+
- bundle install
|
22
|
+
test_script:
|
23
|
+
- bundle exec rake spec
|
24
|
+
build: off
|
25
|
+
deploy: off
|
26
|
+
environment:
|
27
|
+
matrix:
|
28
|
+
- ruby_version: 23
|
29
|
+
- ruby_version: 23-x64
|
30
|
+
cache:
|
31
|
+
- vendor/bundle
|
data/bin/console
CHANGED
@@ -2,13 +2,6 @@
|
|
2
2
|
|
3
3
|
require "bundler/setup"
|
4
4
|
require "redis/helper"
|
5
|
+
require "pry"
|
5
6
|
|
6
|
-
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start
|
7
|
+
Pry.start
|
data/lib/redis/helper.rb
CHANGED
@@ -2,6 +2,7 @@ require "redis"
|
|
2
2
|
require "active_support"
|
3
3
|
require "active_support/core_ext/object/blank"
|
4
4
|
require "active_support/core_ext/numeric/time"
|
5
|
+
require "redis/helper/lock"
|
5
6
|
require "redis/helper/version"
|
6
7
|
|
7
8
|
# Redisを扱うクラスで利用するモジュール
|
@@ -30,11 +31,14 @@ class Redis
|
|
30
31
|
module Helper
|
31
32
|
# 正しくない固有キー(固有キー値が空?)
|
32
33
|
class UnknownUniqueValue < StandardError; end
|
34
|
+
class LockTimeout < StandardError; end
|
33
35
|
|
34
36
|
# デフォルトの固有キー名
|
35
37
|
DEFAULT_UNIQUE_ATTR_NAME = :id
|
36
38
|
# redisキーの区切り文字
|
37
39
|
REDIS_KEY_DELIMITER = ":".freeze
|
40
|
+
# ロックを取得に利用する接尾辞
|
41
|
+
LOCK_POSTFIX = "lock".freeze
|
38
42
|
|
39
43
|
def self.included(klass)
|
40
44
|
klass.extend ClassMethods
|
@@ -57,6 +61,14 @@ class Redis
|
|
57
61
|
end
|
58
62
|
end
|
59
63
|
end
|
64
|
+
|
65
|
+
# 特定のkeyをbaseにしたロックをかけてブロック内の処理を実行
|
66
|
+
# @param [String] base_key ロックを取得するリソースのkey
|
67
|
+
# @yield ロック中に実行する処理のブロック
|
68
|
+
def lock(base_key, &block)
|
69
|
+
lock_key = [base_key, LOCK_POSTFIX].compact.join(REDIS_KEY_DELIMITER)
|
70
|
+
::Redis::Helper::Lock.new(redis, lock_key).lock(&block)
|
71
|
+
end
|
60
72
|
end
|
61
73
|
|
62
74
|
# instance固有のkeyとattr_nameからkeyを生成する
|
@@ -100,5 +112,16 @@ class Redis
|
|
100
112
|
def redis
|
101
113
|
self.class.redis
|
102
114
|
end
|
115
|
+
|
116
|
+
# 特定のkeyをbaseにしたロックをかけてブロック内の処理を実行
|
117
|
+
# @example
|
118
|
+
# lock(attr_key(:foo)) {
|
119
|
+
# # some processing
|
120
|
+
# }
|
121
|
+
# @param [String] base_key ロックを取得するリソースのkey
|
122
|
+
# @yield ロック中に実行する処理のブロック
|
123
|
+
def lock(base_key, &block)
|
124
|
+
self.class.lock(base_key, &block)
|
125
|
+
end
|
103
126
|
end
|
104
127
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
class Redis
|
2
|
+
module Helper
|
3
|
+
class Lock
|
4
|
+
# ロック取得のタイムアウト(sec)
|
5
|
+
DEFAULT_TIMEOUT = 5
|
6
|
+
|
7
|
+
def initialize(redis, lock_key, options = {})
|
8
|
+
@redis = redis
|
9
|
+
@lock_key = lock_key
|
10
|
+
@options = options
|
11
|
+
@locked_by_self = false
|
12
|
+
end
|
13
|
+
|
14
|
+
# ロックをかけてブロック内の処理を実行
|
15
|
+
# @yield ロック中に実行する処理のブロック
|
16
|
+
def lock
|
17
|
+
raise ArgumentError unless block_given?
|
18
|
+
if Thread.current[@lock_key]
|
19
|
+
yield
|
20
|
+
else
|
21
|
+
begin
|
22
|
+
Thread.current[@lock_key] = true
|
23
|
+
try_lock!(Time.now.to_f)
|
24
|
+
yield
|
25
|
+
ensure
|
26
|
+
unlock
|
27
|
+
Thread.current[@lock_key] = nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# ロックを開放
|
33
|
+
# (自身でかけたロックの場合のみ開放する)
|
34
|
+
def unlock
|
35
|
+
if @locked_by_self
|
36
|
+
@redis.del(@lock_key)
|
37
|
+
@locked_by_self = false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
# ロックを取得
|
43
|
+
# @param [Float] start ロック取得開始時間のUNIXタイムスタンプ
|
44
|
+
# @yield ロック中に実行する処理のブロック
|
45
|
+
# @raise [Redis::Helper::LockTimeout] ロックの取得に失敗した
|
46
|
+
def try_lock!(start)
|
47
|
+
loop do
|
48
|
+
if @redis.setnx(@lock_key, expiration)
|
49
|
+
@locked_by_self = true
|
50
|
+
break
|
51
|
+
end
|
52
|
+
|
53
|
+
current = @redis.get(@lock_key).to_f
|
54
|
+
if current < Time.now.to_f
|
55
|
+
old = @redis.getset(@lock_key, expiration).to_f
|
56
|
+
if old < Time.now.to_f
|
57
|
+
@locked_by_self = true
|
58
|
+
break
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
Kernel.sleep(0.1)
|
63
|
+
raise ::Redis::Helper::LockTimeout if (Time.now.to_f - start) > timeout
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# ロックの有効期限
|
68
|
+
# @return [Float] 有効期限(UNIXタイムスタンプ)
|
69
|
+
def expiration
|
70
|
+
(Time.now + timeout).to_f
|
71
|
+
end
|
72
|
+
|
73
|
+
# ロック取得と取得したロックがタイムアウトするまでの時間
|
74
|
+
# @return [Float] タイムアウト時間(sec)
|
75
|
+
def timeout
|
76
|
+
@timeout ||= (@options[:timeout] || DEFAULT_TIMEOUT).to_f
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/redis/helper/version.rb
CHANGED
data/redis-helper.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-helper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Narazaka
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-02-
|
11
|
+
date: 2017-02-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -122,6 +122,20 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: pry
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
125
139
|
description:
|
126
140
|
email:
|
127
141
|
- info@narazaka.net
|
@@ -137,9 +151,11 @@ files:
|
|
137
151
|
- LICENSE.txt
|
138
152
|
- README.md
|
139
153
|
- Rakefile
|
154
|
+
- appveyor.yml
|
140
155
|
- bin/console
|
141
156
|
- bin/setup
|
142
157
|
- lib/redis/helper.rb
|
158
|
+
- lib/redis/helper/lock.rb
|
143
159
|
- lib/redis/helper/version.rb
|
144
160
|
- redis-helper.gemspec
|
145
161
|
homepage: https://github.com/Narazaka/redis-helper
|