persistent-cache 0.4.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1c8b77545d0f4b605d15137012b0fcaf1f849032
4
+ data.tar.gz: e2258f5db2125f20ca38253e8f6fd51065783aca
5
+ SHA512:
6
+ metadata.gz: 6282dbd4b4916eedf1a97dbdb0d6f0a2c28422a7f6f0191c29e112b6a0b76e5daa42d22b2a0e8994b7eebce4333e877ec79fc8d8e927f9d9edd6985302ada000
7
+ data.tar.gz: 03eaed66ba58ca33230093b2b892be3f9bf889e354f610ebdd9e5a823f9fd816d1cb111c151e275101b45ba5dd680114100aed28f46a3e7350395f9ed581442a
@@ -0,0 +1 @@
1
+ persistent-cache
@@ -0,0 +1 @@
1
+ ruby-2.3.0
data/README.md CHANGED
@@ -6,7 +6,7 @@ Values in the cache have a default freshness period of 15465600 ms. This can be
6
6
 
7
7
  Note that when using a back-end that requires marshalling (e.g. sqlite) the string encoding for []= and [] needs to be the same (e.g. UTF-8, US-ASCII, etc.) If the coding does not match, [] will not be able to find the entry during lookup and will return nil. See the section on 'Encoding' below for more detail.
8
8
 
9
- This gem is sponsored by Hetzner (Pty) Ltd - http://hetzner.co.za
9
+ This gem was sponsored by Hetzner (Pty) Ltd - http://hetzner.co.za
10
10
 
11
11
  ## StorageSQLite
12
12
 
@@ -113,10 +113,10 @@ If you'd like persistent cache to rather store keys using an encoding of your pr
113
113
 
114
114
  Please send feedback and comments to the authors at:
115
115
 
116
- Wynand van Dyk <wynand.van.dyk@hetzner.co.za>
117
-
118
116
  Ernst van Graan <ernst.van.graan@hetzner.co.za>
119
117
 
118
+ Wynand van Dyk <wynand.van.dyk@hetzner.co.za>
119
+
120
120
  1. Fork it
121
121
  2. Create your feature branch (`git checkout -b my-new-feature`)
122
122
  3. Commit your changes (`git commit -am 'Added some feature'`)
@@ -1,8 +1,8 @@
1
1
  require "persistent-cache/version"
2
2
  require "sqlite3"
3
- require "persistent-cache/storage/storage_sq_lite"
4
- require "persistent-cache/storage/storage_directory"
5
- require "persistent-cache/storage/storage_ram"
3
+ require "persistent-cache/storage_sqlite"
4
+ require "persistent-cache/storage_directory"
5
+ require "persistent-cache/storage_ram"
6
6
 
7
7
  module Persistent
8
8
  class Cache
@@ -23,7 +23,7 @@ module Persistent
23
23
 
24
24
  @storage = StorageSQLite.new(storage_details) if storage == STORAGE_SQLITE
25
25
  @storage = StorageDirectory.new(storage_details) if storage == STORAGE_DIRECTORY
26
- @storage = StorageRAM.new if storage == STORAGE_RAM
26
+ @storage = StorageRAM.new(storage_details) if storage == STORAGE_RAM
27
27
  @fresh = fresh
28
28
  @storage_details = storage_details
29
29
 
@@ -1,5 +1,3 @@
1
1
  module Persistent
2
- class Cache
3
- VERSION = "0.4.1"
4
- end
2
+ VERSION = "1.0.0"
5
3
  end
@@ -1,9 +1,11 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/persistent-cache/version', __FILE__)
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'persistent-cache/version'
3
5
 
4
6
  Gem::Specification.new do |gem|
5
- gem.authors = ["Wynand van Dyk", "Ernst van Graan"]
6
- gem.email = ["wvd@hetzner.co.za", "ernst.van.graan@hetzner.co.za"]
7
+ gem.authors = ["Ernst van Graan", "Wynand van Dyk"]
8
+ gem.email = ["ernst.van.graan@hetzner.co.za", "wvd@hetzner.co.za"]
7
9
  gem.description = %q{Persistent Cache using a pluggable back-end (e.g. SQLite)}
8
10
  gem.summary = %q{Persistent Cache has a default freshness threshold of 179 days after which entries are no longer returned}
9
11
  gem.homepage = ""
@@ -13,11 +15,14 @@ Gem::Specification.new do |gem|
13
15
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
16
  gem.name = "persistent-cache"
15
17
  gem.require_paths = ["lib"]
16
- gem.version = Persistent::Cache::VERSION
18
+ gem.version = Persistent::VERSION
17
19
  gem.add_development_dependency 'rspec', '2.12.0'
18
20
  gem.add_development_dependency 'simplecov'
19
21
  gem.add_development_dependency 'simplecov-rcov'
20
- gem.add_development_dependency 'debugger'
21
- gem.add_dependency 'sqlite3', '1.3.10'
22
+ gem.add_development_dependency 'byebug'
22
23
  gem.add_dependency 'eh'
24
+ gem.add_dependency "persistent-cache-storage-api"
25
+ gem.add_dependency "persistent-cache-storage-sqlite"
26
+ gem.add_dependency "persistent-cache-storage-directory"
27
+ gem.add_dependency "persistent-cache-storage-ram"
23
28
  end
@@ -1,8 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
- require "persistent-cache"
4
- require "persistent-cache/storage/storage_sq_lite"
5
-
6
3
  describe Persistent::Cache do
7
4
  before :each do
8
5
  @db_name = get_database_name
@@ -3,7 +3,11 @@ require 'rspec/mocks'
3
3
  require 'tempfile'
4
4
  require 'simplecov'
5
5
  require 'simplecov-rcov'
6
- require 'debugger'
6
+ require 'byebug'
7
+ require "persistent-cache"
8
+ require "persistent-cache/storage_sqlite"
9
+ require "persistent-cache/storage_directory"
10
+ require "persistent-cache/storage_ram"
7
11
 
8
12
  # This file was generated by the `rspec --init` command. Conventionally, all
9
13
  # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
@@ -1,6 +1,4 @@
1
1
  require 'spec_helper'
2
- require "persistent-cache/storage/storage_directory"
3
- require 'debugger'
4
2
 
5
3
  describe Persistent::StorageDirectory do
6
4
  before :each do
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require "persistent-cache/storage/storage_ram"
3
2
 
4
3
  describe Persistent::StorageRAM do
5
4
  before :each do
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require "persistent-cache/storage/storage_sq_lite"
3
2
 
4
3
  describe Persistent::StorageSQLite do
5
4
  before :each do
metadata CHANGED
@@ -1,21 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: persistent-cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
5
- prerelease:
4
+ version: 1.0.0
6
5
  platform: ruby
7
6
  authors:
8
- - Wynand van Dyk
9
7
  - Ernst van Graan
8
+ - Wynand van Dyk
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2015-08-28 00:00:00.000000000 Z
12
+ date: 2016-04-12 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: rspec
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
18
  - - '='
21
19
  - !ruby/object:Gem::Version
@@ -23,7 +21,6 @@ dependencies:
23
21
  type: :development
24
22
  prerelease: false
25
23
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
24
  requirements:
28
25
  - - '='
29
26
  - !ruby/object:Gem::Version
@@ -31,102 +28,132 @@ dependencies:
31
28
  - !ruby/object:Gem::Dependency
32
29
  name: simplecov
33
30
  requirement: !ruby/object:Gem::Requirement
34
- none: false
35
31
  requirements:
36
- - - ! '>='
32
+ - - ">="
37
33
  - !ruby/object:Gem::Version
38
34
  version: '0'
39
35
  type: :development
40
36
  prerelease: false
41
37
  version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
38
  requirements:
44
- - - ! '>='
39
+ - - ">="
45
40
  - !ruby/object:Gem::Version
46
41
  version: '0'
47
42
  - !ruby/object:Gem::Dependency
48
43
  name: simplecov-rcov
49
44
  requirement: !ruby/object:Gem::Requirement
50
- none: false
51
45
  requirements:
52
- - - ! '>='
46
+ - - ">="
53
47
  - !ruby/object:Gem::Version
54
48
  version: '0'
55
49
  type: :development
56
50
  prerelease: false
57
51
  version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
52
  requirements:
60
- - - ! '>='
53
+ - - ">="
61
54
  - !ruby/object:Gem::Version
62
55
  version: '0'
