knuckles 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +40 -13
- data/lib/knuckles/keygen.rb +22 -0
- data/lib/knuckles/pipeline.rb +82 -26
- data/lib/knuckles/stages/combiner.rb +24 -0
- data/lib/knuckles/stages/dumper.rb +23 -0
- data/lib/knuckles/stages/enhancer.rb +21 -0
- data/lib/knuckles/stages/fetcher.rb +30 -0
- data/lib/knuckles/stages/hydrator.rb +29 -0
- data/lib/knuckles/stages/renderer.rb +27 -0
- data/lib/knuckles/stages/writer.rb +41 -0
- data/lib/knuckles/stages.rb +13 -0
- data/lib/knuckles/version.rb +1 -1
- data/lib/knuckles/view.rb +104 -5
- data/lib/knuckles.rb +55 -7
- data/spec/knuckles/pipeline_spec.rb +0 -40
- data/spec/knuckles/{combiner_spec.rb → stages/combiner_spec.rb} +2 -2
- data/spec/knuckles/{dumper_spec.rb → stages/dumper_spec.rb} +2 -2
- data/spec/knuckles/{enhancer_spec.rb → stages/enhancer_spec.rb} +3 -3
- data/spec/knuckles/{fetcher_spec.rb → stages/fetcher_spec.rb} +3 -3
- data/spec/knuckles/{hydrator_spec.rb → stages/hydrator_spec.rb} +3 -3
- data/spec/knuckles/{renderer_spec.rb → stages/renderer_spec.rb} +2 -2
- data/spec/knuckles/{writer_spec.rb → stages/writer_spec.rb} +3 -3
- metadata +31 -43
- data/.gitignore +0 -15
- data/.rspec +0 -2
- data/.rubocop.yml +0 -41
- data/.travis.yml +0 -10
- data/Gemfile +0 -11
- data/Rakefile +0 -9
- data/bench/bench_helper.rb +0 -48
- data/bench/fixtures/serializers.rb +0 -93
- data/bench/fixtures/submissions.json +0 -1
- data/bench/profiling.rb +0 -14
- data/bench/realistic.rb +0 -9
- data/bench/simple.rb +0 -25
- data/bin/rspec +0 -16
- data/knuckles.gemspec +0 -24
- data/lib/knuckles/combiner.rb +0 -26
- data/lib/knuckles/dumper.rb +0 -25
- data/lib/knuckles/enhancer.rb +0 -23
- data/lib/knuckles/fetcher.rb +0 -32
- data/lib/knuckles/hydrator.rb +0 -31
- data/lib/knuckles/renderer.rb +0 -29
- data/lib/knuckles/writer.rb +0 -43
data/bench/profiling.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
require_relative "./bench_helper"
|
2
|
-
|
3
|
-
require "fileutils"
|
4
|
-
require "stackprof"
|
5
|
-
|
6
|
-
FileUtils.mkdir_p("tmp")
|
7
|
-
|
8
|
-
models = BenchHelper.submissions
|
9
|
-
|
10
|
-
StackProf.run(mode: :wall, interval: 500, out: "tmp/stackprof-wall.dump") do
|
11
|
-
100.times do
|
12
|
-
Knuckles.new.call(models, view: SubmissionView)
|
13
|
-
end
|
14
|
-
end
|
data/bench/realistic.rb
DELETED
data/bench/simple.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
require_relative "./bench_helper"
|
2
|
-
|
3
|
-
Post = Struct.new(:id, :title, :updated_at)
|
4
|
-
|
5
|
-
module PostView
|
6
|
-
extend Knuckles::View
|
7
|
-
|
8
|
-
def self.root
|
9
|
-
:posts
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.data(object, _)
|
13
|
-
{id: object.id,
|
14
|
-
title: object.title,
|
15
|
-
updated_at: object.updated_at}
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
models = 100.times.map { |i| Post.new(i, "title", Time.new) }
|
20
|
-
|
21
|
-
Benchmark.ips do |x|
|
22
|
-
x.report("serialize.main") do
|
23
|
-
Knuckles.new.call(models, view: PostView)
|
24
|
-
end
|
25
|
-
end
|
data/bin/rspec
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This file was generated by Bundler.
|
4
|
-
#
|
5
|
-
# The application 'rspec' is installed as part of a gem, and
|
6
|
-
# this file is here to facilitate running it.
|
7
|
-
#
|
8
|
-
|
9
|
-
require "pathname"
|
10
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
11
|
-
Pathname.new(__FILE__).realpath)
|
12
|
-
|
13
|
-
require "rubygems"
|
14
|
-
require "bundler/setup"
|
15
|
-
|
16
|
-
load Gem.bin_path("rspec-core", "rspec")
|
data/knuckles.gemspec
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require "knuckles/version"
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "knuckles"
|
8
|
-
spec.version = Knuckles::VERSION
|
9
|
-
spec.authors = ["Parker Selbert"]
|
10
|
-
spec.email = ["parker@sorentwo.com"]
|
11
|
-
spec.summary = "Simple performance aware data serialization"
|
12
|
-
spec.homepage = ""
|
13
|
-
spec.license = "MIT"
|
14
|
-
|
15
|
-
spec.files = `git ls-files -z`.split("\x0")
|
16
|
-
spec.executables = []
|
17
|
-
spec.test_files = spec.files.grep(%r{^(spec)/})
|
18
|
-
spec.require_paths = ["lib"]
|
19
|
-
|
20
|
-
spec.add_development_dependency "activesupport"
|
21
|
-
spec.add_development_dependency "bundler"
|
22
|
-
spec.add_development_dependency "rake"
|
23
|
-
spec.add_development_dependency "rspec"
|
24
|
-
end
|
data/lib/knuckles/combiner.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Knuckles
|
4
|
-
module Combiner
|
5
|
-
extend self
|
6
|
-
|
7
|
-
def name
|
8
|
-
"combiner"
|
9
|
-
end
|
10
|
-
|
11
|
-
def call(prepared, _)
|
12
|
-
prepared.each_with_object(array_backed_hash) do |hash, memo|
|
13
|
-
hash[:result].each do |root, values|
|
14
|
-
case values
|
15
|
-
when Hash then memo[root.to_s] << values
|
16
|
-
when Array then memo[root.to_s] += values
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def array_backed_hash
|
23
|
-
Hash.new { |hash, key| hash[key] = [] }
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
data/lib/knuckles/dumper.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Knuckles
|
4
|
-
module Dumper
|
5
|
-
extend self
|
6
|
-
|
7
|
-
def name
|
8
|
-
"dumper"
|
9
|
-
end
|
10
|
-
|
11
|
-
def call(objects, _options)
|
12
|
-
Knuckles.serializer.dump(keys_to_arrays(objects))
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def keys_to_arrays(objects)
|
18
|
-
objects.each do |_, value|
|
19
|
-
if value.is_a?(Array)
|
20
|
-
value.uniq! { |hash| hash["id"] || hash[:id] }
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/lib/knuckles/enhancer.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Knuckles
|
4
|
-
module Enhancer
|
5
|
-
extend self
|
6
|
-
|
7
|
-
def name
|
8
|
-
"enhancer"
|
9
|
-
end
|
10
|
-
|
11
|
-
def call(prepared, options)
|
12
|
-
enhancer = options[:enhancer]
|
13
|
-
|
14
|
-
if enhancer
|
15
|
-
prepared.each do |hash|
|
16
|
-
hash[:result] = enhancer.call(hash[:result], options)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
prepared
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/lib/knuckles/fetcher.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Knuckles
|
4
|
-
module Fetcher
|
5
|
-
extend self
|
6
|
-
|
7
|
-
def name
|
8
|
-
"fetcher"
|
9
|
-
end
|
10
|
-
|
11
|
-
def call(prepared, options)
|
12
|
-
results = get_cached(prepared, options)
|
13
|
-
|
14
|
-
prepared.each do |hash|
|
15
|
-
result = results[hash[:key]]
|
16
|
-
hash[:cached?] = !result.nil?
|
17
|
-
hash[:result] = result
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def get_cached(prepared, options)
|
24
|
-
kgen = options.fetch(:keygen, Knuckles.keygen)
|
25
|
-
keys = prepared.map do |hash|
|
26
|
-
hash[:key] = kgen.expand_key(hash[:object])
|
27
|
-
end
|
28
|
-
|
29
|
-
Knuckles.cache.read_multi(*keys)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
data/lib/knuckles/hydrator.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Knuckles
|
4
|
-
module Hydrator
|
5
|
-
extend self
|
6
|
-
|
7
|
-
def name
|
8
|
-
"hydrator"
|
9
|
-
end
|
10
|
-
|
11
|
-
def call(prepared, options)
|
12
|
-
hydrate = options[:hydrate]
|
13
|
-
|
14
|
-
if hydrate && any_missing?(prepared)
|
15
|
-
hydrate.call(hydratable(prepared))
|
16
|
-
end
|
17
|
-
|
18
|
-
prepared
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def any_missing?(prepared)
|
24
|
-
prepared.any? { |hash| !hash[:cached?] }
|
25
|
-
end
|
26
|
-
|
27
|
-
def hydratable(prepared)
|
28
|
-
prepared.reject { |hash| hash[:cached?] }
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
data/lib/knuckles/renderer.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Knuckles
|
4
|
-
module Renderer
|
5
|
-
extend self
|
6
|
-
|
7
|
-
def name
|
8
|
-
"renderer"
|
9
|
-
end
|
10
|
-
|
11
|
-
def call(objects, options)
|
12
|
-
view = options.fetch(:view)
|
13
|
-
|
14
|
-
objects.each do |hash|
|
15
|
-
unless hash[:cached?]
|
16
|
-
hash[:result] = do_render(hash[:object], view, options)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def do_render(object, view, options)
|
24
|
-
view.relations(object, options).merge!(
|
25
|
-
view.root => [view.data(object, options)]
|
26
|
-
)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
data/lib/knuckles/writer.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Knuckles
|
4
|
-
module Writer
|
5
|
-
extend self
|
6
|
-
|
7
|
-
def name
|
8
|
-
"writer"
|
9
|
-
end
|
10
|
-
|
11
|
-
def call(objects, _)
|
12
|
-
if cache.respond_to?(:write_multi)
|
13
|
-
write_multi(objects)
|
14
|
-
else
|
15
|
-
write_each(objects)
|
16
|
-
end
|
17
|
-
|
18
|
-
objects
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def cache
|
24
|
-
Knuckles.cache
|
25
|
-
end
|
26
|
-
|
27
|
-
def write_each(objects)
|
28
|
-
objects.each do |hash|
|
29
|
-
cache.write(hash[:key], hash[:result]) unless hash[:cached?]
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def write_multi(objects)
|
34
|
-
writable = objects.each_with_object({}) do |hash, memo|
|
35
|
-
next if hash[:cached?]
|
36
|
-
|
37
|
-
memo[hash[:key]] = hash[:result]
|
38
|
-
end
|
39
|
-
|
40
|
-
cache.write_multi(writable) if writable.any?
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|