solid_cache 0.7.0 → 1.0.0

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: 3bb8fa17755c13f25f2a42794d3be5843de423f484d36d7d4a6c38c0241862c7
4
- data.tar.gz: d71f6c7aad61cb20f1b1f2a077550e63bdb47d37c33b4a498855d9d35427a153
3
+ metadata.gz: 74f6b8bdfea57b8ffbe60b8f525b3907c7278f4b73d07fad2506a41b0884a14c
4
+ data.tar.gz: b3af9a6526d97bcb9b5ac1fd313b9c9cf76551ae75e214479a10fe9b04d678d3
5
5
  SHA512:
6
- metadata.gz: 716d333398fa3efa935668d918e92742df8f7c8056c7ee222a545167085f2fd3b871fb96d3a8d0f6961ea63f1c0e5ac69146c8469985afa3da9913d4f4b0de0f
7
- data.tar.gz: f51f7265604cf7c22ff2cb1ba9d865c0210b3cc54f2e57a0503dca99be015d345feb03d6eecfe1ed8211eba7e049f7aa5c70d647985fa5444d7cc3a393e7c04d
6
+ metadata.gz: b6503fe5c3f9d3158ec64bc054465e48f1479236b05fd3b023f4c7050b8c2c0019a546cae0c494a91da0c7b3e9abf3cc3f8f700b2d6c9853a3832b8a726d750a
7
+ data.tar.gz: 38eec70ef2680b811f9f3baf42e02d5d81d72947c508f45a4ca0cd8d2c1d6d761280e5ec15261c4ca3b94fbdfe20dd1cf96a2cf871255791b41a2d11cfe8aa29
data/README.md CHANGED
@@ -6,13 +6,7 @@ Solid Cache is a database-backed Active Support cache store implementation.
6
6
 
7
7
  Using SQL databases backed by SSDs we can have caches that are much larger and cheaper than traditional memory-only Redis or Memcached backed caches.
8
8
 
9
- ## Usage
10
-
11
- To set Solid Cache as your Rails cache, you should add this to your environment config:
12
-
13
- ```ruby
14
- config.cache_store = :solid_cache_store
15
- ```
9
+ ## Introduction
16
10
 
17
11
  Solid Cache is a FIFO (first in, first out) cache. While this is not as efficient as an LRU cache, it is mitigated by the longer cache lifespan.
18
12
 
@@ -21,7 +15,7 @@ A FIFO cache is much easier to manage:
21
15
  2. We can estimate and control the cache size by comparing the maximum and minimum IDs.
22
16
  3. By deleting from one end of the table and adding at the other end we can avoid fragmentation (on MySQL at least).
23
17
 
24
- ### Installation
18
+ ## Installation
25
19
  Add this line to your application's `Gemfile`:
26
20
 
27
21
  ```ruby
@@ -38,13 +32,69 @@ Or install it yourself as:
38
32
  $ gem install solid_cache
39
33
  ```
40
34
 
41
- Add the migration to your app:
35
+ #### Cache database configuration
36
+
37
+ The default installation of Solid Cache expects a database named `cache` in `database.yml`. It should
38
+ have it's own connection pool to avoid mixing cache queries in other transactions.
39
+
40
+ You can use the primary database for your cache like this:
41
+
42
+ ```yaml
43
+ # config/database.yml
44
+ production:
45
+ primary: &production_primary
46
+ ...
47
+ cache:
48
+ <<: *production_primary
49
+ ```
50
+
51
+ Or a separate database like this:
52
+
53
+ ```yaml
54
+ production:
55
+ primary:
56
+ ...
57
+ cache:
58
+ database: cache_development
59
+ host: 127.0.0.1
60
+ migrations_paths: "db/cache/migrate"
61
+ ```
62
+
63
+ #### Install Solid Cache
64
+
65
+ Now, you need to install the necessary migrations and configure the cache store. You can do both at once using the provided generator:
66
+
67
+ ```bash
68
+ # If using the primary database
69
+ $ bin/rails generate solid_cache:install
70
+
71
+ # Or if using a dedicated database
72
+ $ DATABASE=cache bin/rails generate solid_cache:install
73
+ ```
74
+
75
+ This will set solid_cache as the cache store in production, and will copy the optional configuration file and the required migration over to your app.
76
+
77
+ Alternatively, you can add only the migration to your app:
42
78
 
