cache_box 0.0.1.pre.preview2 → 0.0.1.pre.preview7

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: ffc75a2d7008957a8c53dabf66772390d5eca8e964f6ab92f35fe57c063d5e52
4
- data.tar.gz: 28c08be79e3a089f14897a42805a3a3b0b12f44a49c8fda8bc81884763aacc72
3
+ metadata.gz: e95404d4c91af3089b9d7d5628a3449010007df8784043b3668bc028b3b54c44
4
+ data.tar.gz: f8fd2afe635ceab0504a2c2aef6b4a27417ad5bdde6564a7a39fd8af9b22840d
5
5
  SHA512:
6
- metadata.gz: 948602c9c4a3aac655c6a2c13a8284d92f9da2246a7b901133c050adb2119ceadb4936fe750cb27ab5d5afe383326e2e02cf623fb5c3d5145acb6a9dce289aa2
7
- data.tar.gz: c8f3529d877814c4007d31699dabbd4fc375714b52184f36ec6660f3c126463f90afbe522c5e7eee42f62c0495ea9483753f02de66f533297dd855ec0b20f88e
6
+ metadata.gz: 5c5a41a763a413cef9e294c01e94c18808f3e817bdd4baff7ac4b936225b19f3b7785a43981b9167066123d3fd0d5673e81f5b54c71586a83e64fa39c2907a99
7
+ data.tar.gz: b2029aca5aa9a5a36a82e7010cb5959787ee214d7a0b1739b8575e95e5c3cfb7a842fde3c9264449d1dcb45dc926180d9eb3bbfd18edcb4b30d0ba2d04a50206
@@ -2,25 +2,33 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'cache_box'
5
- spec.version = '0.0.1-preview2'
5
+ spec.version = '0.0.1-preview7'
6
6
  spec.authors = ['Codruț Constantin Gușoi']
7
- spec.email = ['codrut.gusoi+git-commit@gmail.com']
7
+ spec.email = ['codrut.gusoi+rubygems.org@gmail.com']
8
8
 
9
- spec.summary = 'A simple, fast, and easy to use file backed cache.'
9
+ spec.summary = 'A simple, fast, and easy to use local cache.'
10
10
  spec.homepage = 'https://gitlab.com/sdwolfz/cache_box_rb'
11
- spec.license = 'BSD 3-clause'
11
+ spec.license = 'BSD-3-Clause'
12
+
13
+ spec.metadata = {
14
+ 'homepage_uri' => 'https://gitlab.com/sdwolfz/cache_box_rb',
15
+ 'source_code_uri' => 'https://gitlab.com/sdwolfz/cache_box_rb'
16
+ }
12
17
 
13
18
  spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
14
19
 
15
20
  spec.files = [
16
21
  'lib/cache_box.rb',
17
- 'lib/cache_box_chain.rb',
22
+ 'lib/cache_box/chain.rb',
23
+ 'lib/cache_box/file_storage.rb',
24
+ 'lib/cache_box/memory_storage.rb',
18
25
  'LICENSE',
19
26
  'cache_box.gemspec'
20
27
  ]
21
28
  spec.require_paths = ['lib']
22
29
 
23
- spec.add_development_dependency 'minitest', '~> 5.0'
24
- spec.add_development_dependency 'rake', '~> 12.0'
25
- spec.add_development_dependency 'rubocop', '~> 0.88'
30
+ spec.add_development_dependency 'minitest', '~> 5.14'
31
+ spec.add_development_dependency 'pry-byebug', '~> 3.9'
32
+ spec.add_development_dependency 'rake', '~> 13.0'
33
+ spec.add_development_dependency 'rubocop', '~> 0.88'
26
34
  end
@@ -1,80 +1,123 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'fileutils'
4
- require_relative 'cache_box_chain'
4
+ require 'logger'
5
5
 
6
- class CacheBox
7
- def initialize(namespace = :namespace)
8
- validate!(namespace, 'namespace')
9
-
10
- @namespace = namespace
11
- @state = {}
12
- @root = File.join(Dir.pwd, '.cache')
13
- @directory = File.join(@root, @namespace.to_s)
14
- end
15
-
16
- def reset!(namespace = :namespace)
17
- initialize(namespace)
6
+ require_relative 'cache_box/chain'
7
+ require_relative 'cache_box/file_storage'
8
+ require_relative 'cache_box/memory_storage'
18
9
 
