cache_box 0.0.1.pre.preview7 → 0.0.1.pre.preview8

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: e95404d4c91af3089b9d7d5628a3449010007df8784043b3668bc028b3b54c44
4
- data.tar.gz: f8fd2afe635ceab0504a2c2aef6b4a27417ad5bdde6564a7a39fd8af9b22840d
3
+ metadata.gz: 2121d192ceadcf66d3ddcea5bbed36e4b90d5a34749e50b3f23672f61cb8a7ea
4
+ data.tar.gz: b5c009712c162fa0b761ff4b8998645aed7a09e467e6569fbc785b76ac166b78
5
5
  SHA512:
6
- metadata.gz: 5c5a41a763a413cef9e294c01e94c18808f3e817bdd4baff7ac4b936225b19f3b7785a43981b9167066123d3fd0d5673e81f5b54c71586a83e64fa39c2907a99
7
- data.tar.gz: b2029aca5aa9a5a36a82e7010cb5959787ee214d7a0b1739b8575e95e5c3cfb7a842fde3c9264449d1dcb45dc926180d9eb3bbfd18edcb4b30d0ba2d04a50206
6
+ metadata.gz: c4c45937029f9096bc8a8224decec4ab72faa98569043b1292d19e050826a92a8be57bdf26612e2800f82712654a444b03c66327e9a4baa5f8110444967397c3
7
+ data.tar.gz: 97dece56e4b22094415960285047136b15a1e02bea647b0c8b41eb2b762b661ef301f81b7acc376b27cc9027a4c86c7403971656cf824e9e8debc59439922ad0
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'cache_box'
5
- spec.version = '0.0.1-preview7'
5
+ spec.version = '0.0.1-preview8'
6
6
  spec.authors = ['Codruț Constantin Gușoi']
7
7
  spec.email = ['codrut.gusoi+rubygems.org@gmail.com']
8
8
 
@@ -19,9 +19,14 @@ Gem::Specification.new do |spec|
19
19
 
20
20
  spec.files = [
21
21
  'lib/cache_box.rb',
22
+ 'lib/cache_box/helper/validate.rb',
23
+ 'lib/cache_box/scheduler/serial.rb',
24
+ 'lib/cache_box/storage/file.rb',
25
+ 'lib/cache_box/storage/memory.rb',
26
+ 'lib/cache_box/box.rb',
22
27
  'lib/cache_box/chain.rb',
23
- 'lib/cache_box/file_storage.rb',
24
- 'lib/cache_box/memory_storage.rb',
28
+ 'lib/cache_box/graph.rb',
29
+ 'lib/cache_box/unit.rb',
25
30
  'LICENSE',
26
31
  'cache_box.gemspec'
27
32
  ]
@@ -3,62 +3,49 @@
3
3
  require 'fileutils'
4
4
  require 'logger'
5
5
 
6
+ require_relative 'cache_box/helper/validate'
7
+
8
+ require_relative 'cache_box/storage/file'
9
+ require_relative 'cache_box/storage/memory'
10
+
11
+ require_relative 'cache_box/box'
12
+ require_relative 'cache_box/unit'
13
+
14
+ require_relative 'cache_box/scheduler/serial'
15
+
6
16
  require_relative 'cache_box/chain'
7
- require_relative 'cache_box/file_storage'
8
- require_relative 'cache_box/memory_storage'
17
+ require_relative 'cache_box/graph'
9
18
 
10
19
  class CacheBox
20
+ include CacheBox::Helper::Validate
21
+
11
22
  # Input:
12
23
  #
13
- # namespace = String | Symbol # Default: 'namespace'
24
+ # namespace = String | Symbol # Default: :namespace
25
+ # logger = Logger
26
+ # storage = CacheBox::Storage::*
14
27
  #
15
28
  # Output: N/A
16
29
  def initialize(namespace = nil, logger: nil, storage: nil)
17
- validate_symbol_or_string!(namespace, 'namespace')
30
+ namespace ||= :namespace
31
+ validate_string_or_symbol!(namespace, 'namespace')
18
32
 
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: {} }
33
+ @unit = ::CacheBox::Unit.new(namespace, logger: logger, storage: storage)
23
34
  end
24
35
 
25
36
  # Input:
26
37
  #
27
38
  # name = String | Symbol # Default: 'name'
28
- # args = Array[...Object]
29
- # &block = Proc(Hash{...Object => Object}, *args)
39
+ # args = Object
40
+ # &block = Proc(CacheBox::Box)
30
41
  #
31
42
  # 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
