timed_lru 0.3.2 → 0.5.1

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
- SHA1:
3
- metadata.gz: 6cf30083009f9f233369eea32cbbe9446ed8cb37
4
- data.tar.gz: 0eaf174e3f28b27e20983daf5adb38a73158e0ac
2
+ SHA256:
3
+ metadata.gz: d8356a5bb499e4071592b34aa27409e1f547e0f7738f6b54c06114f725aba41c
4
+ data.tar.gz: e7a468c52c087700490049f2fce67f4c27a212022080cdf2e462664f5546e53a
5
5
  SHA512:
6
- metadata.gz: 5e8e534ba9487aab9255be94956beea7c7bec8cd1364c2c2db446258f308c4e5969b50df303ac21197be77ea5d938aeff02577a825247e7147bf76555f7c29ec
7
- data.tar.gz: a4a8b1b83dbd3ad8d50a3d74ad6ff566f27a0ec1e9782615fadd83fdd6e3e643eaf425b4c26efe15c10ec675bcbc596f9942fd88c290bc9858150a66a8cf6029
6
+ metadata.gz: ecc600e5afa12ac7a73b2a4a8c4efef9b9760711ace6bc2f2411fe4701c08c6582ca6123ff28f269ed4231d96d59405c4a69ef47fe118d5d0f767e17ffeee120
7
+ data.tar.gz: b642d728caea2b800b0cef3d3f46e2e3e823c8459a8cbc38cb5cf6d5025fb60fe5a832fa729d499e6434bf5cc31f5a0e8a843aa4288af40abb6e88d2975a3c27
@@ -0,0 +1,21 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ ruby-version: ["2.7", "3.0", "3.1"]
15
+ steps:
16
+ - uses: actions/checkout@v2
17
+ - uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: ${{ matrix.ruby-version }}
20
+ bundler-cache: true
21
+ - run: bundle exec rake
data/.gitignore CHANGED
@@ -2,3 +2,4 @@
2
2
  .yardoc/
3
3
  coverage/
4
4
  doc/
5
+ .rubocop-*
data/.rubocop.yml ADDED
@@ -0,0 +1,10 @@
1
+ inherit_gem:
2
+ rubocop-bsm:
3
+ - default.yml
4
+ inherit_mode:
5
+ merge:
6
+ - Exclude
7
+ AllCops:
8
+ TargetRubyVersion: "2.7"
9
+ Naming/MemoizedInstanceVariableName:
10
+ Enabled: false
data/Gemfile CHANGED
@@ -1,6 +1,2 @@
1
- source "http://rubygems.org"
1
+ source 'http://rubygems.org'
2
2
  gemspec
3
-
4
- gem 'coveralls', require: false, group: :test
5
- gem 'json', '>= 1.7.7', require: false, group: :test
6
-
data/Gemfile.lock CHANGED
@@ -1,58 +1,68 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- timed_lru (0.3.2)
4
+ timed_lru (0.5.1)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
8
8
  specs:
9
- coveralls (0.8.21)
10
- json (>= 1.8, < 3)
11
- simplecov (~> 0.14.1)
12
- term-ansicolor (~> 1.3)
13
- thor (~> 0.19.4)
14
- tins (~> 1.6)
15
- diff-lcs (1.3)
16
- docile (1.1.5)
17
- json (2.1.0)
18
- rake (12.3.0)
19
- redcarpet (3.4.0)
20
- rspec (3.7.0)
21
- rspec-core (~> 3.7.0)
22
- rspec-expectations (~> 3.7.0)
23
- rspec-mocks (~> 3.7.0)
24
- rspec-core (3.7.0)
25
- rspec-support (~> 3.7.0)
26
- rspec-expectations (3.7.0)
9
+ ast (2.4.2)
10
+ diff-lcs (1.5.0)
11
+ parallel (1.22.1)
12
+ parser (3.1.2.0)
13
+ ast (~> 2.4.1)
14
+ rainbow (3.1.1)
15
+ rake (13.0.6)
16
+ regexp_parser (2.5.0)
17
+ rexml (3.2.5)
18
+ rspec (3.11.0)
19
+ rspec-core (~> 3.11.0)
20
+ rspec-expectations (~> 3.11.0)
21
+ rspec-mocks (~> 3.11.0)
22
+ rspec-core (3.11.0)
23
+ rspec-support (~> 3.11.0)
24
+ rspec-expectations (3.11.0)
27
25
  diff-lcs (>= 1.2.0, < 2.0)
