Skip to content

Commit

Permalink
refactor digests.
Browse files Browse the repository at this point in the history
  • Loading branch information
gmac committed Sep 17, 2024
1 parent e2f8233 commit b913da5
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 7 deletions.
6 changes: 6 additions & 0 deletions docs/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ client.on_cache_write do |request, payload|
end
```

All request digests use SHA2 by default. You can swap in [a faster algorithm](https://github.com/Shopify/blake3-rb) and/or add base scoping by reconfiguring the stitching library:

```ruby
GraphQL::Stitching.digest { |str| Digest::MD5.hexdigest("v2/#{str}") }
```

Note that inlined input data works against caching, so you should _avoid_ these input literals when possible:

```graphql
Expand Down
16 changes: 14 additions & 2 deletions lib/graphql/stitching.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,24 @@ class CompositionError < StitchingError; end
class ValidationError < CompositionError; end

class << self
attr_writer :stitch_directive

# Proc used to compute digests; uses SHA2 by default.
# @returns [Proc] proc used to compute digests.
def digest(&block)
if block_given?
@digest = block
else
@digest ||= ->(str) { Digest::SHA2.hexdigest(str) }
end
end

# Name of the directive used to mark type resolvers.
# @returns [String] name of the type resolver directive.
def stitch_directive
@stitch_directive ||= "stitch"
end

attr_writer :stitch_directive

# Names of stitching directives to omit from the composed supergraph.
# @returns [Array<String>] list of stitching directive names.
def stitching_directive_names
Expand Down
4 changes: 2 additions & 2 deletions lib/graphql/stitching/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ def normalized_string

# @return [String] a digest of the original document string. Generally faster but less consistent.
def digest
@digest ||= Digest::SHA2.hexdigest(string)
@digest ||= Stitching.digest.call("#{Stitching::VERSION}/#{string}")
end

# @return [String] a digest of the normalized document string. Slower but more consistent.
def normalized_digest
@normalized_digest ||= Digest::SHA2.hexdigest(normalized_string)
@normalized_digest ||= Stitching.digest.call("#{Stitching::VERSION}/#{normalized_string}")
end

# @return [GraphQL::Language::Nodes::OperationDefinition] The selected root operation for the request.
Expand Down
2 changes: 1 addition & 1 deletion lib/graphql/stitching/type_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def list?
end

def version
@version ||= Digest::SHA2.hexdigest("#{Stitching::VERSION}/#{as_json.to_json}")
@version ||= Stitching.digest.call("#{Stitching::VERSION}/#{as_json.to_json}")
end

def ==(other)
Expand Down
4 changes: 2 additions & 2 deletions test/graphql/stitching/request/request_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ def test_provides_digest_and_normalized_digest
|

request = GraphQL::Stitching::Request.new(@supergraph, string)
expected = "ad4b4eb706f67020084a7927ed5bd73b7196e393e0af3535d25ae2d22df33232"
expected_normalized = "88908d0790f7b20afe4a7508a8bba6343c62f98abb9c5abff17345c64d90c0d0"
expected = "9f3c5afb51b7155611921d0e8537c8556b8d757ac90b63d85ea52964d18076d0"
expected_normalized = "71369fe5ee8f33e15b049991a294e6eeeb6e743310c339877f770fa8beb29f21"

assert_equal expected, request.digest
assert_equal expected_normalized, request.normalized_digest
Expand Down
32 changes: 32 additions & 0 deletions test/graphql/stitching_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

require "test_helper"

describe "GraphQL::Stitching" do
def test_digest_gets_and_sets_hashing_implementation
expected_sha = "f5a163f364ac65dfd8ef60edb3ba39d6c2b44bccc289af3ced96b06e3f25df59"
expected_md5 = "fec9ff7a551c37ef692994407710fa54"

fn = GraphQL::Stitching.digest
assert_equal expected_sha, new_type_resolver.version

GraphQL::Stitching.digest { |str| Digest::MD5.hexdigest(str) }
assert_equal expected_md5, new_type_resolver.version

GraphQL::Stitching.digest(&fn)
assert_equal expected_sha, new_type_resolver.version
end

private

def new_type_resolver
GraphQL::Stitching::TypeResolver.new(
location: "a",
type_name: "Test",
list: false,
field: "a",
key: GraphQL::Stitching::TypeResolver.parse_key("id"),
arguments: GraphQL::Stitching::TypeResolver.parse_arguments_with_type_defs("id: $.id", "id: ID"),
)
end
end

0 comments on commit b913da5

Please sign in to comment.