cache_box 0.0.1.pre.preview1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 19b591535ab5ba124dca095013f08a3be9b348e0138a1738ec6c3088f388e8b9
4
+ data.tar.gz: 33183202f61274a5f3cfbae070bb83a8f2749b99596daeb98a43f173da8e5ea7
5
+ SHA512:
6
+ metadata.gz: e14a3c9b73792b6debc38676ce17f28ecfc81981e96476c7d6038ef4a1b9cd9af48513fc4569b9155edb5aa1c685e0ed2ad7844be2ff4e98ae905dce131fdff0
7
+ data.tar.gz: fd250b2db538d59d215ab656def286afca52d09894d1ea667484a1927441bd1d50638c5a1f0c187a89fb92cb40f7863c5b018fba8ae47867eec15df65edb8233
data/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (c) 2020, Codruț Constantin Gușoi
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ * Neither the name of the software nor the names of its
15
+ contributors may be used to endorse or promote products derived from
16
+ this software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'cache_box'
5
+ spec.version = '0.0.1-preview1'
6
+ spec.authors = ['Codruț Constantin Gușoi']
7
+ spec.email = ['codrut.gusoi+git-commit@gmail.com']
8
+
9
+ spec.summary = 'A simple, fast, and easy to use file backed cache.'
10
+ spec.homepage = 'https://gitlab.com/sdwolfz/cache_box_rb'
11
+ spec.license = 'BSD 3-clause'
12
+
13
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
14
+
15
+ spec.files = [
16
+ 'lib/cache_box.rb',
17
+ 'lib/cache_box_chain.rb',
18
+ 'LICENSE',
19
+ 'cache_box.gemspec'
20
+ ]
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_development_dependency 'minitest', '~> 5.0'
24
+ spec.add_development_dependency 'rake', '~> 12.0'
25
+ spec.add_development_dependency 'rubocop', '~> 0.88'
26
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+ require_relative 'cache_box_chain'
5
+
6
+ class CacheBox
7
+ def initialize(namespace = :default_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 = :default_namespace)
17
+ initialize(namespace)
18
+
19
+ self
20
+ end
21
+
22
+ def with(name = :default_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?
28
+
29
+ store(yield(*args), name, file)
30
+ end
31
+
32
+ def with_many(name = :default_name, *args)
33
+ validate!(name, 'name')
34
+
35
+ file = File.join(@directory, name.to_s)
36
+ result = find(name, file)
37
+ return result unless result.nil?
38
+
39
+ storage = {}
40
+ begin
41
+ yield(storage, *args)
42
+ ensure
43
+ store(storage, name, file)
44
+ end
45
+ storage
46
+ end
47
+
48
+ def has?(name = :default_name)
49
+ validate!(name, 'name')
50
+
51
+ file = File.join(@directory, name.to_s)
52
+ load!(name, file)
53
+
54
+ @state.key?(name)
55
+ end
56
+
57
+ def expire!
58
+ @state = {}
59
+ FileUtils.remove_entry_secure(@directory, true)
60
+
61
+ self
62
+ end
63
+
64
+ def expire(name = :default_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)
70
+
71
+ self
72
+ end
73
+
74
+ private
75
+
76
+ def validate!(arg, name)
77
+ return if arg.is_a?(Symbol)
78
+
79
+ klass = arg.class
80
+ value = arg.inspect
81
+
82
+ raise(ArgumentError, "#{name} must be a Symbol, got #{klass}: #{value}")
83
+ end
84
+
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
+ FileUtils.mkdir_p(@directory) unless Dir.exist?(@directory)
104
+ File.write(file, content)
105
+
106
+ value
107
+ end
108
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CacheBox
4
+ class Chain
5
+ def initialize(namespace = :default_namespace)
6
+ @cache = ::CacheBox.new(namespace)
7
+ @chain = []
8
+ end
9
+
10
+ def reset!(namespace = :default_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)
65
+ klass = name.class
66
+ value = name.inspect
67
+
68
+ raise(ArgumentError, "name must be a Symbol, got #{klass}: #{value}")
69
+ end
70
+
71
+ return unless block.nil?
72
+
73
+ raise(
74
+ ArgumentError,
75
+ 'The `#chain/2` method needs to be called with a block'
76
+ )
77
+ end
78
+
79
+ def validate_run!(arg)
80
+ return if arg.nil? || arg == :all
81
+
82
+ klass = arg.class
83
+ value = arg.inspect
84
+
85
+ raise(
86
+ ArgumentError,
87
+ 'The `run!` method only accepts `nil` or the Symbol `:all` as an ' \
88
+ "argument, got #{klass}: #{value}"
89
+ )
90
+ end
91
+
92
+ def run_all
93
+ result = nil
94
+ @chain.each do |_name, args, callable|
95
+ input = []
96
+ input << result if result
97
+ input += args if args
98
+
99
+ result = callable.call(*input)
100
+ end
101
+
102
+ result
103
+ end
104
+
105
+ def run_chain
106
+ work = []
107
+
108
+ @chain.reverse_each do |name, args, callable|
109
+ work.push([name, args, callable])
110
+
111
+ break if @cache.has?(name)
112
+ end
113
+
114
+ result = nil
115
+ work.reverse_each do |_name, args, callable|
116
+ input = []
117
+ input << result if result
118
+ input += args if args
119
+
120
+ result = callable.call(*input)
121
+ end
122
+
123
+ result
124
+ end
125
+ end
126
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cache_box
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.pre.preview1
5
+ platform: ruby
6
+ authors:
7
+ - Codruț Constantin Gușoi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-07-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '12.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '12.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.88'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.88'
55
+ description:
56
+ email:
57
+ - codrut.gusoi+git-commit@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - LICENSE
63
+ - cache_box.gemspec
64
+ - lib/cache_box.rb
65
+ - lib/cache_box_chain.rb
66
+ homepage: https://gitlab.com/sdwolfz/cache_box_rb
67
+ licenses:
68
+ - BSD 3-clause
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: 2.5.0
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">"
82
+ - !ruby/object:Gem::Version
83
+ version: 1.3.1
84
+ requirements: []
85
+ rubygems_version: 3.1.3
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: A simple, fast, and easy to use file backed cache.
89
+ test_files: []