Giter Club home page Giter Club logo

graphql-ruby-persisted_queries's Introduction

Hi! 👋

My name is Dmitry and I'm a backend engineer focusing on Ruby, Rails, PostgreSQL and GraphQL. I prefer working on arhitectural, performance and developer experience (i.e., custom linters, CI actions, etc.) tasks. At my free time I'm playing with Go, Rust and Haskell.

I contribute to various open–source projects (Ruby on Rails, graphql-ruby, GitLab, prism and many more). Also, I maintain my own libraries — check them out pinned right below.

Featured articles and conference talks:

You can find me on Twitter and LinkedIn.

graphql-ruby-persisted_queries's People

Contributors

artplan1 avatar bmorton avatar dmitrytsepelev avatar janstevens avatar louim avatar ogidow avatar olleolleolle avatar rbviz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

graphql-ruby-persisted_queries's Issues

graphql-ruby 1.10.0 update breaks the gem

Looks like a similar issue to graphql-guard#36 and graphql-batch#116:

NoMethodError:
  undefined method `target' for SomeSchema:Class
# ./.bundle/gems/graphql-persisted_queries-0.1.1/lib/graphql/persisted_queries.rb:11:in `use'
# ./.bundle/gems/graphql-1.10.0/lib/graphql/schema.rb:861:in `use'
# ./app/graphql/some_schema.rb:14:in `<class:SomeSchema>'
# ./app/graphql/some_schema.rb:3:in `<top (required)>'

Squish queries

Hello,

I was thinking of adding squish when storing queries. There is no point in saving line brakes or spaces.

Downside is that there is of course a difference in the hash (not sure if that is a problem or not)

Squish from rails could be implemented as

def squish(query)
  query.gsub(/[[:space:]]+/, " ").strip
end

Skip the redis_client argument when ENV["REDIS_URL"] is defined.

Hey!

it is possible to completely skip the redis_client argument when ENV["REDIS_URL"] is defined?

What I tried:

use GraphQL::PersistedQueries,
      compiled_queries: true,
      store: :redis

but it raises an error:

missing keyword: redis_client
/Users/louim/.asdf/installs/ruby/2.6.6/lib/ruby/gems/2.6.0/gems/graphql-persisted_queries-1.2.2/lib/graphql/persisted_queries/store_adapters/redis_with_local_cache_store_adapter.rb:11:in `initialize'
/Users/louim/.asdf/installs/ruby/2.6.6/lib/ruby/gems/2.6.0/gems/graphql-persisted_queries-1.2.2/lib/graphql/persisted_queries/store_adapters.rb:22:in `new'
/Users/louim/.asdf/installs/ruby/2.6.6/lib/ruby/gems/2.6.0/gems/graphql-persisted_queries-1.2.2/lib/graphql/persisted_queries/store_adapters.rb:22:in `build_by_name'
/Users/louim/.asdf/installs/ruby/2.6.6/lib/ruby/gems/2.6.0/gems/graphql-persisted_queries-1.2.2/lib/graphql/persisted_queries/store_adapters.rb:17:in `build'
/Users/louim/.asdf/installs/ruby/2.6.6/lib/ruby/gems/2.6.0/gems/graphql-persisted_queries-1.2.2/lib/graphql/persisted_queries/schema_patch.rb:33:in `configure_persisted_query_store'
/Users/louim/.asdf/installs/ruby/2.6.6/lib/ruby/gems/2.6.0/gems/graphql-persisted_queries-1.2.2/lib/graphql/persisted_queries.rb:36:in `use'
/Users/louim/.asdf/installs/ruby/2.6.6/lib/ruby/gems/2.6.0/gems/graphql-1.12.8/lib/graphql/schema.rb:935:in `use'

I ended up using an empty hash. but it feels a bit weird. Would it be possible to completely skip the redis_client?

  use GraphQL::PersistedQueries,
      compiled_queries: true,
      store: :redis,
      redis_client: {}

In-memory backed RedisStore

It seems like the cache entries that are stored to Redis can be long lived and don't need to be invalidated (the hash will always resolve to the same query), so we are looking at using the Redis implementation but caching Redis lookups locally to avoid the network call when possible. It's essentially a combination of the in-memory adapter with the redis adapter.

I can think of three options for implementing this:

  1. Add this support to the RedisStore so a config option can be passed to allow local caching
  2. In my project, create a new LocalCachedRedisStore that takes a RedisStore and an in-memory store and does both
  3. Same as 2, but included with this repo instead of directly in my project

Do you have a preference here? Should I keep this to my project alone or would you accept a PR for something like this?

[graphql-ruby 1.10] Resolve error when extending a schema class

Hi, thank you for this gem.

I'm getting errors from resolver when extending schema classes and using this gem.

Example setup:

class ApplicationSchema < GraphQL::Schema
  use ::GraphQL::PersistedQueries,
    store: :redis,
    redis_client: Redis.current
end

class MySchema < ApplicationSchema
end

Error log:

NoMethodError (undefined method `call' for nil:NilClass):
graphql-persisted_queries (0.5.0) lib/graphql/persisted_queries/resolver.rb:44:in `rescue in with_error_handling'
graphql-persisted_queries (0.5.0) lib/graphql/persisted_queries/resolver.rb:41:in `with_error_handling'
graphql-persisted_queries (0.5.0) lib/graphql/persisted_queries/resolver.rb:32:in `resolve'
graphql-persisted_queries (0.5.0) lib/graphql/persisted_queries/multiplex_resolver.rb:35:in `resolve_persisted_query'
graphql-persisted_queries (0.5.0) lib/graphql/persisted_queries/multiplex_resolver.rb:27:in `block in resolve_persisted_queries'
graphql-persisted_queries (0.5.0) lib/graphql/persisted_queries/multiplex_resolver.rb:26:in `each'
graphql-persisted_queries (0.5.0) lib/graphql/persisted_queries/multiplex_resolver.rb:26:in `each_with_index'
graphql-persisted_queries (0.5.0) lib/graphql/persisted_queries/multiplex_resolver.rb:26:in `resolve_persisted_queries'
graphql-persisted_queries (0.5.0) lib/graphql/persisted_queries/multiplex_resolver.rb:14:in `resolve'
graphql-persisted_queries (0.5.0) lib/graphql/persisted_queries/schema_patch.rb:52:in `multiplex'
graphql (1.10.5) lib/graphql/schema.rb:1546:in `execute'

It looks that any patches applied in SchemaPatch are not passed to extended classes and @schema.persisted_query_store, @schema.persisted_query_error_handler return nil.

Deprecation warning on usage of `Schema.instrument`

We're getting the following deprecation warning in our app after upgrading the graphql gem to a newer version:

Schema.instrument is deprecated, use `trace_with` instead: https://graphql-ruby.org/queries/tracing.html"
  (From `DeviceApi::V1::Schema.instrument(query, GraphQL::PersistedQueries::CompiledQueries::Instrumentation)` at /home/runner/work/rails_core/rails_core/vendor/bundle/ruby/3.2.0/gems/graphql-persisted_queries-1.7.0/lib/graphql/persisted_queries/schema_patch.rb:18:in `patch')

Support for snake_case

Looking at the code, we can see that the library traverses the code in camel-case such as the function below:
def hash @hash ||= @extensions.dig("persistedQuery", "sha256Hash") end
Is it possible for you to add functionality to also handle the case where the extensions object is passed through as snake_case?

undefined method ensure_hash

Hi ,I'm graphql beginner.

I tried persisted_queries based on this repository's README.

This is my demo repository.
https://github.com/hamilton-keisuke/graphql-apollo-rails-demo

Main tool ver is here

[Ruby]
ruby 3.0.1
graphql-ruby-persisted_queries 1.5.0
graphql-ruby 2.0.7

[js]
apollo/client 3.5.10
node 16.14.2

I encountered such error, undefined method ensure_hash'`.

