cache_guard 1.0.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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c9c48a204891eb04bb84c52347b5025352f0f41e
4
+ data.tar.gz: 0f90e08c1138244ca18129db5850288a1aab33be
5
+ SHA512:
6
+ metadata.gz: bc8d26739c8394c4892b964473002ad35606ea025324909c2d43f4a3b8125ea08e099afb7f2df3b4ce559ac57b54ce4b14e53b22da9deec798cd25682b8d8b79
7
+ data.tar.gz: fbc853045045d2b9b4ffb870e908155c0cc6655904e86e651b1c2fec3eaeaa9416f31199d44842b09e74f95437e9c3a62b192c5b3deeae3473d326358bb7295c
@@ -0,0 +1,40 @@
1
+ class CacheGuard
2
+ class AcquireError < RuntimeError
3
+ end
4
+
5
+ def initialize(name, options = {})
6
+ @name = name
7
+ @default_value = options[:default_value] || 1
8
+ @expires_in = options[:expires_in] || 120
9
+ @cache_store = options[:cache_store] || Rails.store
10
+ end
11
+
12
+ def guard
13
+ raise AcquireError, "Unable to acquire guard for: #{@name}" unless acquire
14
+
15
+ begin
16
+ yield
17
+ ensure
18
+ release
19
+ end
20
+ end
21
+
22
+ def self.guard(name, options = {}, &block)
23
+ new(name, options).guard(&block)
24
+ end
25
+
26
+ private
27
+
28
+ def acquire
29
+ # The FileStore increment operation returns nil if the cache key doesn't exist. Since the FileStore strategy
30
+ # should be only used in development environment we can allow all guards to pass.
31
+ # http://api.rubyonrails.org/classes/ActiveSupport/Cache/FileStore.html#method-i-increment
32
+ # http://www.rubydoc.info/github/mperham/dalli/ActiveSupport/Cache/DalliStore#increment-instance_method
33
+ value = @cache_store.increment(@name, @default_value, :expires_in => @expires_in)
34
+ value.nil? || value == @default_value ? true : false
35
+ end
36
+
37
+ def release
38
+ @cache_store.delete(@name)
39
+ end
40
+ end
@@ -0,0 +1,57 @@
1
+ require "spec_helper"
2
+ require "cache_guard"
3
+
4
+ describe CacheGuard do
5
+ describe "#guard" do
6
+ let(:cache_store){ double("Cache", :delete => true) }
7
+ subject{ described_class.new("guard", :cache_store => cache_store) }
8
+
9
+ context "when able to acquire guard" do
10
+ before do
11
+ allow(cache_store).to receive(:increment).and_return(1)
12
+ end
13
+
14
+ it "executes the given block" do
15
+ expect{ |probe| subject.guard(&probe) }.to yield_control
16
+ end
17
+
18
+ it "releases on success" do
19
+ subject.guard{ true }
20
+ expect(cache_store).to have_received(:delete)
21
+ end
22
+
23
+ it "releases on exception" do
24
+ subject.guard{ raise } rescue nil
25
+ expect(cache_store).to have_received(:delete)
26
+ end
27
+ end
28
+
29
+ context "when unable to acquire guard" do
30
+ before do
31
+ allow(cache_store).to receive(:increment).and_return(2)
32
+ end
33
+
34
+ it "raises an CacheGuard::AcquireError" do
35
+ expect{ subject.guard{ true } }.to raise_error(CacheGuard::AcquireError)
36
+ end
37
+
38
+ it "doesn't release" do
39
+ subject.guard{ true } rescue nil
40
+ expect(cache_store).to_not have_received(:delete)
41
+ end
42
+ end
43
+ end
44
+
45
+ describe ".guard" do
46
+ subject{ double("guard") }
47
+
48
+ before do
49
+ allow(subject).to receive(:guard).and_yield
50
+ allow(described_class).to receive(:new).with("static", :expires_in => 100).and_return(subject)
51
+ end
52
+
53
+ it "creates a new instance and calls guard with the given block" do
54
+ expect{ |probe| described_class.guard("static", { :expires_in => 100 }, &probe) }.to yield_control
55
+ end
56
+ end
57
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cache_guard
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Duarte Henriques
8
+ - Miguel Teixeira
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-01-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '3.4'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '3.4'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rubocop
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: 0.35.1
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: 0.35.1
42
+ description:
43
+ email:
44
+ - duarte.henriques@seedrs.com
45
+ - miguel.teixeira@seedrs.com
46
+ executables: []
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - lib/cache_guard.rb
51
+ - spec/lib/cache_guard_spec.rb
52
+ homepage: http://rubygems.org/gems/cache_guard
53
+ licenses:
54
+ - MIT
55
+ metadata: {}
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project:
72
+ rubygems_version: 2.4.8
73
+ signing_key:
74
+ specification_version: 4
75
+ summary: Allows you to protect the execution of a block against concurrency.
76
+ test_files:
77
+ - spec/lib/cache_guard_spec.rb