28
- rspec-support (~> 3.7.0)
29
- rspec-mocks (3.7.0)
26
+ rspec-support (~> 3.11.0)
27
+ rspec-mocks (3.11.1)
30
28
  diff-lcs (>= 1.2.0, < 2.0)
31
- rspec-support (~> 3.7.0)
32
- rspec-support (3.7.0)
33
- simplecov (0.14.1)
34
- docile (~> 1.1.0)
35
- json (>= 1.8, < 3)
36
- simplecov-html (~> 0.10.0)
37
- simplecov-html (0.10.2)
38
- term-ansicolor (1.6.0)
39
- tins (~> 1.0)
40
- thor (0.19.4)
41
- tins (1.16.3)
42
- yard (0.9.12)
29
+ rspec-support (~> 3.11.0)
30
+ rspec-support (3.11.0)
31
+ rubocop (1.30.1)
32
+ parallel (~> 1.10)
33
+ parser (>= 3.1.0.0)
34
+ rainbow (>= 2.2.2, < 4.0)
35
+ regexp_parser (>= 1.8, < 3.0)
36
+ rexml (>= 3.2.5, < 4.0)
37
+ rubocop-ast (>= 1.18.0, < 2.0)
38
+ ruby-progressbar (~> 1.7)
39
+ unicode-display_width (>= 1.4.0, < 3.0)
40
+ rubocop-ast (1.18.0)
41
+ parser (>= 3.1.1.0)
42
+ rubocop-bsm (0.6.0)
43
+ rubocop (~> 1.0)
44
+ rubocop-performance
45
+ rubocop-rake
46
+ rubocop-rspec
47
+ rubocop-performance (1.14.1)
48
+ rubocop (>= 1.7.0, < 2.0)
49
+ rubocop-ast (>= 0.4.0)
50
+ rubocop-rake (0.6.0)
51
+ rubocop (~> 1.0)
52
+ rubocop-rspec (2.11.1)
53
+ rubocop (~> 1.19)
54
+ ruby-progressbar (1.11.0)
55
+ unicode-display_width (2.1.0)
43
56
 
44
57
  PLATFORMS
45
- ruby
58
+ x86_64-linux
46
59
 
47
60
  DEPENDENCIES
48
61
  bundler
49
- coveralls
50
- json (>= 1.7.7)
51
62
  rake
52
- redcarpet
53
63
  rspec
64
+ rubocop-bsm
54
65
  timed_lru!
55
- yard
56
66
 
57
67
  BUNDLED WITH
58
- 1.16.0
68
+ 2.3.9
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2021 Black Square Media Ltd
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md CHANGED
@@ -1,16 +1,13 @@
1
- Timed LRU
2
- =========
1
+ # Timed LRU
3
2
 