37
-
38
- name = name&.to_s || 'name'
39
- return @state[:result][name] if @state[:result].key?(name)
40
-
41
- data = @storage.read!(name)
42
- if data&.key?(:result)
43
- @state[:result][name] = data[:result]
44
-
45
- return data[:result]
46
- elsif data&.key?(:stash)
47
- @state[:stash][name] = data[:stash]
48
- end
49
-
50
- stash = @state[:stash][name] || {}
51
- begin
52
- @state[:result][name] = yield(stash, *args)
53
- ensure
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
61
- end
43
+ def with(name = nil, args = nil, &block)
44
+ name ||= 'name'
45
+ validate_string_or_symbol!(name, 'name')
46
+ validate_block_presence!(block, '#with')
47
+
48
+ @unit.with(name, args, nil, &block)
62
49
  end
63
50
 
64
51
  # Input:
@@ -67,20 +54,10 @@ class CacheBox
67
54
  #
68
55
  # Output: true | false
69
56
  def has?(name = nil)
70
- validate_symbol_or_string!(name, 'name')
71
-
72
- name = name&.to_s || 'name'
73
- return true if @state[:result].key?(name)
57
+ name ||= 'name'
58
+ validate_string_or_symbol!(name, 'name')
74
59
 
75
- data = @storage.read!(name)
76
-
77
- if data&.key?(:result)
78
- @state[:result][name] = data[:result]
79
- elsif data&.key?(:stash)
80
- @state[:stash][name] = data[:stash]
81
- end
82
-
83
- @state[:result].key?(name)
60
+ @unit.has?(name)
84
61
  end
85
62
 
86
63
  # Input:
@@ -89,59 +66,10 @@ class CacheBox
89
66
  #
90
67
  # Output: self
91
68
  def expire!(*names)
92
- validate_array_of_symbol_or_string!(names, 'names')
93
-
94
- if names.empty?
95
- @state = { result: {}, stash: {} }
69
+ validate_array_of_string_or_symbol!(names, 'names')
96
70
 
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
71
+ @unit.expire!(*names)
107
72
 
108
73
  self
109
74
  end
110
-
111
- private
112
-
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)
121
-
122
- klass = arg.class
123
- value = arg.inspect
124
-
125
- raise(ArgumentError, "#{name} must be a Symbol or String, got #{klass}: #{value}")
126
- end
127
-
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
146
- end
147
75
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CacheBox
4
+ # A container for references needed during execution.
5
+ class Box
6
+ attr_reader :namespace, :name, :args, :input, :stash, :logger
7
+
8
+ def initialize(namespace:, name:, args:, input:, stash:, logger:)
9
+ @namespace = namespace
10
+ @name = name
11
+ @args = args
12
+ @input = input
13
+ @stash = stash
14
+ @logger = logger
15
+ end
16
+ end
17
+ end
@@ -2,43 +2,52 @@
2
2
 
3
3
  class CacheBox
4
4
  class Chain
5
+ include CacheBox::Helper::Validate
6
+
5
7
  # Input:
6
8
  #
7
9
  # namespace = String | Symbol # Default: 'namespace'
8
10
  #
9
11
  # Output: N/A
10
12
  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)
13
+ namespace ||= :namespace
14
+ validate_string_or_symbol!(namespace, 'namespace')
15
+
16
+ logger ||= Logger.new(STDOUT, level: Logger::INFO)
17
+ storage ||= ::CacheBox::Storage::File.new(namespace: namespace)
18
+
19
+ @unit = ::CacheBox::Unit.new(namespace, logger: logger, storage: storage)
20
+ @chain = []
21
+ @lookup = Set.new
14
22
 
15
- @cache = ::CacheBox.new(namespace, logger: logger, storage: storage)
16
- @chain = []
17
- @set = Set.new
23
+ @namespace = namespace
24
+ @logger = logger
18
25
  end
19
26
 
20
27
  # Input:
21
28
  #
22
29
  # name = String | Symbol
23
- # args = Array[...Object]
30
+ # input = Object # Default: nil
24
31
  # &block = Proc(Hash{...Object => Object}, *args)
25
32
  #
26
33
  # Output: self
27
- def add(name, *args, &block)
28
- validate_add!(name, &block)
34
+ def add(name, args = nil, &block)
35
+ validate_string_or_symbol!(name, 'name')
36
+ validate_block_presence!(block, '#add')
29
37
 
30
- string_name = name.to_s
31
- if @set.include?(string_name)
38
+ name_o = name
39
+ name_s = name.to_s
40
+ if @lookup.include?(name_s)
32
41
  raise(
33
42
  ArgumentError,
34
- "Chain already contains a step named #{name.inspect}"
43
+ "Chain already contains a step named #{name_o.inspect}"
35
44
  )
