graphql-result_cache 0.1.1 → 0.1.2

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: ba79fe918d359fba4d366fd3becfd4779860b3af1c4083c634578bba7258fbf9
4
- data.tar.gz: 814addd76ffa4ccb92a4641d27c58d71d0359005eff4e1bc9145cd6d47cf2b0b
3
+ metadata.gz: a82a463a163e049de4904d6c8ccc2dcd434ba9f2d9b8cc290a607691b7444086
4
+ data.tar.gz: a1614159c06e2924a3a11c082bae2668da3acd315ddc881ed70d01a9889ef6a5
5
5
  SHA512:
6
- metadata.gz: 7a8cb8d375f740c870acd94feaafded3d38e911acafa73573748ff63c49c9134e844488308a054ab601daafe56fa6af23a71bb9b7e4a68c7b3e27975d9a1a5f0
7
- data.tar.gz: 59ca4da7a641b8c66f8de5452c647cf56301a37ce5a62e0b0de4a02165d90749f594c5ad6b139fef361f18e7a2dd63f0bb2b2e1eea13590d5a77a99bcdd0e3e5
6
+ metadata.gz: f5437965558d61fbb534ac2cef46c51b70f9a1ba08550dc3aece6b474bb3501b7fbcd53a386f999f5efbe776c0e41fb56bef632c3a5c238687bd516fb6503a46
7
+ data.tar.gz: bf03d88d2fa2a4fab03522f1b14321ddf35076ae3781a4e545c0f683d25b5d1c5d03f25364fa74deb2c350f5becb9ba0b1c4cabf452b9a602cbb41b93cee640d
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- graphql-result_cache (0.1.0)
4
+ graphql-result_cache (0.1.2)
5
5
  graphql (~> 1.9)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -82,6 +82,18 @@ field :theme, Types::ThemeType, null: false, result_cache: { key: :theme_cache_k
82
82
  ```
83
83
  The `key` can be either a Symbol or a Proc.
84
84
 
85
+ ### Callback after cached result applied
86
+
87
+ An `after_process` callback can be provided, eg. when some dynamic values need to be amended after cached result applied.
88
+
89
+ ```ruby
90
+ field :theme, Types::ThemeType, null: false, result_cache: { after_process: :amend_dynamic_attributes }
91
+
92
+ def amend_dynamic_attributes(theme_node)
93
+ theme_node.merge! used_count: object.theme.used_count
94
+ end
95
+ ```
96
+
85
97
  ## Global Configuration
86
98
 
87
99
  `GraphQL::ResultCache` can be configured in initializer.
@@ -98,6 +110,18 @@ GraphQL::ResultCache.configure do |config|
98
110
  end
99
111
  ```
100
112
 
113
+ When the query is an introspection, you can set the value to avoid getting the nullable type for a non-null type.
114
+ ```ruby
115
+ class GraphqlController < ApplicationController
116
+ def execute
117
+ # ...
118
+ GraphQL::ResultCache.introspection = params[:query].include? '__schema'
119
+ result = MySchema.execute(params[:query], variables: ensure_hash(params[:variables]), context: context, operation_name: params[:operationName])
120
+ render json: GraphQL::ResultCache::Result.new(result)
121
+ end
122
+ end
123
+ ```
124
+
101
125
  ## Development
102
126
 
103
127
  After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -0,0 +1,22 @@
1
+ module GraphQL
2
+ module ResultCache
3
+ class Callback
4
+ def initialize obj:, args:, ctx:, value:
5
+ @obj = obj
6
+ @args = args
7
+ @ctx = ctx
8
+ @value = value
9
+ end
10
+
11
+ def call result_hash
12
+ case @value
13
+ when Symbol
14
+ @obj.public_send(@value, result_hash)
15
+ when Proc
16
+ @value.call(result_hash, @obj, @args, @ctx)
17
+ end
18
+ ::GraphQL::ResultCache.logger&.debug "GraphQL result cache callback called for #{@ctx.path.join('.')}"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -8,11 +8,16 @@ module GraphQL
8
8
  @value = {}
9
9
  end
10
10
 
11
- def add context:, key:
11
+ def add context:, key:, after_process: nil
12
12
  @value[context.query] ||= []
13
13
  cached = cache.exist? key
14
14
  logger&.info "GraphQL result cache key #{cached ? 'hit' : 'miss'}: #{key}"
15
- @value[context.query] << { path: context.path, key: key, result: cached ? cache.read(key) : nil }
15
+ config_value = { path: context.path, key: key }
16
+ if cached
17
+ config_value[:result] = cache.read(key)
18
+ config_value[:after_process] = after_process if after_process
19
+ end
20
+ @value[context.query] << config_value
16
21
  cached
17
22
  end
18
23
 
@@ -37,7 +42,9 @@ module GraphQL
37
42
  cache.write config[:key], result.dig('data', *config[:path]), expires_in: expires_in
38
43
  else
39
44
  # result already got from cache, need to amend to response
40
- deep_merge! result.to_h, 'data' => config[:path].reverse.inject(config[:result]) { |a, n| {n => a} }
45
+ result_hash = result.to_h
46
+ deep_merge! result_hash, 'data' => config[:path].reverse.inject(config[:result]) { |a, n| {n => a} }
47
+ config[:after_process]&.call(result_hash.dig('data', *config[:path]))
41
48
  end
42
49
  end
43
50
  result
@@ -1,6 +1,7 @@
1
1
  require 'graphql/result_cache/condition'
2
2
  require 'graphql/result_cache/context_config'
3
3
  require 'graphql/result_cache/key'
4
+ require 'graphql/result_cache/callback'
4
5
 
5
6
  module GraphQL
6
7
  module ResultCache
@@ -11,8 +12,7 @@ module GraphQL
11
12
  cached_resolve_proc = cached_resolve(field)
12
13
  field.redefine do
13
14
  resolve(cached_resolve_proc)
14
- # for cacheable field, change type to be nullable
15
- type(field.type.of_type) if field.type.non_null?
15
+ type(field.type.of_type) if !::GraphQL::ResultCache.introspection? && field.type.non_null?
16
16
  end
17
17
  end
18
18
 
@@ -26,7 +26,8 @@ module GraphQL
26
26
  if Condition.new(cache_config, obj: obj, args: args, ctx: ctx).true?
27
27
  ctx[:result_cache] ||= ContextConfig.new
28
28
  cache_key = Key.new(obj: obj, args: args, ctx: ctx, key: cache_config[:key])
29
- cached = ctx[:result_cache].add context: ctx, key: cache_key.to_s
29
+ after_process = Callback.new(obj: obj, args: args, ctx: ctx, value: cache_config[:after_process]) if cache_config[:after_process]
30
+ cached = ctx[:result_cache].add context: ctx, key: cache_key.to_s, after_process: after_process
30
31
  end
31
32
  old_resolve_proc.call(obj, args, ctx) unless cached
32
33
  end
@@ -21,7 +21,7 @@ module GraphQL
21
21
  private
22
22
 
23
23
  def path_clause
24
- @ctx.path.join('/')
24
+ @ctx.path.join('.')
25
25
  end
26
26
 
27
27
  def args_clause
@@ -1,5 +1,5 @@
1
1
  module GraphQL
2
2
  module ResultCache
3
- VERSION = '0.1.1'
3
+ VERSION = '0.1.2'
4
4
  end
5
5
  end
@@ -16,6 +16,9 @@ module GraphQL
16
16
  # c.client_hash = -> { Rails.cache.read(:deploy_version) }
17
17
  attr_accessor :client_hash
18
18
 
19
+ attr_accessor :introspection
20
+ alias introspection? introspection
21
+
19
22
  # ```
20
23
  # GraphQL::ResultCache.configure do |c|
21
24
  # c.namespace = "GraphQL:Result"
@@ -31,6 +34,7 @@ module GraphQL
31
34
  # Default configuration
32
35
  @expires_in = 3600 # 1.hour
33
36
  @namespace = 'GraphQL:Result'
37
+ @introspection = false
34
38
 
35
39
  def self.use(schema_def, options: {})
36
40
  schema_def.instrument(:field, ::GraphQL::ResultCache::FieldInstrument.new)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-result_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ying Fu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-17 00:00:00.000000000 Z
11
+ date: 2019-08-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -85,6 +85,7 @@ files:
85
85
  - bin/setup
86
86
  - graphql-result_cache.gemspec
87
87
  - lib/graphql/result_cache.rb
88
+ - lib/graphql/result_cache/callback.rb
88
89
  - lib/graphql/result_cache/condition.rb
89
90
  - lib/graphql/result_cache/context_config.rb
90
91
  - lib/graphql/result_cache/field.rb