=> Booting Puma
=> Rails 7.0.2.3 application starting in development
=> Run bin/rails server --help for more startup options
Puma starting in single mode...
* Puma version: 5.6.4 (ruby 3.0.1-p64) ("Birdie's Version")
* Min threads: 5
* Max threads: 5
* Environment: development
* PID: 1289
* Listening on http://0.0.0.0:3000/
Use Ctrl-C to stop
Started POST "/graphql" for 172.18.0.1 at 2022-04-26 04:32:51 +0000
   (3.2ms) SELECT sqlite_version(*)
  ActiveRecord::SchemaMigration Pluck (1.4ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
Processing by GraphqlController#execute as /
  Parameters: {"variables"=>{}, "extensions"=>{"persistedQuery"=>{"version"=>1, "sha256Hash"=>"a5374361d3c49fdb5bd35b9bfc5f459fb799076cf6e343299d0ae1fd09cc9373"}}, "graphql"=>{"variables"=>{}, "extensions"=>{"persistedQuery"=>{"version"=>1, "sha256Hash"=>"a5374361d3c49fdb5bd35b9bfc5f459fb799076cf6e343299d0ae1fd09cc9373"}}}}
undefined method `ensure_hash' for #<GraphqlController:0x00000000008660>
Did you mean? ensure
/app/app/controllers/graphql_controller.rb:8:in `execute'

How can I sove it?

Adding some additional metadata in cache-store along with the query itself and its hash.

Hey @DmitryTsepelev , thank you very much for this great gem. We would like to use this gem in our project but I have a quick question. We have a rate limiter depending on GraphQL query's complexity. For instance, we are doing static analysis to measure the cost of the query before executing it via resolvers. Disabling the analysis, or caching the query won't help us here. I wish there was an API that helps to save some metadata to memory or any cache store along with the query or its hash. What I mean here is that saving some metadata is saving the cost, complexity, and the query with a simple json or hash data structure on Redis side so that when client hits the server with the hash I can retrieve the cached cost or the metadata from the cache-store.

If this gem does not cover our needs, I would like to implement it and send a pull request. Your guidance is welcome since I am not familiar with API.

Thank you again for the great work.

Undefined method `using_ast_analysis?' for class

Hi there!

After the last update, we started to get the exception below.

The stacktrace shows an issue in the persisted-queries module.

Thanks in advance.

bundle list|grep graphql                                                                                                                                          [20:02:14]
  * graphql (2.3.14)
  * graphql-batch (0.6.0)
  * graphql-persisted_queries (1.8.1)
  * graphql_devise (1.5.0)
  * rubocop-graphql (1.5.4)
     NoMethodError:
       undefined method `using_ast_analysis?' for class OurSchemaClass
     # gems/graphql-persisted_queries-1.8.1/lib/graphql/persisted_queries/schema_patch.rb:101:in `prepare_analyzer'
     # gems/graphql-persisted_queries-1.8.1/lib/graphql/persisted_queries/schema_patch.rb:81:in `verify_http_method='
     # gems/graphql-persisted_queries-1.8.1/lib/graphql/persisted_queries.rb:28:in `use'
     # gems/graphql-2.3.11/lib/graphql/schema.rb:327:in `use'

Error in redis_with_local_cache

class WebSchema < GraphQL::Schema
  mutation(Types::MutationType)
  query(Types::QueryType)

  use GraphQL::PersistedQueries,
      store: :redis_with_local_cache,
      redis_client: { redis_url: Rails.application.config.x.redis.url },
      expiration: 2_592_000, # 30 days
      compiled_queries: true
end
 8: from /vendor/bundle/ruby/2.5.0/gems/graphql-1.12.8/lib/graphql/schema.rb:935:in `use'
 7: from /vendor/bundle/ruby/2.5.0/gems/graphql-persisted_queries-1.2.1/lib/graphql/persisted_queries.rb:36:in `use'
 6: from /vendor/bundle/ruby/2.5.0/gems/graphql-persisted_queries-1.2.1/lib/graphql/persisted_queries/schema_patch.rb:33:in `configure_persisted_query_store'
 5: from /vendor/bundle/ruby/2.5.0/gems/graphql-persisted_queries-1.2.1/lib/graphql/persisted_queries/store_adapters.rb:17:in `build'
 4: from /vendor/bundle/ruby/2.5.0/gems/graphql-persisted_queries-1.2.1/lib/graphql/persisted_queries/store_adapters.rb:22:in `build_by_name'
 3: from /vendor/bundle/ruby/2.5.0/gems/graphql-persisted_queries-1.2.1/lib/graphql/persisted_queries/store_adapters.rb:22:in `new'
 2: from /vendor/bundle/ruby/2.5.0/gems/graphql-persisted_queries-1.2.1/lib/graphql/persisted_queries/store_adapters/redis_with_local_cache_store_adapter.rb:21:in `initialize'
 1: from /vendor/bundle/ruby/2.5.0/gems/graphql-persisted_queries-1.2.1/lib/graphql/persisted_queries/store_adapters/redis_with_local_cache_store_adapter.rb:21:in `new'

/vendor/bundle/ruby/2.5.0/gems/graphql-persisted_queries-1.2.1/lib/graphql/persisted_queries/store_adapters/memory_store_adapter.rb:8:in `initialize': wrong number of arguments (given 1, expected 0) (ArgumentError)

Instrumentation

I’ve been looking at how to tie this gem into our instrumentation framework and I think it might be worth implementing something in the gem that allows an instrumenter to be configured that could accept events for things like “cache miss.” I also have considered ActiveSupport::Notifications to do this, but not sure how you feel about taking a dependency on that (or perhaps an optional dependency).

Have you thought about this? Would you accept a PR for this?

Compiled Queries are not saved in `1.6.0`

graphql (1.13.16)
graphql-ruby-persisted_queries (1.6.0)

Today I was exploring graphql-ruby-persisted_queries but could not for the life of me get my queries to ever save to Redis. After doing some digging around, I noticed that before_query was being called after prepare_ast.

        def prepare_ast
          return super unless @context[:extensions]

          super.tap do
            if @context.errors.any?(&method(:not_found_error?))
              @context.errors.select!(&method(:not_found_error?))
            end

            resolver.persist(query_string, @document) if @not_loaded_document && query_string
          end
        end

Because of that, in the following line:

resolver.persist(query_string, @document) if @not_loaded_document && query_string

@not_loaded_document always returned nil since the expectation is that the before_query callback sets it, but that callback has not been called yet, and my queries were never saved.

After downgrading the gem to 1.5.1 everything appears to be working like a charm.

It is definitely possible that there is some setup error on my end.

HttpMethodAnalyzer not compatible with Interpreter runtime

When using HTTP Caching with verify_http_method: true, I get the error below.

Error log:

NoMethodError (undefined method `new' for #<GraphQL::PersistedQueries::HttpMethodAnalyzer:0x0000559aff07f540>):
  
graphql (1.10.5) lib/graphql/analysis/ast.rb:58:in `block (2 levels) in analyze_query'
graphql (1.10.5) lib/graphql/analysis/ast.rb:58:in `map'
graphql (1.10.5) lib/graphql/analysis/ast.rb:58:in `block in analyze_query'
graphql (1.10.5) lib/graphql/tracing.rb:67:in `block in trace'
graphql (1.10.5) lib/graphql/tracing.rb:81:in `call_tracers'
graphql (1.10.5) lib/graphql/tracing.rb:67:in `trace'
graphql (1.10.5) lib/graphql/analysis/ast.rb:56:in `analyze_query'
graphql (1.10.5) lib/graphql/analysis/ast.rb:32:in `block (2 levels) in analyze_multiplex'
graphql (1.10.5) lib/graphql/analysis/ast.rb:30:in `map'
graphql (1.10.5) lib/graphql/analysis/ast.rb:30:in `block in analyze_multiplex'
graphql (1.10.5) lib/graphql/tracing.rb:67:in `block in trace'
graphql (1.10.5) lib/graphql/tracing.rb:81:in `call_tracers'
graphql (1.10.5) lib/graphql/tracing.rb:67:in `trace'
graphql (1.10.5) lib/graphql/analysis/ast.rb:29:in `analyze_multiplex'
graphql (1.10.5) lib/graphql/execution/multiplex.rb:195:in `block in instrument_and_analyze'
graphql (1.10.5) lib/graphql/execution/instrumentation.rb:29:in `block (2 levels) in apply_instrumenters'
graphql (1.10.5) lib/graphql/execution/instrumentation.rb:46:in `block (2 levels) in each_query_call_hooks'
graphql (1.10.5) lib/graphql/execution/instrumentation.rb:41:in `each_query_call_hooks'
graphql (1.10.5) lib/graphql/execution/instrumentation.rb:45:in `block in each_query_call_hooks'
graphql (1.10.5) lib/graphql/execution/instrumentation.rb:72:in `call_hooks'
graphql (1.10.5) lib/graphql/execution/instrumentation.rb:44:in `each_query_call_hooks'
graphql (1.10.5) lib/graphql/execution/instrumentation.rb:27:in `block in apply_instrumenters'
graphql (1.10.5) lib/graphql/execution/instrumentation.rb:72:in `call_hooks'
graphql (1.10.5) lib/graphql/execution/instrumentation.rb:26:in `apply_instrumenters'
graphql (1.10.5) lib/graphql/execution/multiplex.rb:175:in `instrument_and_analyze'
graphql (1.10.5) lib/graphql/execution/multiplex.rb:61:in `block in run_queries'
graphql (1.10.5) lib/graphql/tracing.rb:67:in `block in trace'
graphql (1.10.5) lib/graphql/tracing.rb:81:in `call_tracers'
graphql (1.10.5) lib/graphql/tracing.rb:67:in `trace'
graphql (1.10.5) lib/graphql/execution/multiplex.rb:59:in `run_queries'
graphql (1.10.5) lib/graphql/execution/multiplex.rb:49:in `run_all'
graphql (1.10.5) lib/graphql/schema.rb:1575:in `multiplex'
graphql-persisted_queries (0.5.0) lib/graphql/persisted_queries/multiplex_resolver.rb:42:in `perform_multiplex'
graphql-persisted_queries (0.5.0) lib/graphql/persisted_queries/multiplex_resolver.rb:15:in `resolve'
graphql-persisted_queries (0.5.0) lib/graphql/persisted_queries/schema_patch.rb:52:in `multiplex'
graphql (1.10.5) lib/graphql/schema.rb:1546:in `execute'

The GraphQL::Analysis::AST plugin, that is required to use GraphQL::Execution::Interpreter expects analyzers to be classes and not instances as can be seen here and graphql-persisted-queries creates instances here.

The AST analyzers seem to have a different interface from plain analyzers and I think a separate analyzer that inherits GraphQL::Analysis::AST::Analyzer is needed.

Compiled queries broken with latest graphql gem

The recently released graphql gem 2.0.14 has some refactors that seem to have broken persisted queries when compiled queries are enabled.

Queries using persisted queries result in "No query string was present" error:
#<GraphQL::Query::Result @query=... @to_h={"errors"=>[{"message"=>"No query string was present"}]}>

If I set compiled_queries: false on use GraphQL::PersistedQueries then everything works normally so I'm using that as workaround for now.

My versions:
graphql (2.0.14)
graphql-persisted_queries (1.5.0)

Handling Redis failures

I noticed if there's something wrong with making requests to Redis (like an incorrect password, for example), an exception is raised. I think for my use case I'd like Redis errors to be treated as a cache miss. I was looking into implementing this at the RedisStoreAdapter level with an option for failures_as_cache_miss or something similar.

Would you accept a PR for something like this? Do you have thoughts on how you'd want this implemented? Or should I build my own Redis adapter for this separately from the gem?

Doesn't work on graphql (2.2.5)

Hey all,

I am working through an upgrade from graphql (1.13.15) to graphql (2.2.5) on a personal project and i'm running into an issue where APQs are not working anymore. I get an error: No query string was present exclusively when I use it now. Any ideas?

Appreciate the help!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.