readthis 1.3.0 → 1.4.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
  SHA1:
3
- metadata.gz: 3fc72dc492c9faadf1cdb788cffc7cc7f884b718
4
- data.tar.gz: 9f3953c2e151c2533518c58deb434d0018cfa898
3
+ metadata.gz: ff00fddcb5af28ee6566f8f9d95e69b842adbb4c
4
+ data.tar.gz: cf57c791dbf2d3c9bb4b0fe3cb3f541df00b9385
5
5
  SHA512:
6
- metadata.gz: 4773d7f739dce07c3ee5f193f6966599d9dd12619bf8bfe1ad9d325563b1d00c70fcac0014e9b0d408167b929e6629401d44332bded3facc4b2581c3cb78ae7b
7
- data.tar.gz: 709e8fdbfab3668d51e8a428223e8e976e9e49e60c1e3e10fa397dc6bf0d8445127466830472c203f8e3e663c42d789db474e2acecfc91d61f9d69148ef50f81
6
+ metadata.gz: 378c680e372e985903972f569b4402e11f1dde8b9ce1805e3bc1b78e21428fd0290f9896d186aab1014f7cc2aa0ed1c75001573e0a90dd3cfa3bdb7c11cc16f1
7
+ data.tar.gz: c41dbbf2eea8a564975510066e6ed881c1940497cd04249ed676faf935314eafd9a26b1e76c98633c69bcf8cd67d8df766730e97f3f9877d2e3c03ed600fa155
data/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
  [![Build Status](https://travis-ci.org/sorentwo/readthis.svg?branch=master)](https://travis-ci.org/sorentwo/readthis)
3
3
  [![Code Climate](https://codeclimate.com/github/sorentwo/readthis/badges/gpa.svg)](https://codeclimate.com/github/sorentwo/readthis)
4
4
  [![Coverage Status](https://coveralls.io/repos/sorentwo/readthis/badge.svg?branch=master&service=github)](https://coveralls.io/github/sorentwo/readthis?branch=master)
5
+ [![Inline Docs](http://inch-ci.org/github/sorentwo/readthis.svg?branch=master)](http://inch-ci.org/github/sorentwo/readthis)
5
6
 
6
7
  # Readthis
7
8
 
@@ -184,7 +185,8 @@ Readthis supports all of standard cache methods except for the following:
184
185
  * `cleanup` - Redis does this with TTL or LRU already.
185
186
  * `delete_matched` - You really don't want to perform key matching operations in
186
187
  Redis. They are linear time and only support basic globbing.
187
- * `mute` and `silence!` - You can subscribe to the events `/cache*+active_support/` with `ActiveSupport::Notifications` to [log cache calls manually][notifications].
188
+ * `mute` and `silence!` - You can subscribe to the events `/cache*.active_support/`
189
+ with `ActiveSupport::Notifications` to [log cache calls manually][notifications].
188
190
 
189
191
  [notifications]: https://github.com/sorentwo/readthis/issues/22#issuecomment-142595938
190
192
 
@@ -1,6 +1,9 @@
1
1
  require 'readthis'
2
2
 
3
3
  module ActiveSupport
4
+ # Provided for compatibility with ActiveSupport's cache lookup behavior. When
5
+ # the ActiveSupport `cache_store` is set to `:readthis_store` it will resolve
6
+ # to `Readthis::Cache`.
4
7
  module Cache
5
8
  ReadthisStore ||= Readthis::Cache # rubocop:disable Style/ConstantName
6
9
  end
@@ -1,12 +1,13 @@
1
1
  require 'readthis/entity'
2
2
  require 'readthis/expanders'
3
3
  require 'readthis/passthrough'
4
+ require 'readthis/scripts'
4
5
  require 'redis'
5
6
  require 'connection_pool'
6
7
 
7
8
  module Readthis
8
9
  class Cache
9
- attr_reader :entity, :notifications, :options, :pool
10
+ attr_reader :entity, :notifications, :options, :pool, :scripts
10
11
 
11
12
  # Provide a class level lookup of the proper notifications module.
12
13
  # Instrumention is expected to occur within applications that have
@@ -18,15 +19,15 @@ module Readthis
18
19
 
19
20
  # Creates a new Readthis::Cache object with the given options.
20
21
  #
21
- # @option [Hash] :redis Options that will be passed to the redis connection
22
- # @option [Boolean] :compress (false) Enable or disable automatic compression
23
- # @option [Number] :compression_threshold (8k) Minimum string size for compression
24
- # @option [Number] :expires_in The number of seconds until an entry expires
25
- # @option [Boolean] :refresh (false) Automatically refresh key expiration
26
- # @option [Module] :marshal (Marshal) Module that responds to `dump` and `load`
27
- # @option [String] :namespace Prefix used to namespace entries
28
- # @option [Number] :pool_size (5) The number of threads in the pool
29
- # @option [Number] :pool_timeout (5) How long before a thread times out
22
+ # @option options [Hash] :redis Options that will be passed to the redis connection
23
+ # @option options [Boolean] :compress (false) Enable or disable automatic compression
24
+ # @option options [Number] :compression_threshold (8k) Minimum string size for compression
25
+ # @option options [Number] :expires_in The number of seconds until an entry expires
26
+ # @option options [Boolean] :refresh (false) Automatically refresh key expiration
27
+ # @option options [Module] :marshal (Marshal) Module that responds to `dump` and `load`
28
+ # @option options [String] :namespace Prefix used to namespace entries
29
+ # @option options [Number] :pool_size (5) The number of threads in the pool
30
+ # @option options [Number] :pool_timeout (5) How long before a thread times out
30
31
  #
31
32
  # @example Create a new cache instance
32
33
  # Readthis::Cache.new(namespace: 'cache',
@@ -47,14 +48,16 @@ module Readthis
47
48
  @pool = ConnectionPool.new(pool_options(options)) do
48
49
  Redis.new(options.fetch(:redis, {}))
49
50
  end
51
+
52
+ @scripts = Readthis::Scripts.new
50
53
  end
51
54
 
52
55
  # Fetches data from the cache, using the given key. If there is data in
53
56
  # the cache with the given key, then that data is returned. Otherwise, nil
54
57
  # is returned.
55
58
  #
56
- # @param [String] Key for lookup
57
- # @param [Hash] Optional overrides
59
+ # @param [String] key Key for lookup
60
+ # @param [Hash] options Optional overrides
58
61
  #
59
62
  # @example
60
63
  #
@@ -76,8 +79,8 @@ module Readthis
76
79
  # Writes data to the cache using the given key. Will overwrite whatever
77
80
  # value is already stored at that key.
78
81
  #
79
- # @param [String] Key for lookup
80
- # @param [Hash] Optional overrides
82
+ # @param [String] key Key for lookup
83
+ # @param [Hash] options Optional overrides
81
84
  #
82
85
  # @example
83
86
  #
@@ -96,8 +99,8 @@ module Readthis
96
99
  # Delete the value stored at the specified key. Returns `true` if
97
100
  # anything was deleted, `false` otherwise.
98
101
  #
99
- # @params [String] The key for lookup
100
- # @params [Hash] Optional overrides
102
+ # @param [String] key The key for lookup
103
+ # @param [Hash] options Optional overrides
101
104
  #
102
105
  # @example
103
106
  #
@@ -121,10 +124,11 @@ module Readthis
121
124
  # the block will be written to the cache under the given cache key, and
122
125
  # that return value will be returned.
123
126
  #
124
- # @param [String] Key for lookup
125
- # @param [Block] Optional block for generating the value when missing
127
+ # @param [String] key Key for lookup
126
128
  # @param options [Hash] Optional overrides
127
129
  # @option options [Boolean] :force Force a cache miss
130
+ # @yield [String] Gives a missing key to the block, which is used to
131
+ # generate the missing value
128
132
  #
129
133
  # @example Typical
130
134
  #
@@ -137,6 +141,7 @@ module Readthis
137
141
  # cache.fetch('city') do
138
142
  # 'Duckburgh'
139
143
  # end
144
+ #
140
145
  # cache.fetch('city') # => "Duckburgh"
141
146
  #
142
147
  # @example Cache Miss
@@ -161,9 +166,9 @@ module Readthis
161
166
  # If the key doesn't exist it will be initialized at 0. If the key exists
162
167
  # but it isn't a Fixnum it will be initialized at 0.
163
168
  #
164
- # @param [String] Key for lookup
165
- # @param [Fixnum] Value to increment by
166
- # @param [Hash] Optional overrides
169
+ # @param [String] key Key for lookup
170
+ # @param [Fixnum] amount Value to increment by
171
+ # @param [Hash] options Optional overrides
167
172
  #
168
173
  # @example
169
174
  #
@@ -182,9 +187,9 @@ module Readthis
182
187
  # If the key doesn't exist it will be initialized at 0. If the key exists
183
188
  # but it isn't a Fixnum it will be initialized at 0.
184
189
  #
185
- # @param [String] Key for lookup
186
- # @param [Fixnum] Value to decrement by
187
- # @param [Hash] Optional overrides
190
+ # @param [String] key Key for lookup
191
+ # @param [Fixnum] amount Value to decrement by
192
+ # @param [Hash] options Optional overrides
188
193
  #
189
194
  # @example
190
195
  #
@@ -233,8 +238,8 @@ module Readthis
233
238
  #
234
239
  # This is a non-standard, but useful, cache method.
235
240
  #
236
- # @param [Hash] Key value hash to write
237
- # @param [Hash] Optional overrides
241
+ # @param [Hash] hash Key value hash to write
242
+ # @param [Hash] options Optional overrides
238
243
  #
239
244
  # @example
240
245
  #
@@ -291,8 +296,8 @@ module Readthis
291
296
 
292
297
  # Returns `true` if the cache contains an entry for the given key.
293
298
  #
294
- # @param [String] Key for lookup
295
- # @param [Hash] Optional overrides
299
+ # @param [String] key Key for lookup
300
+ # @param [Hash] options Optional overrides
296
301
  #
297
302
  # @example
298
303
  #
@@ -308,11 +313,12 @@ module Readthis
308
313
  # Clear the entire cache. This flushes the current database, no
309
314
  # globbing is applied.
310
315
  #
311
- # @param [Hash] Options, only present for compatibility.
316
+ # @param [Hash] _options Options, only present for compatibility
312
317
  #
313
318
  # @example
314
319
  #
315
320
  # cache.clear #=> 'OK'
321
+ #
316
322
  def clear(_options = nil)
317
323
  invoke(:clear, '*', &:flushdb)
318
324
  end
@@ -322,11 +328,9 @@ module Readthis
322
328
  def refresh_entity(keys, store, options)
323
329
  return unless options[:refresh] && options[:expires_in]
324
330
 
325
- store.multi do
326
- Array(keys).each do |key|
327
- store.expire(key, coerce_expiration(options[:expires_in]))
328
- end
329
- end
331
+ expiration = coerce_expiration(options[:expires_in])
332
+
333
+ scripts.run('mexpire', store, keys, expiration)
330
334
  end
331
335
 
332
336
  def write_entity(key, value, store, options)
@@ -1,13 +1,19 @@
1
1
  require 'zlib'
2
2
 
3
3
  module Readthis
4
+ # An instance of the Entity class is used to handle `load` and `dump`
5
+ # operations on cached values.
4
6
  class Entity
7
+ # Unless they are overridden, these are the options used to load and unload
8
+ # every value.
5
9
  DEFAULT_OPTIONS = {
6
10
  compress: false,
7
11
  marshal: Marshal,
8
12
  threshold: 8 * 1024
9
13
  }.freeze
10
14
 
15
+ # A hexidecimal compression flag. When it is present within the magic bit
16
+ # of an entity that entity is considered compressed.
11
17
  COMPRESSED_FLAG = 0x8
12
18
 
13
19
  # Creates a Readthis::Entity with default options. Each option can be
@@ -17,9 +23,12 @@ module Readthis
17
23
  # automatically be used again when loading, regardless of how current
18
24
  # options are set.
19
25
  #
20
- # @option [Boolean] :compress (false) Enable or disable automatic compression
21
- # @option [Module] :marshal (Marshal) Any module that responds to `dump` and `load`
22
- # @option [Number] :threshold (8k) The size a string must be for compression
26
+ # @option [Boolean] :compress (false) Enable or disable automatic
27
+ # compression
28
+ # @option [Module] :marshal (Marshal) Any module that responds to `dump`
29
+ # and `load`
30
+ # @option [Number] :threshold (8k) The size a string must be for
31
+ # compression
23
32
  #
24
33
  def initialize(options = {})
25
34
  @options = DEFAULT_OPTIONS.merge(options)
@@ -28,10 +37,13 @@ module Readthis
28
37
  # Output a value prepared for cache storage. Passed options will override
29
38
  # whatever has been specified for the instance.
30
39
  #
31
- # @param [String] String to dump
32
- # @option [Boolean] :compress Enable or disable automatic compression
33
- # @option [Module] :marshal Any module that responds to `dump` and `load`
34
- # @option [Number] :threshold The size a string must be for compression
40
+ # @param [String] value String to dump
41
+ # @option options [Boolean] :compress Enable or disable automatic
42
+ # compression
43
+ # @option options [Module] :marshal Any module that responds to `dump` and
44
+ # `load`
45
+ # @option options [Number] :threshold The size a string must be for
46
+ # compression
35
47
  # @return [String] The prepared, possibly compressed, string
36
48
  #
37
49
  # @example Dumping a value using defaults
@@ -54,7 +66,7 @@ module Readthis
54
66
 
55
67
  # Parse a dumped value using the embedded options.
56
68
  #
57
- # @param [String] Option embedded string to load
69
+ # @param [String] string Option embedded string to load
58
70
  # @return [String] The original dumped string, restored
59
71
  #
60
72
  # @example
@@ -77,9 +89,9 @@ module Readthis
77
89
  # Where there are four unused bits, 1 compression bit, and 3 bits for the
78
90
  # serializer. This allows up to 8 different serializers for marshaling.
79
91
  #
80
- # @param [String] String to prefix with flags
81
- # @param [Module] The marshal module to be used
82
- # @param [Boolean] Flag determining whether the value is compressed
92
+ # @param [String] value String to prefix with flags
93
+ # @param [Module] marshal The marshal module to be used
94
+ # @param [Boolean] compress Flag determining whether the value is compressed
83
95
  # @return [String] The original string with a single byte prefixed
84
96
  #
85
97
  # @example Compose an option embedded string
@@ -96,7 +108,7 @@ module Readthis
96
108
 
97
109
  # Decompose an option embedded string into marshal, compression and value.
98
110
  #
99
- # @param [String] Option embedded string to
111
+ # @param [String] string Option embedded string to
100
112
  # @return [Array<Module, Boolean, String>] An array comprised of the
101
113
  # marshal, compression flag, and the base string.
102
114
  #
@@ -1,7 +1,22 @@
1
1
  module Readthis
2
+ # This is the base error that all other specific errors inherit from,
3
+ # making it possible to rescue the `ReadthisError` superclass.
4
+ #
5
+ # This isn't raised by itself.
2
6
  ReadthisError = Class.new(StandardError)
3
7
 
8
+ # Raised when attempting to modify the serializers after they have been
9
+ # frozen.
4
10
  SerializersFrozenError = Class.new(ReadthisError)
11
+
12
+ # Raised when attempting to add a new serializer after the limit of 7 is
13
+ # reached.
5
14
  SerializersLimitError = Class.new(ReadthisError)
15
+
16
+ # Raised when an unknown script is called.
17
+ UnknownCommandError = Class.new(ReadthisError)
18
+
19
+ # Raised when a serializer was specified, but hasn't been configured for
20
+ # usage.
6
21
  UnknownSerializerError = Class.new(ReadthisError)
7
22
  end
@@ -7,7 +7,10 @@ module Readthis
7
7
  when key.is_a?(Array)
8
8
  key.flat_map { |elem| expand_key(elem) }.join('/')
9
9
  when key.is_a?(Hash)
10
- key.sort_by { |hkey, _| hkey.to_s }.map { |hkey, val| "#{hkey}=#{val}" }.join('/')
10
+ key
11
+ .sort_by { |hkey, _| hkey.to_s }
12
+ .map { |hkey, val| "#{hkey}=#{val}" }
13
+ .join('/')
11
14
  when key.respond_to?(:to_param)
12
15
  key.to_param
13
16
  else
@@ -3,7 +3,7 @@
3
3
  module Readthis
4
4
  module Passthrough
5
5
  def self.dump(value)
6
- value
6
+ value.dup
7
7
  end
8
8
 
9
9
  def self.load(value)
@@ -0,0 +1,50 @@
1
+ module Readthis
2
+ # The `Scripts` class is used to conveniently execute lua scripts. The first
3
+ # time a command is run it is stored on the server and subsequently referred
4
+ # to by its SHA. Each instance tracks SHAs separately, they are not global.
5
+ class Scripts
6
+ attr_reader :loaded
7
+
8
+ # Creates a new Readthis::Scripts instance.
9
+ def initialize
10
+ @loaded = {}
11
+ end
12
+
13
+ # Run a named lua script with the provided keys and arguments.
14
+ #
15
+ # @param [String] command The script to run, without a `.lua` extension
16
+ # @param [#Store] store A Redis client for storing and evaluating the script
17
+ # @param [Array] keys One or more keys to pass to the command
18
+ # @param [Array] args One or more args to pass to the command
19
+ #
20
+ # @return [Any] The Redis converted value returned on the script
21
+ #
22
+ # @example
23
+ #
24
+ # scripts.run('mexpire', store, %w[a b c], 1) # => 'OK'
25
+ #
26
+ def run(command, store, keys, args = [])
27
+ store.evalsha(
28
+ sha(command, store),
29
+ Array(keys),
30
+ Array(args)
31
+ )
32
+ end
33
+
34
+ private
35
+
36
+ def sha(command, store)
37
+ loaded[command] ||= load_script!(command, store)
38
+ end
39
+
40
+ def load_script!(command, store)
41
+ path = File.join('script', "#{command}.lua")
42
+
43
+ File.open(path) do |file|
44
+ loaded[command] = store.script(:load, file.read)
45
+ end
46
+ rescue Errno::ENOENT
47
+ raise Readthis::UnknownCommandError, "unknown command '#{command}'"
48
+ end
49
+ end
50
+ end
@@ -4,12 +4,16 @@ require 'readthis/passthrough'
4
4
 
5
5
  module Readthis
6
6
  class Serializers
7
+ # Defines the default set of three serializers: Marshal, Passthrough, and
8
+ # JSON. With a hard limit of 7 that leaves 4 additional slots.
7
9
  BASE_SERIALIZERS = {
8
10
  Marshal => 0x1,
9
11
  Passthrough => 0x2,
10
12
  JSON => 0x3
11
13
  }.freeze
12
14
 
15
+ # The hard serializer limit, based on the number of possible values within
16
+ # a single 3bit integer.
13
17
  SERIALIZER_LIMIT = 7
14
18
 
15
19
  attr_reader :serializers, :inverted
@@ -25,7 +29,7 @@ module Readthis
25
29
  # any single application be configured for any single application. This
26
30
  # limit is based on the number of bytes available in the option flag.
27
31
  #
28
- # @param [Module] Any object that responds to `dump` and `load`
32
+ # @param [Module] serializer Any object that responds to `dump` and `load`
29
33
  # @return [self] Returns itself for possible chaining
30
34
  #
31
35
  # @example
@@ -37,7 +41,7 @@ module Readthis
37
41
  case
38
42
  when serializers.frozen?
39
43
  raise SerializersFrozenError
40
- when serializers.length > SERIALIZER_LIMIT
44
+ when serializers.length >= SERIALIZER_LIMIT
41
45
  raise SerializersLimitError
42
46
  else
43
47
  @serializers[serializer] = flags.max.succ
@@ -63,7 +67,7 @@ module Readthis
63
67
 
64
68
  # Find a flag for a serializer object.
65
69
  #
66
- # @param [Object] Look up a flag by object
70
+ # @param [Object] serializer Look up a flag by object
67
71
  # @return [Number] Corresponding flag for the serializer object
68
72
  # @raise [UnknownSerializerError] Indicates that a serializer was
69
73
  # specified, but hasn't been configured for usage.
@@ -84,7 +88,7 @@ module Readthis
84
88
 
85
89
  # Find a serializer object by flag value.
86
90
  #
87
- # @param [Number] Flag to look up the serializer object by
91
+ # @param [Number] flag Integer to look up the serializer object by
88
92
  # @return [Module] The serializer object
89
93
  #
90
94
  # @example
@@ -92,7 +96,7 @@ module Readthis
92
96
  # serializers.rassoc(1) #=> Marshal
93
97
  #
94
98
  def rassoc(flag)
95
- inverted[flag & inverted.length]
99
+ inverted[flag & SERIALIZER_LIMIT]
96
100
  end
97
101
 
98
102
  # @private
@@ -1,3 +1,3 @@
1
1
  module Readthis
2
- VERSION = '1.3.0'.freeze
2
+ VERSION = '1.4.0'.freeze
3
3
  end
data/lib/readthis.rb CHANGED
@@ -7,7 +7,7 @@ module Readthis
7
7
  # The current, global, instance of serializers that is used by all cache
8
8
  # instances.
9
9
  #
10
- # @returns [Readthis::Serializers] An cached Serializers instance
10
+ # @return [Readthis::Serializers] An cached Serializers instance
11
11
  #
12
12
  # @see readthis/serializers
13
13
  #
@@ -18,7 +18,7 @@ module Readthis
18
18
  # Indicates whether connection error tolerance is enabled. With tolerance
19
19
  # enabled every operation will return a `nil` value.
20
20
  #
21
- # @returns [Boolean] True for enabled, false for disabled
21
+ # @return [Boolean] True for enabled, false for disabled
22
22
  #
23
23
  def fault_tolerant?
24
24
  @fault_tolerant
@@ -26,7 +26,7 @@ module Readthis
26
26
 
27
27
  # Toggle fault tolerance for connection errors.
28
28
  #
29
- # @param [Boolean] The new value for fault tolerance
29
+ # @param [Boolean] value The new value for fault tolerance
30
30
  #
31
31
  def fault_tolerant=(value)
32
32
  @fault_tolerant = value
@@ -0,0 +1,7 @@
1
+ local expire = ARGV[1]
2
+
3
+ for index = 1, #KEYS do
4
+ redis.call('EXPIRE', KEYS[index], expire)
5
+ end
6
+
7
+ return true
@@ -1,4 +1,3 @@
1
- require 'readthis'
2
1
  require 'matchers/redis_matchers'
3
2
 
4
3
  RSpec.describe Readthis::Cache do
@@ -173,6 +172,12 @@ RSpec.describe Readthis::Cache do
173
172
  expect(cache.read('missing-key')).to eq(value)
174
173
  end
175
174
 
175
+ it 'returns computed value when using passthrough marshalling' do
176
+ cache = Readthis::Cache.new(marshal: Readthis::Passthrough)
177
+ result = cache.fetch('missing-key') { 'value for you' }
178
+ expect(result).to eq('value for you')
179
+ end
180
+
176
181
  it 'does not set for a missing key without a block' do
177
182
  expect(cache.fetch('missing-key')).to be_nil
178
183
  end
@@ -1,4 +1,3 @@
1
- require 'readthis'
2
1
  require 'json'
3
2
 
4
3
  RSpec.describe Readthis::Entity do
@@ -1,5 +1,3 @@
1
- require 'readthis/expanders'
2
-
3
1
  RSpec.describe Readthis::Expanders do
4
2
  def expand(key, namespace = nil)
5
3
  Readthis::Expanders.namespace_key(key, namespace)
@@ -1,17 +1,16 @@
1
- require 'readthis/passthrough'
2
-
3
1
  RSpec.describe Readthis::Passthrough do
2
+ let(:value) { 'skywalker' }
3
+
4
4
  describe '.load' do
5
5
  it 'passes through the provided value' do
6
- value = Object.new
7
6
  expect(Readthis::Passthrough.load(value)).to eq(value)
8
7
  end
9
8
  end
10
9
 
11
10
  describe '.dump' do
12
11
  it 'passes through the provided value' do
13
- value = Object.new
14
12
  expect(Readthis::Passthrough.dump(value)).to eq(value)
13
+ expect(Readthis::Passthrough.dump(value)).not_to be(value)
15
14
  end
16
15
  end
17
16
  end
@@ -0,0 +1,31 @@
1
+ RSpec.describe Readthis::Scripts do
2
+ let(:scripts) { Readthis::Scripts.new }
3
+
4
+ describe '#run' do
5
+ it 'raises an error with an unknown command' do
6
+ expect do
7
+ scripts.run('unknown', nil, [])
8
+ end.to raise_error(Readthis::UnknownCommandError)
9
+ end
10
+
11
+ it 'runs the script command with a single key' do
12
+ store = Redis.new
13
+
14
+ store.set('alpha', 'content')
15
+ scripts.run('mexpire', store, 'alpha', 1)
16
+
17
+ expect(store.ttl('alpha')).to eq(1)
18
+ end
19
+
20
+ it 'runs the script command with multiple keys' do
21
+ store = Redis.new
22
+
23
+ store.set('beta', 'content')
24
+ store.set('gamma', 'content')
25
+ scripts.run('mexpire', store, %w[beta gamma], 1)
26
+
27
+ expect(store.ttl('beta')).to eq(1)
28
+ expect(store.ttl('gamma')).to eq(1)
29
+ end
30
+ end
31
+ end
@@ -1,5 +1,3 @@
1
- require 'readthis/serializers'
2
-
3
1
  RSpec.describe Readthis::Serializers do
4
2
  CustomSerializer = Class.new
5
3
  AnotherSerializer = Class.new
@@ -24,9 +22,9 @@ RSpec.describe Readthis::Serializers do
24
22
 
25
23
  it 'prevents more than seven serializers' do
26
24
  serializers = Readthis::Serializers.new
27
-
25
+ serializers << Class.new until serializers.flags.length >= 7
28
26
  expect do
29
- 10.times { serializers << Class.new }
27
+ serializers << Class.new
30
28
  end.to raise_error(Readthis::SerializersLimitError)
31
29
  end
32
30
  end
@@ -48,18 +46,29 @@ RSpec.describe Readthis::Serializers do
48
46
  end
49
47
 
50
48
  describe '#rassoc' do
51
- it 'inverts the current set of serializers' do
52
- serializers = Readthis::Serializers.new
49
+ let(:serializers) { Readthis::Serializers.new }
53
50
 
51
+ it 'inverts the current set of serializers' do
54
52
  expect(serializers.rassoc(1)).to eq(Marshal)
55
53
  end
56
54
 
57
55
  it 'returns custom serializers' do
58
- serializers = Readthis::Serializers.new
59
56
  serializers << CustomSerializer
60
-
61
57
  expect(serializers.rassoc(4)).to eq(CustomSerializer)
62
58
  end
59
+
60
+ it 'inverts default serializers after adding custom one' do
61
+ serializers << CustomSerializer
62
+ expect(serializers.rassoc(1)).to eq(Marshal)
63
+ expect(serializers.rassoc(3)).to eq(JSON)
64
+ end
65
+
66
+ it 'takes into account only first 3 bytes of passed integer' do
67
+ expect(serializers.rassoc(1)).to eq(Marshal)
68
+ expect(serializers.rassoc(11)).to eq(JSON)
69
+ serializers << CustomSerializer
70
+ expect(serializers.rassoc(12)).to eq(CustomSerializer)
71
+ end
63
72
  end
64
73
 
65
74
  describe '#freeze!' do
@@ -1,5 +1,3 @@
1
- require 'readthis'
2
-
3
1
  RSpec.describe Readthis do
4
2
  describe '#serializers' do
5
3
  it 'lists currently configured serializers' do
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'coveralls'
2
+ require 'readthis'
2
3
 
3
4
  Coveralls.wear!
4
5
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: readthis
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Parker Selbert
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-08 00:00:00.000000000 Z
11
+ date: 2016-07-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -123,13 +123,16 @@ files:
123
123
  - lib/readthis/errors.rb
124
124
  - lib/readthis/expanders.rb
125
125
  - lib/readthis/passthrough.rb
126
+ - lib/readthis/scripts.rb
126
127
  - lib/readthis/serializers.rb
127
128
  - lib/readthis/version.rb
129
+ - script/mexpire.lua
128
130
  - spec/matchers/redis_matchers.rb
129
131
  - spec/readthis/cache_spec.rb
130
132
  - spec/readthis/entity_spec.rb
131
133
  - spec/readthis/expanders_spec.rb
132
134
  - spec/readthis/passthrough_spec.rb
135
+ - spec/readthis/scripts_spec.rb
133
136
  - spec/readthis/serializers_spec.rb
134
137
  - spec/readthis_spec.rb
135
138
  - spec/spec_helper.rb
@@ -163,6 +166,8 @@ test_files:
163
166
  - spec/readthis/entity_spec.rb
164
167
  - spec/readthis/expanders_spec.rb
165
168
  - spec/readthis/passthrough_spec.rb
169
+ - spec/readthis/scripts_spec.rb
166
170
  - spec/readthis/serializers_spec.rb
167
171
  - spec/readthis_spec.rb
168
172
  - spec/spec_helper.rb
173
+ has_rdoc: