cache_box 0.0.1.pre.preview1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +27 -0
- data/cache_box.gemspec +26 -0
- data/lib/cache_box.rb +108 -0
- data/lib/cache_box_chain.rb +126 -0
- metadata +89 -0
checksums.yaml
ADDED
@@ -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.
|
data/cache_box.gemspec
ADDED
@@ -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
|
data/lib/cache_box.rb
ADDED
@@ -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: []
|