File: graphql_channel.rb

package info (click to toggle)
ruby-graphql 2.2.17-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 9,584 kB
  • sloc: ruby: 67,505; ansic: 1,753; yacc: 831; javascript: 331; makefile: 6
file content (141 lines) | stat: -rw-r--r-- 3,363 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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# frozen_string_literal: true
class GraphqlChannel < ActionCable::Channel::Base
  class QueryType < GraphQL::Schema::Object
    field :value, Integer, null: false
    def value
      3
    end
  end

  class PayloadType < GraphQL::Schema::Object
    field :value, Integer, null: false
  end

  class CounterIncremented < GraphQL::Schema::Subscription
    def self.reset_call_count
      @@call_count = 0
    end

    reset_call_count

    field :new_value, Integer, null: false

    def update
      if object
        if object.value == "server-unsubscribe"
          unsubscribe
        elsif object.value == "server-unsubscribe-with-message"
          unsubscribe({ new_value: 9999 })
        end
      end
      result = {
        new_value: @@call_count += 1
      }
      puts "  -> CounterIncremented#update: #{result}"
      result
    end
  end

  class SubscriptionType < GraphQL::Schema::Object
    field :payload, PayloadType, null: false do
      argument :id, ID
    end

    field :counter_incremented, subscription: CounterIncremented
  end

  # Wacky behavior around the number 4
  # so we can confirm it's used by the UI
  module CustomSerializer
    def self.load(value)
      if value == "4x"
        ExamplePayload.new(400)
      else
        GraphQL::Subscriptions::Serialize.load(value)
      end
    end

    def self.dump(obj)
      if obj.is_a?(ExamplePayload) && obj.value == 4
        "4x"
      else
        GraphQL::Subscriptions::Serialize.dump(obj)
      end
    end
  end

  class GraphQLSchema < GraphQL::Schema
    query(QueryType)
    subscription(SubscriptionType)
    use GraphQL::Subscriptions::ActionCableSubscriptions,
      serializer: CustomSerializer,
      broadcast: true,
      default_broadcastable: true
  end

  def subscribed
    @subscription_ids = []
  end

  def execute(data)
    query = data["query"]
    variables = data["variables"] || {}
    operation_name = data["operationName"]
    context = {
      # Make sure the channel is in the context
      channel: self,
    }

    puts "[GraphQLSchema.execute] #{query} || #{variables}"
    result = GraphQLSchema.execute(
      query: query,
      context: context,
      variables: variables,
      operation_name: operation_name
    )

    payload = {
      result: result.to_h,
      more: result.subscription?,
    }

    # Track the subscription here so we can remove it
    # on unsubscribe.
    if result.context[:subscription_id]
      @subscription_ids << result.context[:subscription_id]
    end
    puts "  -> [transmit(#{result.context[:subscription_id]})] #{payload.inspect}"
    transmit(payload)
  end

  def make_trigger(data)
    field = data["field"]
    args = data["arguments"]
    value = data["value"]
    value = value && ExamplePayload.new(value)
    puts "[make_trigger] #{[field, args, value]}"
    GraphQLSchema.subscriptions.trigger(field, args, value)
  end

  def unsubscribed
    @subscription_ids.each { |sid|
      puts "[delete_subscription] #{sid}"
      GraphQLSchema.subscriptions.delete_subscription(sid)
    }
  end

  # This is to make sure that GlobalID is used to load and dump this object
  class ExamplePayload
    include GlobalID::Identification
    def initialize(value)
      @value = value
    end

    def self.find(value)
      self.new(value)
    end

    attr_reader :value
    alias :id :value
  end
end