File: async_dataloader_spec.rb

package info (click to toggle)
ruby-graphql 2.5.19-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 13,868 kB
  • sloc: ruby: 80,420; ansic: 1,808; yacc: 845; javascript: 480; makefile: 6
file content (117 lines) | stat: -rw-r--r-- 3,110 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# frozen_string_literal: true
require "spec_helper"

describe GraphQL::Dataloader::AsyncDataloader do
  class RailsAsyncSchema < GraphQL::Schema
    class CustomAsyncDataloader < GraphQL::Dataloader::AsyncDataloader
      def cleanup_fiber
      end

      def get_fiber_variables
        vars = super
        vars[:connected_to] = {
          role: StarWars::StarWarsModel.current_role,
          shard: StarWars::StarWarsModel.current_shard,
          prevent_writes: StarWars::StarWarsModel.current_preventing_writes
        }
        vars
      end

      def set_fiber_variables(vars)
        connection_config = vars.delete(:connected_to)
        StarWars::StarWarsModel.connecting_to(**connection_config)
        super(vars)
      end
    end

    class BaseSource < GraphQL::Dataloader::Source
      def fetch(ids)
        bases = StarWars::Base.where(id: ids)
        ids.map { |id| bases.find { |b| b.id == id } }
      end
    end

    class SelfSource < GraphQL::Dataloader::Source
      def fetch(ids)
        ids
      end
    end

    class Query < GraphQL::Schema::Object
      field :base_name, String do
        argument :id, Int
      end

      def base_name(id:)
        base = dataloader.with(BaseSource).load(id)
        base&.name
      end

      field :query, Query

      field :inline_base_name, String do
        argument :id, Int
      end

      def inline_base_name(id:)
        StarWars::Base.where(id: id).first&.name
      end

      def query
        dataloader.with(SelfSource).load(:query)
      end

      field :role, String

      def role
        StarWars::StarWarsModel.current_role.to_s
      end
    end

    query(Query)
    use CustomAsyncDataloader
  end

  before {
    skip("Only test when isolation_level = :fiber") unless ENV["ISOLATION_LEVEL_FIBER"]
  }

  it "cleans up database connections" do
    starting_connections = ActiveRecord::Base.connection_pool.connections.size
    query_str = "{
      b1: baseName(id: 1) b2: baseName(id: 2)
      ib1: inlineBaseName(id: 1)
      query {
        b3: baseName(id: 3)
        query {
          b4: baseName(id: 4)
          ib2: inlineBaseName(id: 2)
        }
      }
    }"
    res = RailsAsyncSchema.execute(query_str)
    assert_equal({
      "b1" => "Yavin", "b2" => "Echo Base", "ib1" => "Yavin",
      "query" => {
        "b3" => "Secret Hideout",
        "query" => { "b4" => "Death Star", "ib2" => "Echo Base" }
      }
    }, res["data"])

    RailsAsyncSchema.execute(query_str)
    RailsAsyncSchema.execute(query_str)

    ending_connections = ActiveRecord::Base.connection_pool.connections.size
    retained_connections = ending_connections - starting_connections
    assert_equal 0, retained_connections, "No connections are retained by GraphQL"
  end

  it "uses the `connected_to` role" do
    query_str = "{ role query { role } }"
    result = StarWars::StarWarsModel.connected_to(role: :reading) do
      RailsAsyncSchema.execute(query_str)
    end
    expected_res = { "role" => "reading", "query" => { "role" => "reading" }}
    assert_graphql_equal expected_res, result["data"]
  end
end