19
- self
10
+ class CacheBox
11
+ # Input:
12
+ #
13
+ # namespace = String | Symbol # Default: 'namespace'
14
+ #
15
+ # Output: N/A
16
+ def initialize(namespace = nil, logger: nil, storage: nil)
17
+ validate_symbol_or_string!(namespace, 'namespace')
18
+
19
+ @namespace = namespace&.to_s || 'namespace'
20
+ @logger = logger || Logger.new(STDOUT, level: Logger::INFO)
21
+ @storage = storage || FileStorage.new(namespace: @namespace)
22
+ @state = { result: {}, stash: {} }
20
23
  end
21
24
 
22
- def with(name = :name, *args)
23
- validate!(name, 'name')
24
-
25
- file = File.join(@directory, name.to_s)
26
- result = find(name, file)
27
- return result unless result.nil?
25
+ # Input:
26
+ #
27
+ # name = String | Symbol # Default: 'name'
28
+ # args = Array[...Object]
29
+ # &block = Proc(Hash{...Object => Object}, *args)
30
+ #
31
+ # Output: Object # Anything the &block returns.
32
+ def with(name = nil, *args)
33
+ validate_symbol_or_string!(name, 'name')
34
+ unless block_given?
35
+ raise(ArgumentError, 'The `:with` method requires a block')
36
+ end
28
37
 
29
- store(yield(*args), name, file)
30
- end
38
+ name = name&.to_s || 'name'
39
+ return @state[:result][name] if @state[:result].key?(name)
31
40
 
32
- def with_many(name = :name, *args)
33
- validate!(name, 'name')
41
+ data = @storage.read!(name)
42
+ if data&.key?(:result)
43
+ @state[:result][name] = data[:result]
34
44
 
35
- file = File.join(@directory, name.to_s)
36
- result = find(name, file)
37
- return result unless result.nil?
45
+ return data[:result]
46
+ elsif data&.key?(:stash)
47
+ @state[:stash][name] = data[:stash]
48
+ end
38
49
 
39
- storage = {}
50
+ stash = @state[:stash][name] || {}
40
51
  begin
41
- yield(storage, *args)
52
+ @state[:result][name] = yield(stash, *args)
42
53
  ensure
43
- store(storage, name, file)
54
+ if @state[:result].key?(name)
55
+ @state[:stash].delete(name)
56
+ @storage.write!(name, { result: @state[:result][name] })
57
+ else
58
+ @state[:stash][name] = stash
59
+ @storage.write!(name, { stash: stash })
60
+ end
44
61
  end
45
- storage
46
62
  end
47
63
 
48
- def has?(name = :name)
49
- validate!(name, 'name')
64
+ # Input:
65
+ #
66
+ # name = String | Symbol # Default: 'name'
67
+ #
68
+ # Output: true | false
69
+ def has?(name = nil)
70
+ validate_symbol_or_string!(name, 'name')
50
71
 
51
- file = File.join(@directory, name.to_s)
52
- load!(name, file)
72
+ name = name&.to_s || 'name'
73
+ return true if @state[:result].key?(name)
53
74
 
54
- @state.key?(name)
55
- end
75
+ data = @storage.read!(name)
56
76
 
57
- def expire!
58
- @state = {}
59
- FileUtils.remove_entry_secure(@directory, true)
77
+ if data&.key?(:result)
78
+ @state[:result][name] = data[:result]
79
+ elsif data&.key?(:stash)
80
+ @state[:stash][name] = data[:stash]
81
+ end
60
82
 
61
- self
83
+ @state[:result].key?(name)
62
84
  end
63
85
 
64
- def expire(name = :name)
65
- validate!(name, 'name')
66
-
67
- @state.delete(name)
68
- file = File.join(@directory, name.to_s)
69
- FileUtils.remove_entry_secure(file, true)
86
+ # Input:
87
+ #
88
+ # name = Array[String | Symbol] # Default: []
89
+ #
90
+ # Output: self
91
+ def expire!(*names)
92
+ validate_array_of_symbol_or_string!(names, 'names')
93
+
94
+ if names.empty?
95
+ @state = { result: {}, stash: {} }
96
+
97
+ @storage.reset!
98
+ else
99
+ names.each do |name|
100
+ name = name.to_s
101
+ @state[:result].delete(name)
102
+ @state[:stash].delete(name)
103
+
104
+ @storage.delete!(name)
105
+ end
106
+ end
70
107
 
71
108
  self
72
109
  end
73
110
 
74
111
  private
75
112
 
