graphql-persisted_queries 0.1.3 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8b56768c7a951fcc1f1ef63fb0bcbe054c900b0a5636579b811f5e858ed1e57b
4
- data.tar.gz: 512044a14538d39037d5092860a739646771b5ad4d9deca2df522ce9ba1ef657
3
+ metadata.gz: 3121fbd184f715130c9f9f1956dcd89c24d52507d23ac0b35a408a9d53d54e72
4
+ data.tar.gz: 7e4b32a6b5d0fda8d9b135a435bca92587749ccb61664f37092c593ef4b04eb0
5
5
  SHA512:
6
- metadata.gz: f6359ac33469754e332377d2c5c945cf5ce94c13609efeb603f9d2d6b5db8c08af58c290cec1ca9aa85ff048894ff1edd61a517069348ac2ea6144e7c12f8291
7
- data.tar.gz: fe4f663992844109589ab001fe394e5c562f75c9eba9b95c6733f6b264a4531657a57952d7b10a30cb7692184592fa46b51cbfc89686dea358f7cbd061de3fd7
6
+ metadata.gz: a42f753183b5d8aa8c0d8f321a988b61375ad6ae828ef9c232e91f4f20adb5da824b6b095cb034af805e11039f5c7122d52add4cdb4caa36bb873335a85e5847
7
+ data.tar.gz: 539d3e7da1bed8a470555b2b411cd52a6631663e7f3927e0c9252988488800c205bfe10f4eb03b3baa34899e286420b9d743f411fefc54c9dc091a1406d75a96
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.2.0 (2020-02-11)
6
+
7
+ - [PR#17](https://github.com/DmitryTsepelev/graphql-ruby-persisted_queries/pull/17) Allow an optional custom error handler so that implementors can control failure scenarios when query resolution fails ([@bmorton][])
8
+
5
9
  ## 0.1.3 (2020-01-30)
6
10
 
7
11
  - [PR#15](https://github.com/DmitryTsepelev/graphql-ruby-persisted_queries/pull/15) Allow optional custom expiration and namespace for Redis store ([@bmorton][])
data/README.md CHANGED
@@ -115,6 +115,33 @@ class GraphqlSchema < GraphQL::Schema
115
115
  end
116
116
  ```
117
117
 
118
+ ## Error handling
119
+
120
+ You may optionally specify an object that will be called whenever an error occurs while attempting to resolve or save a query. This will give you the opportunity to both handle (e.g. graceful Redis failure) and/or log the error. By default, errors will be raised when a failure occurs within a `StoreAdapter`.
121
+
122
+ An error handler can be a proc or an implementation of `GraphQL::PersistedQueries::ErrorHandlers::BaseErrorHandler`. Here's an example for treating Redis failures as cache misses:
123
+
124
+ ```ruby
125
+ class GracefulRedisErrorHandler < GraphQL::PersistedQueries::ErrorHandlers::BaseErrorHandler
126
+ def call(error)
127
+ case error
128
+ when Redis::BaseError
129
+ # Treat Redis errors as a cache miss, but you should log the error into
130
+ # your instrumentation framework here.
131
+ else
132
+ raise error
133
+ end
134
+
135
+ # Return nothing to ensure handled errors are treated as cache misses
136
+ return
137
+ end
138
+ end
139
+
140
+ class GraphqlSchema < GraphQL::Schema
141
+ use GraphQL::PersistedQueries, error_handler: GracefulRedisErrorHandler.new
142
+ end
143
+ ```
144
+
118
145
  ## GET requests and HTTP cache
119
146
 
120
147
  Using `GET` requests for persisted queries allows you to enable HTTP caching (e.g., turn on CDN). In order to make it work you should change the way link is initialized on front-end side (`createPersistedQueryLink({ useGETForHashedQueries: true })`) and register a new route `get "/graphql", to: "graphql#execute"`.
@@ -1,17 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/persisted_queries/error_handlers"
3
4
  require "graphql/persisted_queries/schema_patch"
4
5
  require "graphql/persisted_queries/store_adapters"
5
6
  require "graphql/persisted_queries/version"
7
+ require "graphql/persisted_queries/builder_helpers"
6
8
 
7
9
  module GraphQL
8
10
  # Plugin definition
9
11
  module PersistedQueries
10
- def self.use(schema_defn, store: :memory, hash_generator: :sha256, **options)
12
+ def self.use(schema_defn, store: :memory, hash_generator: :sha256,
13
+ error_handler: :default, **options)
11
14
  schema = schema_defn.is_a?(Class) ? schema_defn : schema_defn.target
12
15
 
13
16
  schema.singleton_class.prepend(SchemaPatch)
14
17
  schema.hash_generator = hash_generator
18
+ schema.configure_persisted_query_error_handler(error_handler)
15
19
  schema.configure_persisted_query_store(store, options)
16
20
  end
17
21
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module PersistedQueries
5
+ # Contains factory methods for error handlers
6
+ module BuilderHelpers
7
+ def self.camelize(name)
8
+ name.to_s.split("_").map(&:capitalize).join
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "graphql/persisted_queries/error_handlers/base_error_handler"
4
+ require "graphql/persisted_queries/error_handlers/default_error_handler"
5
+
6
+ module GraphQL
7
+ module PersistedQueries
8
+ # Contains factory methods for error handlers
9
+ module ErrorHandlers
10
+ def self.build(handler, options = nil)
11
+ if handler.is_a?(ErrorHandlers::BaseErrorHandler)
12
+ handler
13
+ elsif handler.is_a?(Proc)
14
+ build_from_proc(handler)
15
+ else
16
+ build_by_name(handler, options)
17
+ end
18
+ end
19
+
20
+ def self.build_from_proc(proc)
21
+ if proc.arity != 1
22
+ raise ArgumentError, "proc passed to :error_handler should have exactly one argument"
23
+ end
24
+
25
+ proc
26
+ end
27
+
28
+ def self.build_by_name(name, options)
29
+ const_get("#{BuilderHelpers.camelize(name)}ErrorHandler").new(options || {})
30
+ rescue NameError => e
31
+ raise e.class, "Persisted query error handler for :#{name} haven't been found", e.backtrace
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module PersistedQueries
5
+ module ErrorHandlers
6
+ # Base class for all error handlers
7
+ class BaseErrorHandler
8
+ def initialize(_options); end
9
+
10
+ def call(_error)
11
+ raise NotImplementedError
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module PersistedQueries
5
+ module ErrorHandlers
6
+ # Default error handler for simply re-raising the error
7
+ class DefaultErrorHandler < BaseErrorHandler
8
+ def call(error)
9
+ raise error
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -18,10 +18,11 @@ module GraphQL
18
18
  end
19
19
  end
20
20
 
21
- def initialize(extensions, store, hash_generator_proc)
21
+ def initialize(extensions, store, hash_generator_proc, error_handler)
22
22
  @extensions = extensions
23
23
  @store = store
24
24
  @hash_generator_proc = hash_generator_proc
25
+ @error_handler = error_handler
25
26
  end
26
27
 
27
28
  def resolve(query_str)
@@ -30,7 +31,7 @@ module GraphQL
30
31
  if query_str
31
32
  persist_query(query_str)
32
33
  else
33
- query_str = @store.fetch_query(hash)
34
+ query_str = with_error_handling { @store.fetch_query(hash) }
34
35
  raise NotFound if query_str.nil?
35
36
  end
36
37
 
@@ -39,10 +40,16 @@ module GraphQL
39
40
 
40
41
  private
41
42
 
43
+ def with_error_handling
44
+ yield
45
+ rescue StandardError => e
46
+ @error_handler.call(e)
47
+ end
48
+
42
49
  def persist_query(query_str)
43
50
  raise WrongHash if @hash_generator_proc.call(query_str) != hash
44
51
 
45
- @store.save_query(hash, query_str)
52
+ with_error_handling { @store.save_query(hash, query_str) }
46
53
  end
47
54
 
48
55
  def hash
@@ -7,19 +7,24 @@ module GraphQL
7
7
  module PersistedQueries
8
8
  # Patches GraphQL::Schema to support persisted queries
9
9
  module SchemaPatch
10
- attr_reader :persisted_query_store, :hash_generator_proc
10
+ attr_reader :persisted_query_store, :hash_generator_proc, :persisted_query_error_handler
11
11
 
12
12
  def configure_persisted_query_store(store, options)
13
13
  @persisted_query_store = StoreAdapters.build(store, options)
14
14
  end
15
15
 
16
+ def configure_persisted_query_error_handler(handler)
17
+ @persisted_query_error_handler = ErrorHandlers.build(handler)
18
+ end
19
+
16
20
  def hash_generator=(hash_generator)
17
21
  @hash_generator_proc = HashGeneratorBuilder.new(hash_generator).build
18
22
  end
19
23
 
20
24
  def execute(query_str = nil, **kwargs)
21
25
  if (extensions = kwargs.delete(:extensions))
22
- resolver = Resolver.new(extensions, persisted_query_store, hash_generator_proc)
26
+ resolver = Resolver.new(extensions, persisted_query_store, hash_generator_proc,
27
+ persisted_query_error_handler)
23
28
  query_str = resolver.resolve(query_str)
24
29
  end
25
30
 
@@ -17,9 +17,7 @@ module GraphQL
17
17
  end
18
18
 
19
19
  def self.build_by_name(name, options)
20
- camelized_adapter = name.to_s.split("_").map(&:capitalize).join
21
- adapter_class_name = "#{camelized_adapter}StoreAdapter"
22
- StoreAdapters.const_get(adapter_class_name).new(options || {})
20
+ const_get("#{BuilderHelpers.camelize(name)}StoreAdapter").new(options || {})
23
21
  rescue NameError => e
24
22
  raise e.class, "Persisted query store adapter for :#{name} haven't been found", e.backtrace
25
23
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GraphQL
4
4
  module PersistedQueries
5
- VERSION = "0.1.3"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-persisted_queries
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - DmitryTsepelev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-01-31 00:00:00.000000000 Z
11
+ date: 2020-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -117,6 +117,10 @@ files:
117
117
  - gemfiles/graphql_master.gemfile
118
118
  - graphql-persisted_queries.gemspec
119
119
  - lib/graphql/persisted_queries.rb
120
+ - lib/graphql/persisted_queries/builder_helpers.rb
121
+ - lib/graphql/persisted_queries/error_handlers.rb
122
+ - lib/graphql/persisted_queries/error_handlers/base_error_handler.rb
123
+ - lib/graphql/persisted_queries/error_handlers/default_error_handler.rb
120
124
  - lib/graphql/persisted_queries/hash_generator_builder.rb
121
125
  - lib/graphql/persisted_queries/resolver.rb
122
126
  - lib/graphql/persisted_queries/schema_patch.rb