4
- [![Build Status](https://travis-ci.org/bsm/timed_lru.png)](https://travis-ci.org/bsm/timed_lru)
3
+ [![Build Status](https://github.com/bsm/timed_lru/actions/workflows/ruby.yml/badge.svg)](https://github.com/bsm/timed_lru/actions/workflows/ruby.yml)
5
4
  [![Dependency Status](https://gemnasium.com/bsm/timed_lru.png)](https://gemnasium.com/bsm/timed_lru)
6
- [![Coverage Status](https://coveralls.io/repos/bsm/timed_lru/badge.png)](https://coveralls.io/r/bsm/timed_lru)
7
5
 
8
6
  My implementation of a simple, thread-safe LRU with (optional) TTLs
9
7
  and constant time operations. There are many LRUs for Ruby available but
10
8
  I was unable to find one that matches all three requirements.
11
9
 
12
- Install
13
- -------
10
+ ## Install
14
11
 
15
12
  Install it via `gem`:
16
13
 
@@ -20,8 +17,7 @@ gem install timed_lru
20
17
 
21
18
  Or just bundle it with your project.
22
19
 
23
- Usage Example
24
- -------------
20
+ ## Usage Example
25
21
 
26
22
  ```ruby
27
23
  # Initialize with a max size (default: 100) and a TTL (default: none)
@@ -45,29 +41,3 @@ sleep(4)
45
41
  lru["c"] # => "value 3"
46
42
  lru.keys # => ["c", "d"]
47
43
  ```
48
-
49
- Licence
50
- -------
51
-
52
- ```
53
- Copyright (c) 2013 Black Square Media Ltd
54
-
55
- Permission is hereby granted, free of charge, to any person obtaining
56
- a copy of this software and associated documentation files (the
57
- "Software"), to deal in the Software without restriction, including
58
- without limitation the rights to use, copy, modify, merge, publish,
59
- distribute, sublicense, and/or sell copies of the Software, and to
60
- permit persons to whom the Software is furnished to do so, subject to
61
- the following conditions:
62
-
63
- The above copyright notice and this permission notice shall be
64
- included in all copies or substantial portions of the Software.
65
-
66
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
67
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
68
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
69
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
70
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
71
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
72
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
73
- ```
data/Rakefile CHANGED
@@ -1,14 +1,9 @@
1
1
  require 'bundler/setup'
2
2
  require 'bundler/gem_tasks'
3
-
4
3
  require 'rspec/core/rake_task'
5
- RSpec::Core::RakeTask.new(:spec)
6
- RSpec::Core::RakeTask.new(:coverage) do |c|
7
- c.ruby_opts = '-r ./spec/coverage_helper'
8
- end
4
+ require 'rubocop/rake_task'
9
5
 
10
- require 'yard'
11
- YARD::Rake::YardocTask.new
6
+ RSpec::Core::RakeTask.new(:spec)
7
+ RuboCop::RakeTask.new(:rubocop)
12
8
 
13
- desc 'Default: run specs.'
14
- task :default => :spec
9
+ task default: %i[spec rubocop]
data/lib/timed_lru.rb CHANGED
@@ -23,22 +23,22 @@ class TimedLRU
23
23
  # @param [Hash] opts options
24
24
  # @option opts [Integer] max_size
25
25
  # maximum allowed number of items, defaults to 100
26
+ # @option opts [Integer,Float] ttl
27
+ # the TTL in seconds
26
28
  # @option opts [Boolean] thread_safe
27
29
  # true by default, set to false if you are not using threads a *really* need
28
30
  # that extra bit of performance
29
- # @option opts [Integer] ttl
30
- # the TTL in seconds
31
- def initialize(opts = {})
31
+ def initialize(max_size: 100, ttl: nil, thread_safe: true)
32
32
  super() # MonitorMixin
33
33
 
34
34
  @hash = {}
35
- @max_size = Integer(opts[:max_size] || 100)
36
- @ttl = Integer(opts[:ttl]) if opts[:ttl]
35
+ @max_size = Integer(max_size)
36
+ @ttl = Float(ttl) if ttl
37
37
 
38
- raise ArgumentError, "Option :max_size must be > 0" unless max_size > 0
39
- raise ArgumentError, "Option :ttl must be > 0" unless ttl.nil? || ttl > 0
38
+ raise ArgumentError, 'Option :max_size must be > 0' unless max_size.positive?
39
+ raise ArgumentError, 'Option :ttl must be > 0' unless ttl.nil? || ttl.positive?
40
40
 
41
- extend ThreadUnsafe if opts[:thread_safe] == false
41
+ extend ThreadUnsafe if thread_safe == false
42
42
  end
43
43
 
44
44
  # Stores a `value` by `key`
@@ -48,13 +48,13 @@ class TimedLRU
48
48
  def store(key, value)
49
49
  mon_synchronize do
50
50
  node = (@hash[key] ||= Node.new(key))
51
- node.value = value
51
+ node.value = value
52
52
  touch(node)
53
53
  compact!
54
54
  node.value
55
55
  end
56
56
  end
57
- alias_method :[]=, :store
57
+ alias []= store
58
58
 
59
59
  # Retrieves a `value` by `key`
60
60
  # @param [Object] key the storage key
@@ -68,7 +68,7 @@ class TimedLRU
68
68
  node.value
69
69
  end
70
70
  end
71
- alias_method :[], :fetch
71
+ alias [] fetch
72
72
 
73
73
  # Deletes by `key`
74
74
  # @param [Object] key the storage key
@@ -82,38 +82,35 @@ class TimedLRU
82
82
 
83
83
  private
84
84
 
85
- def compact!
86
- while @hash.size > max_size
87
- remove(@tail)
88
- end
89
-
90
- while ttl && @tail.expires_at < Time.now.to_i
91
- remove(@tail)
92
- end
93
- end
94
-
95
- def remove(node)
96
- @hash.delete(node.key)
97
- left, right = node.left, node.right
98
- left.nil? ? @head = right : left.right = right
99
- right.nil? ? @tail = left : right.left = left
100
- node
101
- end
85
+ def compact!
86
+ remove(@tail) while @hash.size > max_size
87
+ remove(@tail) while ttl && @tail.expires_at < Time.now.to_f
88
+ end
102
89
 
103
- def touch(node)
104
- node.expires_at = Time.now.to_i + ttl if ttl
105
- return if node == @head
90
+ def remove(node)
91
+ @hash.delete(node.key)
92
+ left = node.left
93
+ right = node.right
94
+ left.nil? ? @head = right : left.right = right
95
+ right.nil? ? @tail = left : right.left = left
96
+ node
97
+ end
106
98
 
107
- left, right = node.left, node.right
108
- node.left, node.right = nil, @head
109
- @head.left = node if @head
99
+ def touch(node)
100
+ node.expires_at = Time.now.to_f + ttl if ttl
101
+ return if node == @head
110
102
 
111
- left.right = right if left
112
- right.left = left if right
103
+ left = node.left
104
+ right = node.right
105
+ node.left = nil
106
+ node.right = @head
107
+ @head.left = node if @head
113
108
 
114
- @tail = left if @tail == node
115
- @head = node
116
- @tail = @head unless @tail
117
- end
109
+ left.right = right if left
110
+ right.left = left if right
118
111
 
112
+ @tail = left if @tail == node
113
+ @head = node
114
+ @tail ||= @head
115
+ end
119
116
  end
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,3 @@
1
1
  require 'bundler/setup'
2
2
  require 'rspec'
3
3
  require 'timed_lru'
4
-
@@ -1,16 +1,18 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe TimedLRU do
4
-
5
4
  subject { described_class.new max_size: 4 }
6
5
 
7
6
  def full_chain
8
7
  return [] unless head
9
8
 
10
9
  res = [head]
11
- while curr = res.last.right
12
- expect(curr.left).to eq(res.last)
13
- res << curr
10
+ loop do
11
+ current = res.last.right
12
+ break unless current
13
+
14
+ expect(current.left).to eq(res.last)
15
+ res << current
14
16
  end
15
17
  expect(head.left).to be_nil
16
18
  expect(tail.right).to be_nil
@@ -30,16 +32,18 @@ describe TimedLRU do
30
32
  subject.instance_variable_get(:@tail)
31
33
  end
32
34
 
33
- describe "defaults" do
35
+ describe 'defaults' do
34
36
  subject { described_class.new }
35
37
 
36
38
  describe '#max_size' do
37
39
  subject { super().max_size }
40
+
38
41
  it { is_expected.to be(100) }
39
42
  end
40
43
 
41
44
  describe '#ttl' do
42
45
  subject { super().ttl }
46
+
43
47
  it { is_expected.to be_nil }
44
48
  end
45
49
 
@@ -51,103 +55,100 @@ describe TimedLRU do
51
55
  it { is_expected.to respond_to(:each_key) }
52
56
  end
53
57
 
54
- describe "init" do
58
+ describe 'init' do
55
59
  subject { described_class.new max_size: 25, ttl: 120, thread_safe: false }
56
60
 
57
61
  describe '#max_size' do
58
62
  subject { super().max_size }
63
+
59
64
  it { is_expected.to be(25) }
60
65
  end
61
66
 
62
67
  describe '#ttl' do
63
68
  subject { super().ttl }
64
- it { is_expected.to be(120) }
69
+
70
+ it { is_expected.to eq(120.0) }
65
71
  end
66
- it { is_expected.to be_a(described_class::ThreadUnsafe) }
67
72
 
68
- it 'should assert correct option values' do
69
- expect { described_class.new(max_size: "X") }.to raise_error(ArgumentError)
73
+ it { is_expected.to be_a(described_class::ThreadUnsafe) }
74
+
75
+ it 'asserts correct option values' do
76
+ expect { described_class.new(max_size: 'X') }.to raise_error(ArgumentError)
70
77
  expect { described_class.new(max_size: -1) }.to raise_error(ArgumentError)
71
78
  expect { described_class.new(max_size: 0) }.to raise_error(ArgumentError)
72
79
 
73
- expect { described_class.new(ttl: "X") }.to raise_error(ArgumentError)
80
+ expect { described_class.new(ttl: 'X') }.to raise_error(ArgumentError)
74
81
  expect { described_class.new(ttl: true) }.to raise_error(TypeError)
75
82
  expect { described_class.new(ttl: 0) }.to raise_error(ArgumentError)
76
83
  end
77
84
  end
78
85
 
79
- describe "storing" do
80
-
81
- it "should set head + tail on first item" do
82
- expect {
83
- expect(subject.store("a", 1)).to eq(1)
84
- }.to change { chain }.from([]).to(["a"])
86
+ describe 'storing' do
87
+ it 'sets head + tail on first item' do
88
+ expect do
89
+ expect(subject.store('a', 1)).to eq(1)
90
+ end.to change { chain }.from([]).to(['a'])
85
91
  end
86
92
 
87
- it "should shift chain when new items are added" do
88
- subject["a"] = 1
89
- expect { subject["b"] = 2 }.to change { chain }.from(%w|a|).to(%w|b a|)
90
- expect { subject["c"] = 3 }.to change { chain }.to(%w|c b a|)
91
- expect { subject["d"] = 4 }.to change { chain }.to(%w|d c b a|)
93
+ it 'shifts chain when new items are added' do
94
+ subject['a'] = 1
95
+ expect { subject['b'] = 2 }.to change { chain }.from(%w[a]).to(%w[b a])
96
+ expect { subject['c'] = 3 }.to change { chain }.to(%w[c b a])
97
+ expect { subject['d'] = 4 }.to change { chain }.to(%w[d c b a])
92
98
  end
93
99
 
94
- it "should expire LRU items when chain exceeds max size" do
95
- ("a".."d").each {|x| subject[x] = 1 }
96
- expect { subject["e"] = 5 }.to change { chain }.to(%w|e d c b|)
97
- expect { subject["f"] = 6 }.to change { chain }.to(%w|f e d c|)
100
+ it 'expires LRU items when chain exceeds max size' do
101
+ ('a'..'d').each {|x| subject[x] = 1 }
102
+ expect { subject['e'] = 5 }.to change { chain }.to(%w[e d c b])
103
+ expect { subject['f'] = 6 }.to change { chain }.to(%w[f e d c])
98
104
  end
99
105
 
100
- it "should update items" do
101
- ("a".."d").each {|x| subject[x] = 1 }
102
- expect { subject["d"] = 2 }.not_to change { chain }
103
- expect { subject["c"] = 2 }.to change { chain }.to(%w|c d b a|)
104
- expect { subject["b"] = 2 }.to change { chain }.to(%w|b c d a|)
105
- expect { subject["a"] = 2 }.to change { chain }.to(%w|a b c d|)
106
+ it 'updates items' do
107
+ ('a'..'d').each {|x| subject[x] = 1 }
108
+ expect { subject['d'] = 2 }.not_to change { chain }
109
+ expect { subject['c'] = 2 }.to change { chain }.to(%w[c d b a])
110
+ expect { subject['b'] = 2 }.to change { chain }.to(%w[b c d a])
111
+ expect { subject['a'] = 2 }.to change { chain }.to(%w[a b c d])
106
112
  end
107
-
108
113
  end
109
114
 
110
- describe "retrieving" do
111
-
112
- it 'should fetch values' do
113
- expect(subject.fetch("a")).to be_nil
114
- expect(subject["a"]).to be_nil
115
- subject["a"] = 1
116
- expect(subject["a"]).to eq(1)
115
+ describe 'retrieving' do
116
+ it 'fetches values' do
117
+ expect(subject.fetch('a')).to be_nil
118
+ expect(subject['a']).to be_nil
119
+ subject['a'] = 1
120
+ expect(subject['a']).to eq(1)
117
121
  end
118
122
 
119
- it 'should renew membership on access' do
120
- ("a".."d").each {|x| subject[x] = 1 }
121
- expect { subject["d"] }.not_to change { chain }
122
- expect { subject["c"] }.to change { chain }.to(%w|c d b a|)
123
- expect { subject["b"] }.to change { chain }.to(%w|b c d a|)
124
- expect { subject["a"] }.to change { chain }.to(%w|a b c d|)
125
- expect { subject["x"] }.not_to change { chain }
123
+ it 'renews membership on access' do
124
+ ('a'..'d').each {|x| subject[x] = 1 }
125
+ expect { subject['d'] }.not_to change { chain }
126
+ expect { subject['c'] }.to change { chain }.to(%w[c d b a])
127
+ expect { subject['b'] }.to change { chain }.to(%w[b c d a])
128
+ expect { subject['a'] }.to change { chain }.to(%w[a b c d])
129
+ expect { subject['x'] }.not_to change { chain }
126
130
  end
127
-
128
131
  end
129
132
 
130
- describe "deleting" do
131
-
132
- it 'should delete an return values' do
133
- expect(subject.delete("a")).to be_nil
134
- subject["a"] = 1
135
- expect(subject.delete("a")).to eq(1)
133
+ describe 'deleting' do
134
+ it 'deletes an return values' do
135
+ expect(subject.delete('a')).to be_nil
136
+ subject['a'] = 1
137
+ expect(subject.delete('a')).to eq(1)
136
138
  end
137
139
 
138
- it 'should re-arrange membership chain' do
139
- ("a".."d").each {|x| subject[x] = 1 }
140
- expect { subject.delete("x") }.not_to change { chain }
141
- expect { subject.delete("c") }.to change { chain }.to(%w|d b a|)
142
- expect { subject.delete("a") }.to change { chain }.to(%w|d b|)
143
- expect { subject.delete("d") }.to change { chain }.to(%w|b|)
144
- expect { subject.delete("b") }.to change { subject.size }.from(1).to(0)
140
+ it 're-arranges membership chain' do
141
+ ('a'..'d').each {|x| subject[x] = 1 }
142
+ expect { subject.delete('x') }.not_to change { chain }
143
+ expect { subject.delete('c') }.to change { chain }.to(%w[d b a])
144
+ expect { subject.delete('a') }.to change { chain }.to(%w[d b])
145
+ expect { subject.delete('d') }.to change { chain }.to(%w[b])
146
+ expect { subject.delete('b') }.to change(subject, :size).from(1).to(0)
145
147
  end
146
-
147
148
  end
148
149
 
149
- describe "TTL expiration" do
150
- subject { described_class.new max_size: 4, ttl: 60 }
150
+ describe 'TTL expiration' do
151
+ subject { described_class.new max_size: 4, ttl: 60 }
151
152
 
152
153
  def in_past(ago)
153
154
  allow(Time).to receive_messages now: (Time.now - ago)
@@ -156,37 +157,35 @@ describe TimedLRU do
156
157
  allow(Time).to receive(:now).and_call_original
157
158
  end
158
159
 
159
- it 'should expire on access' do
160
+ it 'expires on access' do
160
161
  in_past(70) do
161
- subject["a"] = 1
162
- expect(chain).to eq(%w|a|)
162
+ subject['a'] = 1
163
+ expect(chain).to eq(%w[a])
163
164
  end
164
165
 
165
166
  in_past(50) do
166
- subject["b"] = 2
167
- expect(chain).to eq(%w|b a|)
167
+ subject['b'] = 2
168
+ expect(chain).to eq(%w[b a])
168
169
  end
169
170
 
170
- subject["c"] = 3
171
- expect(chain).to eq(%w|c b|)
171
+ subject['c'] = 3
172
+ expect(chain).to eq(%w[c b])
172
173
  end
173
174
 
174
- it 'should renew expiration on access' do
175
+ it 'renews expiration on access' do
175
176
  in_past(70) do
176
- subject["a"] = 1
177
- subject["b"] = 2
178
- expect(chain).to eq(%w|b a|)
177
+ subject['a'] = 1
178
+ subject['b'] = 2
179
+ expect(chain).to eq(%w[b a])
179
180
  end
180
181
 
181
182
  in_past(50) do
182
- expect(subject["a"]).to eq(1)
183
- expect(chain).to eq(%w|a b|)
183
+ expect(subject['a']).to eq(1)
184
+ expect(chain).to eq(%w[a b])
184
185
  end
185
186
 
186
- subject["c"] = 3
187
- expect(chain).to eq(%w|c a|)
187
+ subject['c'] = 3
188
+ expect(chain).to eq(%w[c a])
188
189
  end
189
-
190
190
  end
191
-
192
191
  end
data/timed_lru.gemspec CHANGED
@@ -1,22 +1,22 @@
1
1
  Gem::Specification.new do |s|
2
- s.required_ruby_version = '>= 2.2.0'
2
+ s.required_ruby_version = '>= 2.7'
3
3
 
4
4
  s.name = File.basename(__FILE__, '.gemspec')
5
- s.summary = "Timed LRU"
6
- s.description = "Thread-safe LRU implementation with (optional) TTL and constant time operations"
7
- s.version = "0.3.2"
5
+ s.summary = 'Timed LRU'
6
+ s.description = 'Thread-safe LRU implementation with (optional) TTL and constant time operations'
7
+ s.version = '0.5.1'
8
8
 
9
- s.authors = ["Black Square Media"]
10
- s.email = "info@blacksquaremedia.com"
11
- s.homepage = "https://github.com/bsm/timed_lru"
9
+ s.authors = ['Black Square Media']
10
+ s.email = 'info@blacksquaremedia.com'
11
+ s.homepage = 'https://github.com/bsm/timed_lru'
12
+ s.license = 'Apache-2.0'
12
13
 
13
14
  s.require_path = 'lib'
14
15
  s.files = `git ls-files`.split("\n")
15
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
16
 
17
- s.add_development_dependency "rake"
18
- s.add_development_dependency "bundler"
19
- s.add_development_dependency "rspec"
20
- s.add_development_dependency "yard"
21
- s.add_development_dependency "redcarpet"
17
+ s.add_development_dependency 'bundler'
18
+ s.add_development_dependency 'rake'
19
+ s.add_development_dependency 'rspec'
20
+ s.add_development_dependency 'rubocop-bsm'
21
+ s.metadata['rubygems_mfa_required'] = 'true'
22
22
  end
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timed_lru
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Black Square Media
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-21 00:00:00.000000000 Z
11
+ date: 2022-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: rake
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: bundler
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -39,7 +25,7 @@ dependencies:
39
25
  - !ruby/object:Gem::Version
40
26
  version: '0'
41
27
  - !ruby/object:Gem::Dependency
42
- name: rspec
28
+ name: rake
43
29
  requirement: !ruby/object:Gem::Requirement
44
30
  requirements:
45
31
  - - ">="
@@ -53,7 +39,7 @@ dependencies:
53
39
  - !ruby/object:Gem::Version
54
40
  version: '0'
55
41
  - !ruby/object:Gem::Dependency
56
- name: yard
42
+ name: rspec
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
45
  - - ">="
@@ -67,7 +53,7 @@ dependencies:
67
53
  - !ruby/object:Gem::Version
68
54
  version: '0'
69
55
  - !ruby/object:Gem::Dependency
70
- name: redcarpet
56
+ name: rubocop-bsm
71
57
  requirement: !ruby/object:Gem::Requirement
72
58
  requirements:
73
59
  - - ">="
@@ -87,20 +73,23 @@ executables: []
87
73
  extensions: []
88
74
  extra_rdoc_files: []
89
75
  files:
76
+ - ".github/workflows/ruby.yml"
90
77
  - ".gitignore"
91
- - ".travis.yml"
78
+ - ".rubocop.yml"
92
79
  - Gemfile
93
80
  - Gemfile.lock
81
+ - LICENSE
94
82
  - README.md
95
83
  - Rakefile
96
84
  - lib/timed_lru.rb
97
- - spec/coverage_helper.rb
98
85
  - spec/spec_helper.rb
99
86
  - spec/timed_lru_spec.rb
100
87
  - timed_lru.gemspec
101
88
  homepage: https://github.com/bsm/timed_lru
102
- licenses: []
103
- metadata: {}
89
+ licenses:
90
+ - Apache-2.0
91
+ metadata:
92
+ rubygems_mfa_required: 'true'
104
93
  post_install_message:
105
94
  rdoc_options: []
106
95
  require_paths:
@@ -109,15 +98,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
109
98
  requirements:
110
99
  - - ">="
111
100
  - !ruby/object:Gem::Version
112
- version: 2.2.0
101
+ version: '2.7'
113
102
  required_rubygems_version: !ruby/object:Gem::Requirement
114
103
  requirements:
115
104
  - - ">="
116
105
  - !ruby/object:Gem::Version
117
106
  version: '0'
118
107
  requirements: []
119
- rubyforge_project:
120
- rubygems_version: 2.6.14
108
+ rubygems_version: 3.3.7
121
109
  signing_key:
122
110
  specification_version: 4
123
111
  summary: Timed LRU
data/.travis.yml DELETED
@@ -1,8 +0,0 @@
1
- language: ruby
2
- script: bundle exec rake coverage
3
- rvm:
4
- - 2.2
5
- - 2.3
6
- - 2.4
7
- gemfile:
8
- - Gemfile
@@ -1,5 +0,0 @@
1
- require 'coveralls'
2
-
3
- # Enable coverage
4
- Coveralls.wear!
5
-