76
- def validate!(arg, name)
77
- return if arg.is_a?(Symbol) || arg.is_a?(String)
113
+ # Input:
114
+ #
115
+ # arg = String | Symbol
116
+ # name = String
117
+ #
118
+ # Output: N/A
119
+ def validate_symbol_or_string!(arg, name)
120
+ return if arg.nil? || arg.is_a?(Symbol) || arg.is_a?(String)
78
121
 
79
122
  klass = arg.class
80
123
  value = arg.inspect
@@ -82,28 +125,23 @@ class CacheBox
82
125
  raise(ArgumentError, "#{name} must be a Symbol or String, got #{klass}: #{value}")
83
126
  end
84
127
 
85
- def load!(name, file)
86
- return unless @state[name].nil? && File.exist?(file)
87
-
88
- content = File.read(file)
89
- @state[name] = Marshal.load(content)
90
- end
91
-
92
- def find(name, file)
93
- load!(name, file)
94
-
95
- @state[name]
96
- end
97
-
98
- def store(value, name, file)
99
- @state[name] = value
100
-
101
- content = Marshal.dump(value)
102
-
103
- directory = File.dirname(file)
104
- FileUtils.mkdir_p(directory) unless Dir.exist?(directory)
105
- File.write(file, content)
106
-
107
- value
128
+ # Input:
129
+ #
130
+ # arg = Array[String | Symbol]
131
+ # name = String
132
+ #
133
+ # Output: N/A
134
+ def validate_array_of_symbol_or_string!(args, name)
135
+ args.each do |arg|
136
+ next if arg.is_a?(Symbol) || arg.is_a?(String)
137
+
138
+ klass = arg.class
139
+ value = arg.inspect
140
+
141
+ raise(
142
+ ArgumentError,
143
+ "#{name} must each be Symbol or String, got #{klass}: #{value} in #{args}"
144
+ )
145
+ end
108
146
  end
109
147
  end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CacheBox
