knuckles 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|