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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/README.md +40 -13
  4. data/lib/knuckles/keygen.rb +22 -0
  5. data/lib/knuckles/pipeline.rb +82 -26
  6. data/lib/knuckles/stages/combiner.rb +24 -0
  7. data/lib/knuckles/stages/dumper.rb +23 -0
  8. data/lib/knuckles/stages/enhancer.rb +21 -0
  9. data/lib/knuckles/stages/fetcher.rb +30 -0
  10. data/lib/knuckles/stages/hydrator.rb +29 -0
  11. data/lib/knuckles/stages/renderer.rb +27 -0
  12. data/lib/knuckles/stages/writer.rb +41 -0
  13. data/lib/knuckles/stages.rb +13 -0
  14. data/lib/knuckles/version.rb +1 -1
  15. data/lib/knuckles/view.rb +104 -5
  16. data/lib/knuckles.rb +55 -7
  17. data/spec/knuckles/pipeline_spec.rb +0 -40
  18. data/spec/knuckles/{combiner_spec.rb → stages/combiner_spec.rb} +2 -2
  19. data/spec/knuckles/{dumper_spec.rb → stages/dumper_spec.rb} +2 -2
  20. data/spec/knuckles/{enhancer_spec.rb → stages/enhancer_spec.rb} +3 -3
  21. data/spec/knuckles/{fetcher_spec.rb → stages/fetcher_spec.rb} +3 -3
  22. data/spec/knuckles/{hydrator_spec.rb → stages/hydrator_spec.rb} +3 -3
  23. data/spec/knuckles/{renderer_spec.rb → stages/renderer_spec.rb} +2 -2
  24. data/spec/knuckles/{writer_spec.rb → stages/writer_spec.rb} +3 -3
  25. metadata +31 -43
  26. data/.gitignore +0 -15
  27. data/.rspec +0 -2
  28. data/.rubocop.yml +0 -41
  29. data/.travis.yml +0 -10
  30. data/Gemfile +0 -11
  31. data/Rakefile +0 -9
  32. data/bench/bench_helper.rb +0 -48
  33. data/bench/fixtures/serializers.rb +0 -93
  34. data/bench/fixtures/submissions.json +0 -1
  35. data/bench/profiling.rb +0 -14
  36. data/bench/realistic.rb +0 -9
  37. data/bench/simple.rb +0 -25
  38. data/bin/rspec +0 -16
  39. data/knuckles.gemspec +0 -24
  40. data/lib/knuckles/combiner.rb +0 -26
  41. data/lib/knuckles/dumper.rb +0 -25
  42. data/lib/knuckles/enhancer.rb +0 -23
  43. data/lib/knuckles/fetcher.rb +0 -32
  44. data/lib/knuckles/hydrator.rb +0 -31
  45. data/lib/knuckles/renderer.rb +0 -29
  46. 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
@@ -1,9 +0,0 @@
1
- require_relative "./bench_helper"
2
-
3
- models = BenchHelper.submissions
4
-
5
- Benchmark.ips do |x|
6
- x.report("serialize.realistic") do
7
- Knuckles.new.call(models, view: SubmissionView)
8
- end
9
- end
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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