paquito 0.8.0 → 0.9.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: 2cfefa4171fc3e9f968368e99c134e864d493c6651ed21aff0e1bc299a95fb7f
4
- data.tar.gz: e92cacde6d2aa0867b740f99a001d3ff109f4c88eddb7d89594305a579122af3
3
+ metadata.gz: 2882e208a7d6cc2c9b98f748578ea1c8e91133a5ecc71fdc4e41861bb7788f7e
4
+ data.tar.gz: 8376bc939c974028dd6957e1d98467594c33807cdf13fc0470b216aa2476f9ce
5
5
  SHA512:
6
- metadata.gz: 3e032eb7438d07371862c7f9015b8c0a2f72dc8a93004387f1b151f75d06614dba89bc97da21d3eb83399f1c86909f1dc0bbd5702ec8cc4fef1f5001f512a3da
7
- data.tar.gz: e1bd239ec600c28dc5e322b8a8a95daeb539aaada4c9167cf046f5ee5716eb3a6231487b663b534d0db8cb6e1ce2ce53d1dd1b6706184b57f36890edbcbfa663
6
+ metadata.gz: 7bb6ab11609d478cae8993c65fb12db8ea22363064401c718f6e6915ccdd75ad9ddd5c3f7a5a88a8c0562e943c2fda44c4dab101a3db4266f26134ae2ac0e26f
7
+ data.tar.gz: 268549cd0b872b554397b7d685e0ba9f8db9572690091ebaa4936e7a488a26569e9691ad0bfdf2447d1521a36aa5c26b8a7acf96a04271d449c0a6036de7d777
@@ -13,7 +13,7 @@ jobs:
13
13
  - name: Set up Ruby
14
14
  uses: ruby/setup-ruby@v1
15
15
  with:
16
- ruby-version: '2.6'
16
+ ruby-version: '2.7'
17
17
  bundler-cache: true
18
18
  - name: Run test
19
19
  run: bundle exec rubocop
@@ -23,18 +23,17 @@ jobs:
23
23
  strategy:
24
24
  fail-fast: false
25
25
  matrix:
26
- ruby: [ ruby-head, '3.1', '3.0', '2.7', '2.6' ]
26
+ ruby: [ ruby-head, '3.1', '3.0', '2.7' ]
27
27
  steps:
28
28
  - name: Checkout
29
29
  uses: actions/checkout@v3
30
+ - name: Remove Gemfile.lock
31
+ run: rm Gemfile.lock
30
32
  - name: Set up Ruby
31
33
  uses: ruby/setup-ruby@v1
32
34
  with:
33
35
  ruby-version: ${{ matrix.ruby }}
34
- - name: Install dependencies
35
- run: |
36
- rm Gemfile.lock
37
- bundle install
36
+ bundler-cache: true
38
37
  - name: Run test
39
38
  run: bundle exec rake
40
39
  - name: Install gem
data/.rubocop.yml CHANGED
@@ -2,7 +2,7 @@ inherit_gem:
2
2
  rubocop-shopify: rubocop.yml
3
3
 
4
4
  AllCops:
5
- TargetRubyVersion: 2.6
5
+ TargetRubyVersion: 2.7
6
6
 
7
7
  Style/ClassMethodsDefinitions:
8
8
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Unreleased
2
2
 