63
56
  - !ruby/object:Gem::Dependency
64
- name: debugger
57
+ name: byebug
65
58
  requirement: !ruby/object:Gem::Requirement
66
- none: false
67
59
  requirements:
68
- - - ! '>='
60
+ - - ">="
69
61
  - !ruby/object:Gem::Version
70
62
  version: '0'
71
63
  type: :development
72
64
  prerelease: false
73
65
  version_requirements: !ruby/object:Gem::Requirement
74
- none: false
75
66
  requirements:
76
- - - ! '>='
67
+ - - ">="
77
68
  - !ruby/object:Gem::Version
78
69
  version: '0'
79
70
  - !ruby/object:Gem::Dependency
80
- name: sqlite3
71
+ name: eh
81
72
  requirement: !ruby/object:Gem::Requirement
82
- none: false
83
73
  requirements:
84
- - - '='
74
+ - - ">="
85
75
  - !ruby/object:Gem::Version
86
- version: 1.3.10
76
+ version: '0'
87
77
  type: :runtime
88
78
  prerelease: false
89
79
  version_requirements: !ruby/object:Gem::Requirement
90
- none: false
91
80
  requirements:
92
- - - '='
81
+ - - ">="
93
82
  - !ruby/object:Gem::Version
94
- version: 1.3.10
83
+ version: '0'
95
84
  - !ruby/object:Gem::Dependency
96
- name: eh
85
+ name: persistent-cache-storage-api
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: persistent-cache-storage-sqlite
97
100
  requirement: !ruby/object:Gem::Requirement
98
- none: false
99
101
  requirements:
100
- - - ! '>='
102
+ - - ">="
101
103
  - !ruby/object:Gem::Version
102
104
  version: '0'
103
105
  type: :runtime
104
106
  prerelease: false
105
107
  version_requirements: !ruby/object:Gem::Requirement
106
- none: false
107
108
  requirements:
108
- - - ! '>='
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: persistent-cache-storage-directory
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :runtime
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: persistent-cache-storage-ram
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :runtime
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
109
138
  - !ruby/object:Gem::Version
110
139
  version: '0'
111
140
  description: Persistent Cache using a pluggable back-end (e.g. SQLite)
112
141
  email:
113
- - wvd@hetzner.co.za
114
142
  - ernst.van.graan@hetzner.co.za
143
+ - wvd@hetzner.co.za
115
144
  executables: []
116
145
  extensions: []
117
146
  extra_rdoc_files: []
118
147
  files:
119
- - .gitignore
120
- - .rspec
121
- - .rvmrc
148
+ - ".gitignore"
149
+ - ".rspec"
150
+ - ".ruby-gemset"
151
+ - ".ruby-version"
122
152
  - Gemfile
123
153
  - LICENSE
124
154
  - README.md
125
155
  - Rakefile
126
156
  - lib/persistent-cache.rb
127
- - lib/persistent-cache/storage/storage_directory.rb
128
- - lib/persistent-cache/storage/storage_ram.rb
129
- - lib/persistent-cache/storage/storage_sq_lite.rb
130
157
  - lib/persistent-cache/version.rb
131
158
  - persistent-cache.gemspec
132
159
  - spec/persistent-cache_spec.rb
@@ -136,27 +163,26 @@ files:
136
163
  - spec/storage/storage_sqlite_spec.rb
137
164
  homepage: ''
138
165
  licenses: []
166
+ metadata: {}
139
167
  post_install_message:
140
168
  rdoc_options: []
141
169
  require_paths:
142
170
  - lib
143
171
  required_ruby_version: !ruby/object:Gem::Requirement
144
- none: false
145
172
  requirements:
146
- - - ! '>='
173
+ - - ">="
147
174
  - !ruby/object:Gem::Version
148
175
  version: '0'
149
176
  required_rubygems_version: !ruby/object:Gem::Requirement
150
- none: false
151
177
  requirements:
152
- - - ! '>='
178
+ - - ">="
153
179
  - !ruby/object:Gem::Version
154
180
  version: '0'
155
181
  requirements: []
156
182
  rubyforge_project:
157
- rubygems_version: 1.8.28
183
+ rubygems_version: 2.5.1
158
184
  signing_key:
159
- specification_version: 3
185
+ specification_version: 4
160
186
  summary: Persistent Cache has a default freshness threshold of 179 days after which
161
187
  entries are no longer returned
162
188
  test_files:
data/.rvmrc DELETED
@@ -1,48 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
- # development environment upon cd'ing into the directory
5
-
6
- # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
7
- # Only full ruby name is supported here, for short names use:
8
- # echo "rvm use 1.9.3" > .rvmrc
9
- environment_id="ruby-1.9.3-p194@persistent-hash"
10
-
11
- # Uncomment the following lines if you want to verify rvm version per project
12
- # rvmrc_rvm_version="1.14.3 (stable)" # 1.10.1 seams as a safe start
13
- # eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
14
- # echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
15
- # return 1
16
- # }
17
-
18
- # First we attempt to load the desired environment directly from the environment
19
- # file. This is very fast and efficient compared to running through the entire
20
- # CLI and selector. If you want feedback on which environment was used then
21
- # insert the word 'use' after --create as this triggers verbose mode.
22
- if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
23
- && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
24
- then
25
- \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
26
- [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
27
- \. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
28
- else
29
- # If the environment file has not yet been created, use the RVM CLI to select.
30
- rvm --create "$environment_id" || {
31
- echo "Failed to create RVM environment '${environment_id}'."
32
- return 1
33
- }
34
- fi
35
-
36
- # If you use bundler, this might be useful to you:
37
- # if [[ -s Gemfile ]] && {
38
- # ! builtin command -v bundle >/dev/null ||
39
- # builtin command -v bundle | GREP_OPTIONS= \grep $rvm_path/bin/bundle >/dev/null
40
- # }
41
- # then
42
- # printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
43
- # gem install bundler
44
- # fi
45
- # if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
46
- # then
47
- # bundle install | GREP_OPTIONS= \grep -vE '^Using|Your bundle is complete'
48
- # fi
@@ -1,170 +0,0 @@
1
- require 'fileutils'
2
- require 'tempfile'
3
- require 'pathname'
4
-
5
- module Persistent
6
- class StorageDirectory
7
- CACHE_FILE = "cache.gz" unless defined? CACHE_FILE; CACHE_FILE.freeze
8
-
9
- attr_accessor :storage_root
10
-
11
- def initialize(storage_details)
12
- raise ArgumentError.new("Storage details not provided") if storage_details.nil? or storage_details == ""
13
- @storage_root = storage_details
14
- connect_to_database
15
- end
16
-
17
- def connect_to_database
18
- FileUtils.makedirs([@storage_root]) if not File.directory?(@storage_root)
19
- end
20
-
21
- def save_key_value_pair(key, value, timestamp = nil)
22
- prepare_to_store_key_value(key, value, timestamp)
23
- store_key_value(key, value, get_time(timestamp)) if not value.nil?
24
- end
25
-
26
- def lookup_key(key)
27
- validate_key(key)
28
- return [] if not File.exists? compile_value_path(key)
29
- lookup_key_value_timestamp(key)
30
- end
31
-
32
- def delete_entry(key)
33
- validate_key(key)
34
- FileUtils.rm_rf(compile_key_path(key))
35
- end
36
-
37
- def size
38
- count = Dir::glob("#{@storage_root}/**/#{CACHE_FILE}").size
39
- end
40
-
41
- def keys
42
- return [] if size == 0
43
- list_keys_sorted
44
- end
45
-
46
- def clear
47
- keys.each do |key|
48
- delete_entry(key[0])
49
- end
50
- end
51
-
52
- def get_value_path(key)
53
- validate_key(key)
54
-
55
- return nil if not key_cached?(key)
56
-
57
- compile_value_path(key)
58
- end
59
-
60
- def get_value_path_even_when_not_cached(key)
61
- compile_value_path(key)
62
- end
63
-
64
- def key_cached?(key)
65
- # don't read the value here, as it may be very large - rather look whether the key is present
66
- File.exists? compile_key_path(key)
67
- end
68
-
69
- private
70
-
71
- def list_keys_sorted
72
- result = []
73
- append_keys(result).sort
74
- end
75
-
76
- def append_keys(result)
77
- get_key_directories.each do |dir|
78
- result << extract_key_from_directory(dir)
79
- end
80
- result
81
- end
82
-
83
- def get_key_directories
84
- subdirectories = Dir::glob("#{@storage_root}/**/")
85
- #exclude the storage root directory itself
86
- subdirectories[1..-1]
87
- end
88
-
89
- def extract_key_from_directory(dir)
90
- key = dir.match(/#{@storage_root}\/(\w+)\//)[1]
91
- [key]
92
- end
93
-
94
- def compile_key_path(key)
95
- "#{@storage_root}/#{key}"
96
- end
97
-
98
- def compile_value_path(key)
99
- "#{compile_key_path(key)}/#{CACHE_FILE}"
100
- end
101
-
102
- def validate_save_key_value_pair(key, value)
103
- validate_key(key)
104
- raise ArgumentError.new("Only string values allowed") if not value.is_a?(String)
105
- end
106
-
107
- def lookup_key_value_timestamp(key)
108
- result = [[],[]]
109
- data = File.read(compile_value_path(key))
110
- format_value_timestamp(result, data)
111
- end
112
-
113
- def format_value_timestamp(result, data)
114
- result[0][0] = data.lines.to_a[1..-1].join
115
- result[0][1] = data.lines.to_a[0..0].join.split("\n")[0]
116
- result
117
- end
118
-
119
- def validate_key(key)
120
- raise ArgumentError.new("Only string keys allowed") if not key.is_a?(String)
121
- root_path = Pathname.new(File.absolute_path(@storage_root))
122
- key_path = Pathname.new(File.absolute_path(compile_key_path(key)))
123
- relative = key_path.relative_path_from(root_path).to_s
124
- raise ArgumentError.new("key is outside of storage_root scope") if relative.start_with?("..")
125
- raise ArgumentError.new("key is the same as storage_root") if relative == "."
126
- end
127
-
128
- def empty_key_value(key)
129
- FileUtils.makedirs([compile_key_path(key)]) if not File.exists?(compile_key_path(key))
130
- FileUtils.rm_f(compile_value_path(key))
131
- end
132
-
133
- def get_time(timestamp)
134
- timestamp.nil? ? Time.now.to_s : timestamp.to_s
135
- end
136
-
137
- def prepare_to_store_key_value(key, value, timestamp)
138
- validate_save_key_value_pair(key, value)
139
- delete_entry(key)
140
- empty_key_value(key)
141
- end
142
-
143
- def store_key_value(key, value, timestamp)
144
- tempfile = Tempfile.new("store_key_value")
145
- store_value_timestamp_in_file(value, timestamp, tempfile)
146
- sync_cache_value(key, tempfile)
147
- end
148
-
149
- def sync_cache_value(key, tempfile)
150
- target = compile_value_path(key)
151
- FileUtils.rm_f(target)
152
- FileUtils.move(tempfile.path, target)
153
- end
154
-
155
- def store_value_timestamp_in_file(value, timestamp, tempfile)
156
- output = File.open(tempfile, 'a')
157
- write_value_timestamp(output, value, timestamp)
158
- output.close
159
- end
160
-
161
- def write_value_timestamp(output, value, timestamp)
162
- # Have to be explicit about writing to the file. 'puts' collapses newline at the end of the file and
163
- # so does not guarantee exact replication of 'value' on lookup
164
- output.write(timestamp)
165
- output.write("\n")
166
- output.write(value)
167
- output.flush
168
- end
169
- end
170
- end
@@ -1,51 +0,0 @@
1
- require "eh/eh"
2
-
3
- module Persistent
4
- class StorageRAM
5
- attr_accessor :storage
6
-
7
- def initialize()
8
- @storage = {}
9
- end
10
-
11
- def save_key_value_pair(serialized_key, serialized_value, timestamp = nil)
12
- delete_entry(serialized_key)
13
- time_entry = timestamp.nil? ? Time.now.to_s : timestamp.to_s
14
- EH::retry!(:args => [serialized_key, serialized_value, time_entry]) do
15
- @storage[serialized_key] = {:value => serialized_value, :timestamp => time_entry}
16
- end
17
- end
18
-
19
- def lookup_key(serialized_key)
20
- EH::retry!(:args => [serialized_key]) do
21
- return [] if @storage[serialized_key].nil?
22
- [@storage[serialized_key][:value], @storage[serialized_key][:timestamp]]
23
- end
24
- end
25
-
26
- def delete_entry(serialized_key)
27
- EH::retry!(:args => [serialized_key]) do
28
- @storage.delete(serialized_key)
29
- end
30
- end
31
-
32
- def size
33
- EH::retry!(:args => []) do
34
- @storage.size
35
- end
36
- end
37
-
38
- def keys
39
- EH::retry!(:args => []) do
40
- return [] if @storage.keys == []
41
- [@storage.keys]
42
- end
43
- end
44
-
45
- def clear
46
- EH::retry!(:args => []) do
47
- @storage.clear
48
- end
49
- end
50
- end
51
- end
@@ -1,97 +0,0 @@
1
- require "sqlite3"
2
- require "base64"
3
- require "eh/eh"
4
-
5
- module Persistent
6
- class StorageSQLite
7
- DB_TABLE = "key_value" unless defined? DB_TABLE; DB_TABLE.freeze
8
- DB_TIMEOUT = 30000 unless defined? DB_TIMEOUT; DB_TIMEOUT.freeze
9
-
10
- attr_accessor :storage_details
11
- attr_accessor :storage_handler
12
-
13
- def initialize(storage_details)
14
- raise ArgumentError.new("Storage details not provided") if storage_details.nil? or storage_details == ""
15
- @storage_details = storage_details
16
- @storage_handler = connect_to_database
17
- @storage_handler.busy_timeout = 30000
18
- end
19
-
20
- def save_key_value_pair(key, value, timestamp = nil)
21
- delete_entry(key)
22
- time_entry = timestamp.nil? ? Time.now.to_s : timestamp.to_s
23
- EH::retry!(:args => [serialize(key), serialize(value), time_entry]) do
24
- @storage_handler.execute("INSERT INTO #{DB_TABLE} (key, value, timestamp) VALUES(?, ?, ?)",serialize(key), serialize(value), time_entry)
25
- end
26
- end
27
-
28
- def lookup_key(key)
29
- EH::retry!(:args => [serialize(key)]) do
30
- result = @storage_handler.execute("SELECT value, timestamp FROM #{DB_TABLE} WHERE key=?", serialize(key))
31
- !result.nil? && !result.empty? ? [deserialize(result[0][0]), result[0][1]] : nil
32
- end
33
- end
34
-
35
- def delete_entry(key)
36
- EH::retry!(:args => [serialize(key)]) do
37
- @storage_handler.execute("DELETE FROM #{DB_TABLE} WHERE key=?", serialize(key))
38
- end
39
- end
40
-
41
- def size
42
- EH::retry!(:args => []) do
43
- @storage_handler.execute("SELECT value FROM #{DB_TABLE}").size
44
- end
45
- end
46
-
47
- def keys
48
- EH::retry!(:args => []) do
49
- @storage_handler.execute("SELECT key FROM #{DB_TABLE}").collect { |k| deserialize(k[0]) }
50
- end
51
- end
52
-
53
- def clear
54
- EH::retry!(:args => []) do
55
- @storage_handler.execute("DELETE FROM #{DB_TABLE}")
56
- end
57
- end
58
-
59
- private
60
-
61
- def serialize(data)
62
- Base64.encode64(Marshal.dump(data))
63
- end
64
-
65
- def deserialize(data)
66
- Marshal.load(Base64.decode64(data))
67
-
68
- rescue TypeError => ex
69
- Marshal.load(data)
70
- end
71
-
72
- def connect_to_database
73
- File.exists?(@storage_details) ? open_database : create_database
74
- end
75
-
76
- def open_database
77
- EH::retry!(:args => []) do
78
- SQLite3::Database.open(@storage_details)
79
- end
80
- end
81
-
82
- def create_database
83
- EH::retry!(:args => []) do
84
- @storage_handler = SQLite3::Database.new(@storage_details)
85
- create_table
86
- end
87
- @storage_handler
88
- end
89
-
90
- def create_table
91
- EH::retry!(:args => []) do
92
- @storage_handler.execute("CREATE TABLE #{DB_TABLE}(key TEXT PRIMARY KEY, value TEXT, timestamp TEXT)")
93
- end
94
- @storage_handler
95
- end
96
- end
97
- end