4
+ class Chain
5
+ # Input:
6
+ #
7
+ # namespace = String | Symbol # Default: 'namespace'
8
+ #
9
+ # Output: N/A
10
+ def initialize(namespace = nil, logger: nil, storage: nil)
11
+ namespace ||= 'namespace'
12
+ logger ||= Logger.new(STDOUT, level: Logger::INFO)
13
+ storage ||= FileStorage.new(namespace: namespace)
14
+
15
+ @cache = ::CacheBox.new(namespace, logger: logger, storage: storage)
16
+ @chain = []
17
+ @set = Set.new
18
+ end
19
+
20
+ # Input:
21
+ #
22
+ # name = String | Symbol
23
+ # args = Array[...Object]
24
+ # &block = Proc(Hash{...Object => Object}, *args)
25
+ #
26
+ # Output: self
27
+ def add(name, *args, &block)
28
+ validate_add!(name, &block)
29
+
30
+ string_name = name.to_s
31
+ if @set.include?(string_name)
32
+ raise(
33
+ ArgumentError,
34
+ "Chain already contains a step named #{name.inspect}"
35
+ )
36
+ else
37
+ @set << string_name
38
+ end
39
+
40
+ @chain.push(
41
+ [name, args, proc { |*all| @cache.with(string_name, *all, &block) }]
42
+ )
43
+
44
+ self
45
+ end
46
+
47
+ # Output: Object # Anything the last block in the chain returns.
48
+ def run!
49
+ work = []
50
+
51
+ @chain.reverse_each do |name, args, callable|
52
+ work.push([name, args, callable])
53
+
54
+ break if @cache.has?(name)
55
+ end
56
+
57
+ result = nil
58
+ work.reverse_each do |_name, args, callable|
59
+ input = []
60
+ input << result if result
61
+ input += args if args
62
+
63
+ result = callable.call(*input)
64
+ end
65
+
66
+ result
67
+ end
68
+
69
+ # Input:
70
+ #
71
+ # name = Array[String | Symbol] # Default: []
72
+ #
73
+ # Output: self
74
+ def expire!(*names)
75
+ @cache.expire!(*names)
76
+
77
+ self
78
+ end
79
+
80
+ private
81
+
82
+ # Input:
83
+ #
84
+ # name = String | Symbol
85
+ # &block = Proc
86
+ #
87
+ # Output: N/A
88
+ def validate_add!(name, &block)
89
+ unless name.is_a?(Symbol) || name.is_a?(String)
90
+ klass = name.class
91
+ value = name.inspect
92
+
93
+ raise(
94
+ ArgumentError,
95
+ "name must be a Symbol or String, got #{klass}: #{value}"
96
+ )
97
+ end
98
+
99
+ return unless block.nil?
100
+
101
+ raise(ArgumentError, 'The `:add` method requires a block')
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CacheBox
4
+ # A storage backed by files.
5
+ class FileStorage
6
+ # Input:
7
+ #
8
+ # namespace = Symbol | String # Default: 'namespace'
9
+ # path = String # Path; Default: nil
10
+ #
11
+ # Output: N/A
12
+ def initialize(namespace: nil, path: nil)
13
+ validate_symbol_or_string!(namespace, 'namespace')
14
+ validate_string!(path, 'path')
15
+
16
+ @namespace = namespace.to_s || 'namespace'
17
+
18
+ root = path || File.join(Dir.pwd, '.cache')
19
+ @path = File.join(root, @namespace)
20
+ end
21
+
22
+ # Output: self
23
+ def reset!
24
+ FileUtils.remove_entry_secure(@path, true)
25
+
26
+ self
27
+ end
28
+
29
+ # Reads the content.
30
+ #
31
+ # Input:
32
+ #
33
+ # name = String
34
+ #
35
+ # Output: Object # Anything
36
+ def read!(name)
37
+ validate_string!(name, 'name')
38
+
39
+ file = File.join(@path, name)
40
+ return unless File.exist?(file)
41
+
42
+ Marshal.load(File.read(file))
43
+ end
44
+
45
+ # Input:
46
+ #
47
+ # name = String
48
+ # data = Object # Anything
49
+ #
50
+ # Output: self
51
+ def write!(name, data)
52
+ validate_string!(name, 'name')
53
+
54
+ FileUtils.mkdir_p(@path) unless Dir.exist?(@path)
55
+
56
+ content = Marshal.dump(data)
57
+ file = File.join(@path, name)
58
+
59
+ File.write(file, content)
60
+
61
+ self
62
+ end
63
+
64
+ # Input:
65
+ #
66
+ # name = String
67
+ #
68
+ # Output: self
69
+ def delete!(name)
70
+ validate_string!(name, 'name')
71
+
72
+ file = File.join(@path, name)
73
+ FileUtils.remove_entry_secure(file, true)
74
+
75
+ self
76
+ end
77
+
78
+ # Input:
79
+ #
80
+ # name = String
81
+ #
82
+ # Output: true | false
83
+ def has?(name)
84
+ validate_string!(name, 'name')
85
+
86
+ file = File.join(@path, name)
87
+ File.file?(file)
88
+ end
89
+
90
+ private
91
+
92
+ def validate_symbol_or_string!(arg, name)
93
+ return if arg.nil? || arg.is_a?(Symbol) || arg.is_a?(String)
94
+
95
+ klass = arg.class
96
+ value = arg.inspect
97
+
98
+ raise(
99
+ ArgumentError,
100
+ "#{name} must be a Symbol or String, got #{klass}: #{value}"
101
+ )
102
+ end
103
+
104
+ def validate_string!(arg, name)
105
+ return if arg.nil? || arg.is_a?(String)
106
+
107
+ klass = arg.class
108
+ value = arg.inspect
109
+
110
+ raise(
111
+ ArgumentError,
112
+ "#{name} must be a String, got #{klass}: #{value}"
113
+ )
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,193 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CacheBox
4
+ # A storage backed by an in memory Hash.
5
+ class MemoryStorage
6
+ # Accepts a Hash or any Hash-like object as argument. Will use a plain Hash
7
+ # if none provided.
8
+ #
9
+ # Input:
10
+ #
11
+ # state = Hash{...Object => Object} # Default: nil
12
+ #
13
+ # Output: N/A
14
+ def initialize(state = nil)
15
+ validate!(state)
16
+
17
+ @state = state || {}
18
+ end
19
+
20
+ # Accepts a Hash or any Hash-like object as argument. Will use a plain Hash
21
+ # if none provided.
22
+ #
23
+ # Input:
24
+ #
25
+ # state = Hash{...Object => Object}
26
+ #
27
+ # Output: self
28
+ def reset!(state = nil)
29
+ initialize(state)
30
+
31
+ self
32
+ end
33
+
34
+ # Input:
35
+ #
36
+ # name = String
37
+ #
38
+ # Output: Object # Anything
39
+ def read!(name)
40
+ validate_string!(name, 'name')
41
+
42
+ @state[name]
43
+ end
44
+
45
+ # Input:
46
+ #
47
+ # name = String
48
+ # data = Object # Anything
49
+ #
50
+ # Output: self
51
+ def write!(name, data)
52
+ validate_string!(name, 'name')
53
+
54
+ @state[name] = data
55
+
56
+ self
57
+ end
58
+
59
+ # Input:
60
+ #
61
+ # name = String
62
+ #
63
+ # Output: self
64
+ def delete!(name)
65
+ validate_string!(name, 'name')
66
+
67
+ @state.delete(name)
68
+
69
+ self
70
+ end
71
+
72
+ # Input:
73
+ #
74
+ # name = String
75
+ #
76
+ # Output: true | false
77
+ def has?(name)
78
+ validate_string!(name, 'name')
79
+
80
+ @state.key?(name)
81
+ end
82
+
83
+ private
84
+
85
+ # Input:
86
+ #
87
+ # state = Object # Anything
88
+ #
89
+ # Output: N/A
90
+ def validate!(state)
91
+ return if state.nil? || state.is_a?(Hash)
92
+
93
+ validate_get!(state)
94
+ validate_set!(state)
95
+ validate_delete!(state)
96
+ validate_key!(state)
97
+ end
98
+
99
+ # Input:
100
+ #
101
+ # state = Object # Anything
102
+ #
103
+ # Output: N/A
104
+ def validate_get!(state)
105
+ unless state.respond_to?(:[])
106
+ raise(ArgumentError, 'Given state object does not respond to `:[]`')
107
+ end
108
+
109
+ arity = state.method(:[]).arity
110
+ unless arity == 1
111
+ raise(
112
+ ArgumentError,
113
+ "Given state object's `:[]` method arity must be 1, got: #{arity}"
114
+ )
115
+ end
116
+ end
117
+
118
+ # Input:
119
+ #
120
+ # state = Object # Anything
121
+ #
122
+ # Output: N/A
123
+ def validate_set!(state)
124
+ unless state.respond_to?(:[]=)
125
+ raise(ArgumentError, 'Given state object does not respond to `:[]=`')
126
+ end
127
+
128
+ arity = state.method(:[]=).arity
129
+ unless arity == 2
130
+ raise(
131
+ ArgumentError,
132
+ "Given state object's `:[]=` method arity must be 2, got: #{arity}"
133
+ )
134
+ end
135
+ end
136
+
137
+ # Input:
138
+ #
139
+ # state = Object # Anything
140
+ #
141
+ # Output: N/A
142
+ def validate_delete!(state)
143
+ unless state.respond_to?(:delete)
144
+ raise(ArgumentError, 'Given state object does not respond to `delete`')
145
+ end
146
+
147
+ arity = state.method(:delete).arity
148
+ unless arity == 1
149
+ raise(
150
+ ArgumentError,
151
+ "Given state object's `:delete` method arity must be 1, got: #{arity}"
152
+ )
153
+ end
154
+ end
155
+
156
+ # Input:
157
+ #
158
+ # state = Object # Anything
159
+ #
160
+ # Output: N/A
161
+ def validate_key!(state)
162
+ unless state.respond_to?(:key?)
163
+ raise(ArgumentError, 'Given state object does not respond to `:key?`')
164
+ end
165
+
166
+ arity = state.method(:key?).arity
167
+ unless arity == 1
168
+ raise(
169
+ ArgumentError,
170
+ "Given state object's `:key?` method arity must be 1, got: #{arity}"
171
+ )
172
+ end
173
+ end
174
+
175
+ # Input:
176
+ #
177
+ # arg = String
178
+ # name = String
179
+ #
180
+ # Output: N/A
181
+ def validate_string!(arg, name)
182
+ return if arg.nil? || arg.is_a?(String)
183
+
184
+ klass = arg.class
185
+ value = arg.inspect
186
+
187
+ raise(
188
+ ArgumentError,
189
+ "#{name} must be a String, got #{klass}: #{value}"
190
+ )
191
+ end
192
+ end
193
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cache_box
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.pre.preview2
4
+ version: 0.0.1.pre.preview7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Codruț Constantin Gușoi
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-18 00:00:00.000000000 Z
11
+ date: 2020-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -16,28 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '5.0'
19
+ version: '5.14'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '5.0'
26
+ version: '5.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry-byebug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.9'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.9'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '12.0'
47
+ version: '13.0'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '12.0'
54
+ version: '13.0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rubocop
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -52,9 +66,9 @@ dependencies:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: '0.88'
55
- description:
69
+ description:
56
70
  email:
57
- - codrut.gusoi+git-commit@gmail.com
71
+ - codrut.gusoi+rubygems.org@gmail.com
58
72
  executables: []
59
73
  extensions: []
60
74
  extra_rdoc_files: []
@@ -62,12 +76,16 @@ files:
62
76
  - LICENSE
63
77
  - cache_box.gemspec
64
78
  - lib/cache_box.rb
65
- - lib/cache_box_chain.rb
79
+ - lib/cache_box/chain.rb
80
+ - lib/cache_box/file_storage.rb
81
+ - lib/cache_box/memory_storage.rb
66
82
  homepage: https://gitlab.com/sdwolfz/cache_box_rb
67
83
  licenses:
68
- - BSD 3-clause
69
- metadata: {}
70
- post_install_message:
84
+ - BSD-3-Clause
85
+ metadata:
86
+ homepage_uri: https://gitlab.com/sdwolfz/cache_box_rb
87
+ source_code_uri: https://gitlab.com/sdwolfz/cache_box_rb
88
+ post_install_message:
71
89
  rdoc_options: []
72
90
  require_paths:
73
91
  - lib
@@ -82,8 +100,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
82
100
  - !ruby/object:Gem::Version
83
101
  version: 1.3.1
84
102
  requirements: []
85
- rubygems_version: 3.1.3
86
- signing_key:
103
+ rubygems_version: 3.1.2
104
+ signing_key:
87
105
  specification_version: 4