36
45
  else
37
- @set << string_name
46
+ @lookup << name_s
38
47
  end
39
48
 
40
49
  @chain.push(
41
- [name, args, proc { |*all| @cache.with(string_name, *all, &block) }]
50
+ [name_o, proc { |input| @unit.with(name_s, args, input, &block) }]
42
51
  )
43
52
 
44
53
  self
@@ -48,19 +57,19 @@ class CacheBox
48
57
  def run!
49
58
  work = []
50
59
 
51
- @chain.reverse_each do |name, args, callable|
52
- work.push([name, args, callable])
60
+ @chain.reverse_each do |name, callable|
61
+ work.push([name, callable])
53
62
 
54
- break if @cache.has?(name)
63
+ break if @unit.has?(name)
55
64
  end
56
65
 
57
- result = nil
58
- work.reverse_each do |_name, args, callable|
59
- input = []
60
- input << result if result
61
- input += args if args
66
+ result = nil
67
+ previous = nil
68
+ work.reverse_each do |name, callable|
69
+ result = callable.call(result)
62
70
 
63
- result = callable.call(*input)
71
+ @unit.clear(previous) if previous
72
+ previous = name
64
73
  end
65
74
 
66
75
  result
@@ -72,33 +81,10 @@ class CacheBox
72
81
  #
73
82
  # Output: self
74
83
  def expire!(*names)
75
- @cache.expire!(*names)
84
+ validate_array_of_string_or_symbol!(names, 'names')
85
+ @unit.expire!(*names)
76
86
 
77
87
  self
78
88
  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
89
  end
104
90
  end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CacheBox
4
+ class Graph
5
+ include CacheBox::Helper::Validate
6
+
7
+ # Input:
8
+ #
9
+ # namespace = String | Symbol # Default: 'namespace'
10
+ # scheduler = CacheBox::Scheduler::*
11
+ # storage = CacheBox::Storage::*
12
+ # logger = Logger
13
+ #
14
+ # Output: N/A
15
+ def initialize(namespace = nil, scheduler: nil, storage: nil, logger: nil)
16
+ namespace ||= :namespace
17
+ validate_string_or_symbol!(namespace, 'namespace')
18
+
19
+ @namespace = namespace
20
+ @logger = logger || Logger.new(STDOUT, level: Logger::INFO)
21
+ @storage = storage || ::CacheBox::Storage::File.new(namespace: @namespace)
22
+ @scheduler = scheduler || ::CacheBox::Scheduler::Serial.new(logger: @logger)
23
+ @unit = ::CacheBox::Unit.new(@namespace, logger: @logger, storage: @storage)
24
+
25
+ @nodes = {}
26
+ end
27
+
28
+ # Input:
29
+ #
30
+ # edge = String |
31
+ # Symbol |
32
+ # Hash{String | Symbol => String | Symbol | Array[String | Symbol]}
33
+ # args = Object
34
+ # &block = Proc(Hash{...Object => Object}, *args)
35
+ #
36
+ # Output: self
37
+ def node(edge, args = nil, &block)
38
+ validate_edge!(edge)
39
+ validate_block_presence!(block, '#node')
40
+
41
+ @scheduler.add(edge)
42
+ name_o = extract_name(edge)
43
+ name_s = name_o.to_s
44
+
45
+ @nodes[name_s] = [
46
+ name_o,
47
+ proc { |input| @unit.with(name_s, args, input, &block) }
48
+ ]
49
+
50
+ self
51
+ end
52
+
53
+ # Input: N/A
54
+ #
55
+ # Output: Object # Anything the last block in the chain returns.
56
+ def run!
57
+ @scheduler.run!(@nodes, @unit)
58
+ end
59
+
60
+ # Input:
61
+ #
62
+ # name = Array[String | Symbol] # Default: []
63
+ #
64
+ # Output: self
65
+ def expire!(*names)
66
+ validate_array_of_string_or_symbol!(names, 'names')
67
+ @unit.expire!(*names)
68
+
69
+ self
70
+ end
71
+
72
+ private
73
+
74
+ # Input:
75
+ #
76
+ # edge = String |
77
+ # Symbol |
78
+ # Hash{String | Symbol => String | Symbol | Array[String | Symbol]}
79
+ #
80
+ # Output: String
81
+ def extract_name(edge)
82
+ return edge.to_s if edge.is_a?(Symbol) || edge.is_a?(String)
83
+
84
+ edge.keys.first.to_s
85
+ end
86
+ end
87
+ end