knuckles 0.2.0 → 0.3.0

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