88
- summary: A simple, fast, and easy to use file backed cache.
106
+ summary: A simple, fast, and easy to use local cache.
89
107
  test_files: []
@@ -1,129 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class CacheBox
4
- class Chain
5
- def initialize(namespace = :namespace)
6
- @cache = ::CacheBox.new(namespace)
7
- @chain = []
8
- end
9
-
10
- def reset!(namespace = :namespace)
11
- @cache.reset!(namespace)
12
- @chain = []
13
-
14
- self
15
- end
16
-
17
- def chain(name, *args, &block)
18
- validate_chain!(name, &block)
19
-
20
- @chain.push(
21
- [name, args, proc { |*all| @cache.with(name, *all, &block) }]
22
- )
23
-
24
- self
25
- end
26
-
27
- def chain_many(name, *args, &block)
28
- validate_chain!(name, &block)
29
-
30
- @chain.push(
31
- [name, args, proc { |*all| @cache.with_many(name, *all, &block) }]
32
- )
33
-
34
- self
35
- end
36
-
37
- def run!(all = nil)
38
- validate_run!(all)
39
-
40
- if all
41
- run_all
42
- else
43
- run_chain
44
- end
45
- end
46
-
47
- def expire!
48
- @cache.expire!
49
-
50
- self
51
- end
52
-
53
- def expire(*names)
54
- names.each do |name|
55
- @cache.expire(name)
56
- end
57
-
58
- self
59
- end
60
-
61
- private
62
-
63
- def validate_chain!(name, &block)
64
- unless name.is_a?(Symbol) || name.is_a?(String)
65
- klass = name.class
66
- value = name.inspect
67
-
68
- raise(
69
- ArgumentError,
70
- "name must be a Symbol or a String, got #{klass}: #{value}"
71
- )
72
- end
73
-
74
- return unless block.nil?
75
-
76
- raise(
77
- ArgumentError,
78
- 'The `#chain/2` method needs to be called with a block'
79
- )
80
- end
81
-
82
- def validate_run!(arg)
83
- return if arg.nil? || arg == :all
84
-
85
- klass = arg.class
86
- value = arg.inspect
87
-
88
- raise(
89
- ArgumentError,
90
- 'The `run!` method only accepts `nil` or the Symbol `:all` as an ' \
91
- "argument, got #{klass}: #{value}"
92
- )
93
- end
94
-
95
- def run_all
96
- result = nil
97
- @chain.each do |_name, args, callable|
98
- input = []
99
- input << result if result
100
- input += args if args
101
-
102
- result = callable.call(*input)
103
- end
104
-
105
- result
106
- end
107
-
108
- def run_chain
109
- work = []
110
-
111
- @chain.reverse_each do |name, args, callable|
112
- work.push([name, args, callable])
113
-
114
- break if @cache.has?(name)
115
- end
116
-
117
- result = nil
118
- work.reverse_each do |_name, args, callable|
119
- input = []
120
- input << result if result
121
- input += args if args
122
-
123
- result = callable.call(*input)
124
- end
125
-
126
- result
127
- end
128
- end
129
- end