3
+ # 0.9.0
4
+
5
+ * Handle `compress / decompress` coders (#22)
6
+ * Introduce `FlatCacheEntryCoder` (#21).
7
+ * Drop the partial Ruby 2.6 support.
8
+
9
+ # 0.8.0
10
+
3
11
  * Introduce `SingleBytePrefixVersionWithStringBypass` (#18, #20).
4
12
 
5
13
  # 0.7.0
data/Gemfile.lock CHANGED
@@ -1,23 +1,22 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- paquito (0.8.0)
4
+ paquito (0.9.0)
5
5
  msgpack (>= 1.5.2)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activemodel (6.1.6.1)
11
- activesupport (= 6.1.6.1)
12
- activerecord (6.1.6.1)
13
- activemodel (= 6.1.6.1)
14
- activesupport (= 6.1.6.1)
15
- activesupport (6.1.6.1)
10
+ activemodel (7.0.4)
11
+ activesupport (= 7.0.4)
12
+ activerecord (7.0.4)
13
+ activemodel (= 7.0.4)
14
+ activesupport (= 7.0.4)
15
+ activesupport (7.0.4)
16
16
  concurrent-ruby (~> 1.0, >= 1.0.2)
17
17
  i18n (>= 1.6, < 2)
18
18
  minitest (>= 5.1)
19
19
  tzinfo (~> 2.0)
20
- zeitwerk (~> 2.3)
21
20
  ast (2.4.2)
22
21
  benchmark-ips (2.10.0)
23
22
  byebug (11.1.3)
@@ -52,7 +51,6 @@ GEM
52
51
  tzinfo (2.0.5)
53
52
  concurrent-ruby (~> 1.0)
54
53
  unicode-display_width (2.2.0)
55
- zeitwerk (2.6.0)
56
54
 
57
55
  PLATFORMS
58
56
  ruby
data/README.md CHANGED
@@ -161,6 +161,28 @@ Example:
161
161
  ActiveSupport::Cache::FileStore.new("tmp/cache", coder: Paquito.chain(Paquito::CacheEntryCoder, JSON))
162
162
  ```
163
163
 
164
+ ### `FlatCacheEntryCoder`
165
+
166
+ `Paquito::FlatCacheEntryCoder` is a variation of `Paquito::CacheEntryCoder`. Instead of encoding `ActiveSupport::Cache::Entry`
167
+ into an Array of three members, it serializes the entry metadata itself and adds it as a prefix to the serialized payload.
168
+
169
+ This allows to leverage `Paquito::SingleBytePrefixVersionWithStringBypass` effectively.
170
+
171
+ Example:
172
+
173
+ ```ruby
174
+ ActiveSupport::Cache::FileStore.new(
175
+ "tmp/cache",
176
+ coder: Paquito::FlatCacheEntryCoder.new(
177
+ Paquito::SingleBytePrefixVersionWithStringBypass.new(
178
+ 1,
179
+ 0 => Marshal,
180
+ 1 => JSON,
181
+ )
182
+ )
183
+ )
184
+ ```
185
+
164
186
  ### `SerializedColumn`
165
187
 
166
188
  `Paquito::SerializedColumn` allows you to decorate any encoder to behave like Rails's builtin `YAMLColumn`
data/Rakefile CHANGED
@@ -3,8 +3,7 @@
3
3
  require "bundler/gem_tasks"
4
4
  require "rake/testtask"
5
5
 
6
- suites = [:vanilla, :activesupport]
7
- suites << :activerecord if RUBY_VERSION >= "2.7"
6
+ suites = [:vanilla, :activesupport, :activerecord]
8
7
  namespace :test do
9
8
  suites.each do |suite|
10
9
  Rake::TestTask.new(suite) do |t|
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "paquito"
6
+ require "active_support"
7
+ require "benchmark/ips"
8
+
9
+ CODEC = Paquito::CodecFactory.build
10
+ ORIGINAL = Paquito::SingleBytePrefixVersion.new(
11
+ 0,
12
+ 0 => Paquito.chain(
13
+ Paquito::CacheEntryCoder,
14
+ CODEC,
15
+ ),
16
+ )
17
+ FLAT = Paquito::FlatCacheEntryCoder.new(
18
+ Paquito::SingleBytePrefixVersionWithStringBypass.new(
19
+ 0,
20
+ 0 => CODEC,
21
+ )
22
+ )
23
+
24
+ entries = {
25
+ small_string: "Hello World!",
26
+ bytes_1mb: Random.bytes(1_000_000),
27
+ int_array: 1000.times.to_a,
28
+ }
29
+
30
+ entries.each do |name, object|
31
+ entry = ActiveSupport::Cache::Entry.new(object, expires_at: 15.minutes.from_now.to_f)
32
+ original_payload = ORIGINAL.dump(entry).freeze
33
+ flat_payload = FLAT.dump(entry).freeze
34
+
35
+ puts " === Read #{name} ==="
36
+ Benchmark.ips do |x|
37
+ x.report("original") { ORIGINAL.load(original_payload) }
38
+ x.report("flat") { FLAT.load(flat_payload) }
39
+ x.compare!(order: :baseline)
40
+ end
41
+
42
+ puts " === Write #{name} ==="
43
+ Benchmark.ips do |x|
44
+ x.report("original") { ORIGINAL.dump(entry) }
45
+ x.report("flat") { FLAT.dump(entry) }
46
+ x.compare!(order: :baseline)
47
+ end
48
+
49
+ puts
50
+ end
data/dev.yml CHANGED
@@ -2,11 +2,11 @@ name: paquito
2
2
 
3
3
  up:
4
4
  - ruby:
5
- version: 2.6.9
5
+ version: 2.7.5
6
6
  - bundler
7
7
 
8
8
  commands:
9
9
  test:
10
10
  syntax: ""
11
11
  desc: 'run all the tests'
12
- run: bundle exec rake test
12
+ run: bundle exec rake test
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ gem "activerecord", ">= 7.0"
3
4
  require "paquito/errors"
4
5
 
5
6
  module Paquito
@@ -1,22 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ gem "activesupport", ">= 7.0"
4
+
3
5
  module Paquito
4
6
  module CacheEntryCoder
5
7
  def self.dump(entry)
6
- attrs = [entry.value, entry.expires_at, entry.version]
7
- # drop any trailing nil values to save a couple bytes
8
- attrs.pop until !attrs.last.nil? || attrs.empty?
9
- attrs
8
+ entry.pack
10
9
  end
11
10
 
12
11
  def self.load(payload)
13
- entry = ::ActiveSupport::Cache::Entry.allocate
14
- value, expires_in, version = payload
15
- entry.instance_variable_set(:@value, value)
16
- entry.instance_variable_set(:@expires_in, expires_in)
17
- entry.instance_variable_set(:@created_at, 0.0)
18
- entry.instance_variable_set(:@version, version)
19
- entry
12
+ ::ActiveSupport::Cache::Entry.unpack(payload)
20
13
  end
21
14
  end
22
15
  end
@@ -5,7 +5,7 @@ require "paquito/coder_chain"
5
5
 
6
6
  module Paquito
7
7
  class CodecFactory
8
- def self.build(types, freeze: false, serializable_type: false, pool: 1)
8
+ def self.build(types = [], freeze: false, serializable_type: false, pool: 1)
9
9
  factory = if types.empty? && !serializable_type
10
10
  MessagePack::DefaultFactory
11
11
  else
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Paquito
4
+ class Compressor
5
+ def initialize(compressor)
6
+ @compressor = compressor
7
+ end
8
+
9
+ def dump(serial)
10
+ @compressor.compress(serial)
11
+ end
12
+
13
+ def load(payload)
14
+ @compressor.decompress(payload)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ gem "activesupport", ">= 7.0"
4
+
5
+ module Paquito
6
+ class FlatCacheEntryCoder
7
+ METADATA_CODEC = CodecFactory.build
8
+
9
+ EXPIRES_AT_FORMAT = "E" # Float double-precision, little-endian byte order (8 bytes)
10
+ VERSION_SIZE_FORMAT = "l<" # 32-bit signed, little-endian byte order (int32_t) (4 bytes)
11
+ PREFIX_FORMAT = -(EXPIRES_AT_FORMAT + VERSION_SIZE_FORMAT)
12
+ VERSION_SIZE_OFFSET = [0.0].pack(EXPIRES_AT_FORMAT).bytesize # should be 8
13
+ VERSION_OFFSET = [0.0, 0].pack(PREFIX_FORMAT).bytesize # Should be 12
14
+ VERSION_SIZE_UNPACK = -"@#{VERSION_SIZE_OFFSET}#{VERSION_SIZE_FORMAT}"
15
+
16
+ def initialize(value_coder)
17
+ @value_coder = value_coder
18
+ end
19
+
20
+ def dump(entry)
21
+ version = entry.version
22
+ payload = [
23
+ entry.expires_at || 0.0,
24
+ version ? version.bytesize : -1,
25
+ ].pack(PREFIX_FORMAT)
26
+ payload << version if version
27
+ payload << @value_coder.dump(entry.value)
28
+ end
29
+
30
+ def load(payload)
31
+ expires_at = payload.unpack1(EXPIRES_AT_FORMAT)
32
+ expires_at = nil if expires_at == 0.0
33
+
34
+ version_size = payload.unpack1(VERSION_SIZE_UNPACK)
35
+ if version_size < 0
36
+ version_size = 0
37
+ else
38
+ version = payload.byteslice(VERSION_OFFSET, version_size)
39
+ end
40
+
41
+ ::ActiveSupport::Cache::Entry.new(
42
+ @value_coder.load(payload.byteslice((VERSION_OFFSET + version_size)..-1).freeze),
43
+ expires_at: expires_at,
44
+ version: version,
45
+ )
46
+ end
47
+ end
48
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Paquito
4
- VERSION = "0.8.0"
4
+ VERSION = "0.9.0"
5
5
  end
data/lib/paquito.rb CHANGED
@@ -14,7 +14,6 @@ require "paquito/allow_nil"
14
14
  require "paquito/translate_errors"
15
15
  require "paquito/safe_yaml"
16
16
  require "paquito/conditional_compressor"
17
- require "paquito/cache_entry_coder"
18
17
  require "paquito/single_byte_prefix_version"
19
18
  require "paquito/single_byte_prefix_version_with_string_bypass"
20
19
  require "paquito/comment_prefix_version"
@@ -25,6 +24,8 @@ require "paquito/typed_struct"
25
24
  require "paquito/serialized_column"
26
25
 
27
26
  module Paquito
27
+ autoload :CacheEntryCoder, "paquito/cache_entry_coder"
28
+ autoload :FlatCacheEntryCoder, "paquito/flat_cache_entry_coder"
28
29
  autoload :ActiveRecordCoder, "paquito/active_record_coder"
29
30
 
30
31
  class << self
@@ -33,6 +34,8 @@ module Paquito
33
34
  coder
34
35
  elsif coder.respond_to?(:deflate) && coder.respond_to?(:inflate)
35
36
  Deflater.new(coder)
37
+ elsif coder.respond_to?(:compress) && coder.respond_to?(:decompress)
38
+ Compressor.new(coder)
36
39
  else
37
40
  raise TypeError, "Coders must respond to #dump and #load, #{coder.inspect} doesn't"
38
41
  end
data/paquito.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = "Framework for defining efficient and extendable serializers"
13
13
  spec.homepage = "https://github.com/Shopify/paquito"
14
14
  spec.license = "MIT"
15
- spec.required_ruby_version = ">= 2.6.0"
15
+ spec.required_ruby_version = ">= 2.7.0"
16
16
 
17
17
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
18
18
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paquito
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean Boussier
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-25 00:00:00.000000000 Z
11
+ date: 2022-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -40,6 +40,7 @@ files:
40
40
  - LICENSE.txt
41
41
  - README.md
42
42
  - Rakefile
43
+ - benchmark/flat-entry-coder.rb
43
44
  - benchmark/msgpack-pooling.rb
44
45
  - benchmark/string-bypass.rb
45
46
  - bin/console
@@ -52,9 +53,11 @@ files:
52
53
  - lib/paquito/codec_factory.rb
53
54
  - lib/paquito/coder_chain.rb
54
55
  - lib/paquito/comment_prefix_version.rb
56
+ - lib/paquito/compressor.rb
55
57
  - lib/paquito/conditional_compressor.rb
56
58
  - lib/paquito/deflater.rb
57
59
  - lib/paquito/errors.rb
60
+ - lib/paquito/flat_cache_entry_coder.rb
58
61
  - lib/paquito/safe_yaml.rb
59
62
  - lib/paquito/serialized_column.rb
60
63
  - lib/paquito/single_byte_prefix_version.rb
@@ -81,7 +84,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
81
84
  requirements:
82
85
  - - ">="
83
86
  - !ruby/object:Gem::Version
84
- version: 2.6.0
87
+ version: 2.7.0
85
88
  required_rubygems_version: !ruby/object:Gem::Requirement
86
89
  requirements:
87
90
  - - ">="