43
79
  ```bash
44
- $ bin/rails solid_cache:install:migrations
80
+ # If using the primary database
81
+ $ bin/rails generate solid_cache:install:migrations
82
+
83
+ # Or if using a dedicated database
84
+ $ DATABASE=cache bin/rails generate solid_cache:install:migrations
85
+ ```
86
+
87
+ And set Solid Cache as your application's cache store backend manually, in your environment config:
88
+
89
+ ```ruby
90
+ # config/environments/production.rb
91
+ config.cache_store = :solid_cache_store
45
92
  ```
46
93
 
47
- Then run it:
94
+ #### Run migrations
95
+
96
+ Finally, you need to run the migrations:
97
+
48
98
  ```bash
49
99
  $ bin/rails db:migrate
50
100
  ```
@@ -104,7 +154,9 @@ There are three options that can be set on the engine:
104
154
 
105
155
  - `executor` - the [Rails executor](https://guides.rubyonrails.org/threading_and_code_execution.html#executor) used to wrap asynchronous operations, defaults to the app executor
106
156
  - `connects_to` - a custom connects to value for the abstract `SolidCache::Record` active record model. Required for sharding and/or using a separate cache database to the main app. This will overwrite any value set in `config/solid_cache.yml`
107
- - `size_estimate_samples` - if `max_size` is set on the cache, the number of the samples used to estimates the size
157
+ - `size_estimate_samples` - if `max_size` is set on the cache, the number of the samples used to estimate the size.
158
+ - `encrypted` - whether cache values should be encrypted (see [Enabling encryption](#enabling-encryption))
159
+ - `encryption_context_properties` - custom encryption context properties
108
160
 
109
161
  These can be set in your Rails configuration:
110
162
 
@@ -150,46 +202,6 @@ Only triggering expiry when we write means that if the cache is idle, the backgr
150
202
 
151
203
  If you want the cache expiry to be run in a background job instead of a thread, you can set `expiry_method` to `:job`. This will enqueue a `SolidCache::ExpiryJob`.
152
204
 
153
- ### Using a dedicated cache database
154
-
155
- Add database configuration to database.yml, e.g.:
156
-
157
- ```
158
- development:
159
- cache:
160
- database: cache_development
161
- host: 127.0.0.1
162
- migrations_paths: "db/cache/migrate"
163
- ```
164
-
165
- Create database:
166
- ```
167
- $ bin/rails db:create
168
- ```
169
-
170
- Install migrations:
171
- ```
172
- $ bin/rails solid_cache:install:migrations
173
- ```
174
-
175
- Move migrations to custom migrations folder:
176
- ```
177
- $ mkdir -p db/cache/migrate
178
- $ mv db/migrate/*.solid_cache.rb db/cache/migrate
179
- ```
180
-
181
- Set the engine configuration to point to the new database:
182
- ```yaml
183
- # config/solid_cache.yml
184
- production:
185
- database: cache
186
- ```
187
-
188
- Run migrations:
189
- ```
190
- $ bin/rails db:migrate
191
- ```
192
-
193
205
  ### Sharding the cache
194
206
 
195
207
  Solid Cache uses the [Maglev](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/44824.pdf) consistent hashing scheme to shard the cache across multiple databases.
@@ -223,14 +235,42 @@ production:
223
235
 
224
236
  ### Enabling encryption
225
237
 
226
- Add this to an initializer:
238
+ To encrypt the cache values, you can add set the encrypt property.
227
239
 
240
+ ```yaml
241
+ # config/solid_cache.yml
242
+ production:
243
+ encrypt: true
244
+ ```
245
+ or
228
246
  ```ruby
229
- ActiveSupport.on_load(:solid_cache_entry) do
230
- encrypts :value
231
- end
247
+ # application.rb
248
+ config.solid_cache.encrypt = true
232
249
  ```
233
250
 
251
+ You will need to set up your application to (use Active Record Encryption)[https://guides.rubyonrails.org/active_record_encryption.html].
252
+
253
+ Solid Cache by default uses a custom encryptor and message serializer that are optimised for it.
254
+
255
+ Firstly it disabled compression with the encryptor `ActiveRecord::Encryption::Encryptor.new(compress: false)` - the cache already compresses the data.
256
+ Secondly it uses `ActiveRecord::Encryption::MessagePackMessageSerializer.new` as the serializer. This serializer can only be used for binary columns,
257
+ but can store about 40% more data than the standard serializer.
258
+
259
+ You can choose your own context properties instead if you prefer:
260
+
261
+ ```ruby
262
+ # application.rb
263
+ config.solid_cache.encryption_context_properties = {
264
+ encryptor: ActiveRecord::Encryption::Encryptor.new,
265
+ message_serializer: ActiveRecord::Encryption::MessageSerializer.new
266
+ }
267
+ ```
268
+
269
+ **Note**
270
+
271
+ Encryption currently does not work for PostgreSQL, as Rails does not yet support encrypting binary columns for it.
272
+ See https://github.com/rails/rails/pull/52650.
273
+
234
274
  ### Index size limits
235
275
  The Solid Cache migrations try to create an index with 1024 byte entries. If that is too big for your database, you should:
236
276
 
data/Rakefile CHANGED
@@ -15,7 +15,9 @@ def run_without_aborting(*tasks)
15
15
 
16
16
  tasks.each do |task|
17
17
  Rake::Task[task].invoke
18
- rescue Exception
18
+ rescue Exception => e
19
+ puts e.message
20
+ puts e.backtrace
19
21
  errors << task
20
22
  end
21
23
 
@@ -23,7 +25,7 @@ def run_without_aborting(*tasks)
23
25
  end
24
26
 
25
27
  def configs
26
- [ :default, :connects_to, :database, :no_database, :shards, :unprepared_statements ]
28
+ [ :default, :connects_to, :database, :encrypted, :encrypted_custom, :no_database, :shards, :unprepared_statements ]
27
29
  end
28
30
 
29
31
  task :test do
@@ -34,6 +36,11 @@ end
34
36
  configs.each do |config|
35
37
  namespace :test do
36
38
  task config do
39
+ if config.to_s.start_with?("encrypted") && ENV["TARGET_DB"] == "postgres"
40
+ puts "Skipping encrypted tests on PostgreSQL as binary encrypted columns are not supported by Rails yet"
41
+ next
42
+ end
43
+
37
44
  if config == :default
38
45
  sh("bin/rails test")
39
46
  else
@@ -42,3 +49,5 @@ configs.each do |config|
42
49
  end
43
50
  end
44
51
  end
52
+
53
+ task default: [:test]
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidCache
4
+ class Entry
5
+ module Encryption
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ if SolidCache.configuration.encrypt?
10
+ encrypts :value, **SolidCache.configuration.encryption_context_properties
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -2,41 +2,45 @@
2
2
 
3
3
  module SolidCache
4
4
  class Entry < Record
5
- include Expiration, Size
5
+ include Encryption, Expiration, Size
6
6
 
7
7
  # The estimated cost of an extra row in bytes, including fixed size columns, overhead, indexes and free space
8
8
  # Based on experimentation on SQLite, MySQL and Postgresql.
9
9
  # A bit high for SQLite (more like 90 bytes), but about right for MySQL/Postgresql.
10
10
  ESTIMATED_ROW_OVERHEAD = 140
11
+
12
+ # Assuming MessagePack serialization
13
+ ESTIMATED_ENCRYPTION_OVERHEAD = 170
14
+
11
15
  KEY_HASH_ID_RANGE = -(2**63)..(2**63 - 1)
12
16
 
13
17
  class << self
14
18
  def write(key, value)
15
- upsert_all_no_query_cache([ { key: key, value: value } ])
19
+ write_multi([ { key: key, value: value } ])
16
20
  end
17
21
 
18
22
  def write_multi(payloads)
19
- upsert_all_no_query_cache(payloads)
23
+ without_query_cache do
24
+ upsert_all \
25
+ add_key_hash_and_byte_size(payloads),
26
+ unique_by: upsert_unique_by, on_duplicate: :update, update_only: [ :key, :value, :byte_size ]
27
+ end
20
28
  end
21
29
 
22
30
  def read(key)
23
- result = select_all_no_query_cache(get_sql, key_hash_for(key)).first
24
- result[1] if result&.first == key
31
+ read_multi([key])[key]
25
32
  end
26
33
 
27
34
  def read_multi(keys)
28
- key_hashes = keys.map { |key| key_hash_for(key) }
29
- results = select_all_no_query_cache(get_all_sql(key_hashes), key_hashes).to_h
30
- results.except!(results.keys - keys)
31
- end
32
-
33
- def delete_by_key(key)
34
- delete_no_query_cache(:key_hash, key_hash_for(key)) > 0
35
+ without_query_cache do
36
+ find_by_sql([select_sql(keys), *key_hashes_for(keys)]).pluck(:key, :value).to_h
37
+ end
35
38
  end
36
39
 
37
- def delete_multi(keys)
38
- serialized_keys = keys.map { |key| key_hash_for(key) }
39
- delete_no_query_cache(:key_hash, serialized_keys)
40
+ def delete_by_key(*keys)
41
+ without_query_cache do
42
+ where(key_hash: key_hashes_for(keys)).delete_all
43
+ end
40
44
  end
41
45
 
42
46
  def clear_truncate
@@ -44,12 +48,14 @@ module SolidCache
44
48
  end
45
49
 
46
50
  def clear_delete
47
- in_batches.delete_all
51
+ without_query_cache do
52
+ in_batches.delete_all
53
+ end
48
54
  end
49
55
 
50
56
  def lock_and_write(key, &block)
51
57
  transaction do
52
- uncached do
58
+ without_query_cache do
53
59
  result = lock.where(key_hash: key_hash_for(key)).pick(:key, :value)
54
60
  new_value = block.call(result&.first == key ? result[1] : nil)
55
61
  write(key, new_value) if new_value
@@ -59,33 +65,12 @@ module SolidCache
59
65
  end
60
66
 
61
67
  def id_range
62
- uncached do
68
+ without_query_cache do
63
69
  pick(Arel.sql("max(id) - min(id) + 1")) || 0
64
70
  end
65
71
  end
66
72
 
67
73
  private
68
- def upsert_all_no_query_cache(payloads)
69
- args = [ self.all,
70
- connection_for_insert_all,
71
- add_key_hash_and_byte_size(payloads) ].compact
72
- options = { unique_by: upsert_unique_by,
73
- on_duplicate: :update,
74
- update_only: upsert_update_only }
75
- insert_all = ActiveRecord::InsertAll.new(*args, **options)
76
- sql = connection.build_insert_sql(ActiveRecord::InsertAll::Builder.new(insert_all))
77
-
78
- message = +"#{self} "
79
- message << "Bulk " if payloads.many?
80
- message << "Upsert"
81
- # exec_query_method does not clear the query cache, exec_insert_all does
82
- connection.send exec_query_method, sql, message
83
- end
84
-
85
- def connection_for_insert_all
86
- Rails.version >= "7.2" ? connection : nil
87
- end
88
-
89
74
  def add_key_hash_and_byte_size(payloads)
90
75
  payloads.map do |payload|
91
76
  payload.dup.tap do |payload|
@@ -95,73 +80,42 @@ module SolidCache
95
80
  end
96
81
  end
97
82
 
98
- def exec_query_method
99
- connection.respond_to?(:internal_exec_query) ? :internal_exec_query : :exec_query
100
- end
101
-
102
83
  def upsert_unique_by
103
84
  connection.supports_insert_conflict_target? ? :key_hash : nil
104
85
  end
105
86
 
106
- def upsert_update_only
107
- [ :key, :value, :byte_size ]
108
- end
109
-
110
- def get_sql
111
- @get_sql ||= build_sql(where(key_hash: 1).select(:key, :value))
87
+ def select_sql(keys)
88
+ @get_sql ||= {}
89
+ @get_sql[keys.count] ||= \
90
+ where(key_hash: [ "1111", "2222" ])
91
+ .select(:key, :value)
92
+ .to_sql
93
+ .gsub("1111, 2222", (["?"] * keys.count).join(", "))
112
94
  end
113
95
 
114
- def get_all_sql(key_hashes)
115
- @get_all_sql ||= {}
116
- @get_all_sql[key_hashes.count] ||= build_sql(where(key_hash: key_hashes).select(:key, :value))
96
+ def key_hash_for(key)
97
+ # Need to unpack this as a signed integer - Postgresql and SQLite don't support unsigned integers
98
+ Digest::SHA256.digest(key.to_s).unpack("q>").first
117
99
  end
118
100
 
119
- def build_sql(relation)
120
- collector = Arel::Collectors::Composite.new(
121
- Arel::Collectors::SQLString.new,
122
- Arel::Collectors::Bind.new,
123
- )
124
-
125
- connection.visitor.compile(relation.arel.ast, collector)[0]
101
+ def key_hashes_for(keys)
102
+ keys.map { |key| key_hash_for(key) }
126
103
  end
127
104
 
128
- def select_all_no_query_cache(query, values)
129
- uncached do
130
- if connection.prepared_statements?
131
- result = connection.select_all(sanitize_sql(query), "#{name} Load", Array(values), preparable: true)
132
- else
133
- result = connection.select_all(sanitize_sql([ query, *values ]), "#{name} Load", Array(values), preparable: false)
134
- end
135
-
136
- result.cast_values(SolidCache::Entry.attribute_types)
137
- end
105
+ def byte_size_for(payload)
106
+ payload[:key].to_s.bytesize + payload[:value].to_s.bytesize + estimated_row_overhead
138
107
  end
139
108
 
140
- def delete_no_query_cache(attribute, values)
141
- uncached do
142
- relation = where(attribute => values)
143
- sql = connection.to_sql(relation.arel.compile_delete(relation.table[primary_key]))
144
-
145
- # exec_delete does not clear the query cache
146
- if connection.prepared_statements?
147
- connection.exec_delete(sql, "#{name} Delete All", Array(values))
148
- else
149
- connection.exec_delete(sql, "#{name} Delete All")
150
- end
109
+ def estimated_row_overhead
110
+ if SolidCache.configuration.encrypt?
111
+ ESTIMATED_ROW_OVERHEAD + ESTIMATED_ENCRYPTION_OVERHEAD
112
+ else
113
+ ESTIMATED_ROW_OVERHEAD
151
114
  end
152
115
  end
153
116
 
154
- def to_binary(key)
155
- ActiveModel::Type::Binary.new.serialize(key)
156
- end
157
-
158
- def key_hash_for(key)
159
- # Need to unpack this as a signed integer - Postgresql and SQLite don't support unsigned integers
160
- Digest::SHA256.digest(key.to_s).unpack("q>").first
161
- end
162
-
163
- def byte_size_for(payload)
164
- payload[:key].to_s.bytesize + payload[:value].to_s.bytesize + ESTIMATED_ROW_OVERHEAD
117
+ def without_query_cache(&block)
118
+ uncached(dirties: false, &block)
165
119
  end
166
120
  end
167
121
  end
@@ -0,0 +1,29 @@
1
+ class CreateSolidCacheEntries < ActiveRecord::Migration[7.2]
2
+ def up
3
+ create_table :solid_cache_entries, if_not_exists: true do |t|
4
+ t.binary :key, null: false, limit: 1024
5
+ t.binary :value, null: false, limit: 512.megabytes
6
+ t.datetime :created_at, null: false
7
+ t.integer :key_hash, null: false, limit: 8
8
+ t.integer :byte_size, null: false, limit: 4
9
+
10
+ t.index :key_hash, unique: true
11
+ t.index [:key_hash, :byte_size]
12
+ t.index :byte_size
13
+ end
14
+
15
+ raise "column \"key_hash\" does not exist" unless column_exists? :solid_cache_entries, :key_hash
16
+ rescue => e
17
+ if e.message =~ /(column "key_hash" does not exist|no such column: key_hash)/
18
+ raise \
19
+ "Could not find key_hash column on solid_cache_entries, if upgrading from v0.3 or earlier, have you followed " \
20
+ "the steps in https://github.com/rails/solid_cache/blob/main/upgrading_to_version_0.4.x.md?"
21
+ else
22
+ raise
23
+ end
24
+ end
25
+
26
+ def down
27
+ drop_table :solid_cache_entries
28
+ end
29
+ end
@@ -1,5 +1,5 @@
1
1
  default: &default
2
- database: <%%= Rails.env %>
2
+ database: <%= ENV.fetch("DATABASE", "cache") %>
3
3
  store_options:
4
4
  max_age: <%%= 1.week.to_i %>
5
5
  max_size: <%%= 256.megabytes %>
@@ -2,12 +2,15 @@
2
2
 
3
3
  module SolidCache
4
4
  class Configuration
5
- attr_reader :store_options, :connects_to, :executor, :size_estimate_samples
5
+ attr_reader :store_options, :connects_to, :executor, :size_estimate_samples, :encrypt, :encryption_context_properties
6
6
 
7
- def initialize(store_options: {}, database: nil, databases: nil, connects_to: nil, executor: nil, size_estimate_samples: 10_000)
7
+ def initialize(store_options: {}, database: nil, databases: nil, connects_to: nil, executor: nil, encrypt: false, encryption_context_properties: nil, size_estimate_samples: 10_000)
8
8
  @store_options = store_options
9
9
  @size_estimate_samples = size_estimate_samples
10
10
  @executor = executor
11
+ @encrypt = encrypt
12
+ @encryption_context_properties = encryption_context_properties
13
+ @encryption_context_properties ||= default_encryption_context_properties if encrypt?
11
14
  set_connects_to(database: database, databases: databases, connects_to: connects_to)
12
15
  end
13
16
 
@@ -19,6 +22,10 @@ module SolidCache
19
22
  sharded? ? connects_to[:shards].keys : []
20
23
  end
21
24
 
25
+ def encrypt?
26
+ encrypt.present?
27
+ end
28
+
22
29
  private
23
30
  def set_connects_to(database:, databases:, connects_to:)
24
31
  if [database, databases, connects_to].compact.size > 1
@@ -37,5 +44,16 @@ module SolidCache
37
44
  nil
38
45
  end
39
46
  end
47
+
48
+ def default_encryption_context_properties
49
+ require "active_record/encryption/message_pack_message_serializer"
50
+
51
+ {
52
+ # No need to compress, the cache does that already
53
+ encryptor: ActiveRecord::Encryption::Encryptor.new(compress: false),
54
+ # Binary column only serializer that is 40% more efficient than the default MessageSerializer
55
+ message_serializer: ActiveRecord::Encryption::MessagePackMessageSerializer.new
56
+ }
57
+ end
40
58
  end
41
59
  end
@@ -18,6 +18,8 @@ module SolidCache
18
18
 
19
19
  options[:connects_to] = config.solid_cache.connects_to if config.solid_cache.connects_to
20
20
  options[:size_estimate_samples] = config.solid_cache.size_estimate_samples if config.solid_cache.size_estimate_samples
21
+ options[:encrypt] = config.solid_cache.encrypt if config.solid_cache.encrypt
22
+ options[:encryption_context_properties] = config.solid_cache.encryption_context_properties if config.solid_cache.encryption_context_properties
21
23
 
22
24
  SolidCache.configuration = SolidCache::Configuration.new(**options)
23
25
 
@@ -33,5 +35,13 @@ module SolidCache
33
35
  config.after_initialize do
34
36
  Rails.cache.setup! if Rails.cache.is_a?(Store)
35
37
  end
38
+
39
+ config.after_initialize do
40
+ if SolidCache.configuration.encrypt? && SolidCache::Record.connection.adapter_name == "PostgreSQL"
41
+ raise \
42
+ "Cannot enable encryption for Solid Cache: Active Record Encryption does not currently support " \
43
+ "encrypting binary columns on PostgreSQL"
44
+ end
45
+ end
36
46
  end
37
47
  end
@@ -65,13 +65,13 @@ module SolidCache
65
65
 
66
66
  def entry_delete(key)
67
67
  writing_key(key, failsafe: :delete_entry, failsafe_returning: false) do
68
- Entry.delete_by_key(key)
68
+ Entry.delete_by_key(key) > 0
69
69
  end
70
70
  end
71
71
 
72
72
  def entry_delete_multi(entries)
73
73
  writing_keys(entries, failsafe: :delete_multi_entries, failsafe_returning: 0) do
74
- Entry.delete_multi(entries)
74
+ Entry.delete_by_key(*entries)
75
75
  end
76
76
  end
77
77
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidCache
4
- VERSION = "0.7.0"
4
+ VERSION = "1.0.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solid_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Donal McBreen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-26 00:00:00.000000000 Z
11
+ date: 2024-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,42 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '7'
19
+ version: '7.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '7'
26
+ version: '7.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activejob
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '7'
33
+ version: '7.2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '7'
40
+ version: '7.2'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: railties
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '7'
47
+ version: '7.2'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '7'
54
+ version: '7.2'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: debug
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -106,15 +106,13 @@ files:
106
106
  - Rakefile
107
107
  - app/jobs/solid_cache/expiry_job.rb
108
108
  - app/models/solid_cache/entry.rb
109
+ - app/models/solid_cache/entry/encryption.rb
109
110
  - app/models/solid_cache/entry/expiration.rb
110
111
  - app/models/solid_cache/entry/size.rb
111
112
  - app/models/solid_cache/entry/size/estimate.rb
112
113
  - app/models/solid_cache/entry/size/moving_average_estimate.rb
113
114
  - app/models/solid_cache/record.rb
114
- - db/migrate/20230724121448_create_solid_cache_entries.rb
115
- - db/migrate/20240108155507_add_key_hash_and_byte_size_to_solid_cache_entries.rb
116
- - db/migrate/20240110111600_add_key_hash_and_byte_size_indexes_and_null_constraints_to_solid_cache_entries.rb
117
- - db/migrate/20240110111702_remove_key_index_from_solid_cache_entries.rb
115
+ - db/migrate/20240820123641_create_solid_cache_entries.rb
118
116
  - lib/active_support/cache/solid_cache_store.rb
119
117
  - lib/generators/solid_cache/install/USAGE
120
118
  - lib/generators/solid_cache/install/install_generator.rb
@@ -1,11 +0,0 @@
1
- class CreateSolidCacheEntries < ActiveRecord::Migration[7.0]
2
- def change
3
- create_table :solid_cache_entries do |t|
4
- t.binary :key, null: false, limit: 1024
5
- t.binary :value, null: false, limit: 512.megabytes
6
- t.datetime :created_at, null: false
7
-
8
- t.index :key, unique: true
9
- end
10
- end
11
- end
@@ -1,8 +0,0 @@
1
- class AddKeyHashAndByteSizeToSolidCacheEntries < ActiveRecord::Migration[7.0]
2
- def change
3
- change_table :solid_cache_entries do |t|
4
- t.column :key_hash, :integer, null: true, limit: 8
5
- t.column :byte_size, :integer, null: true, limit: 4
6
- end
7
- end
8
- end
@@ -1,11 +0,0 @@
1
- class AddKeyHashAndByteSizeIndexesAndNullConstraintsToSolidCacheEntries < ActiveRecord::Migration[7.0]
2
- def change
3
- change_table :solid_cache_entries, bulk: true do |t|
4
- t.change_null :key_hash, false
5
- t.change_null :byte_size, false
6
- t.index :key_hash, unique: true
7
- t.index [:key_hash, :byte_size]
8
- t.index :byte_size
9
- end
10
- end
11
- end
@@ -1,7 +0,0 @@
1
- class RemoveKeyIndexFromSolidCacheEntries < ActiveRecord::Migration[7.0]
2
- def change
3
- change_table :solid_cache_entries do |t|
4
- t.remove_index :key, unique: true
5
- end
6
- end
7
- end