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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
# frozen_string_literal: true
module LazyHelpers
MAGIC_NUMBER_WITH_LAZY_AUTHORIZED_HOOK = 44
MAGIC_NUMBER_THAT_RETURNS_NIL = 0
MAGIC_NUMBER_THAT_RAISES_ERROR = 13
class Wrapper
def initialize(item = nil, &block)
if block
@block = block
else
@item = item
end
end
def item
if @block
@item = @block.call()
@block = nil
end
@item
end
end
class SumAll
attr_reader :own_value
attr_writer :value
def initialize(own_value)
@own_value = own_value
all << self
end
def value
@value ||= begin
total_value = all.map(&:own_value).reduce(&:+)
all.each { |v| v.value = total_value}
all.clear
total_value
end
@value
end
def all
self.class.all
end
def self.all
@all ||= []
end
end
class LazySum < GraphQL::Schema::Object
field :value, Integer
def value
if object == MAGIC_NUMBER_THAT_RAISES_ERROR
nil
else
object
end
end
def self.authorized?(obj, ctx)
if obj == MAGIC_NUMBER_WITH_LAZY_AUTHORIZED_HOOK
Wrapper.new { true }
else
true
end
end
field :nested_sum, LazySum, null: false do
argument :value, Integer
end
def nested_sum(value:)
if value == MAGIC_NUMBER_THAT_RAISES_ERROR
Wrapper.new(nil)
else
SumAll.new(@object + value)
end
end
field :nullable_nested_sum, LazySum do
argument :value, Integer
end
alias :nullable_nested_sum :nested_sum
end
class LazyQuery < GraphQL::Schema::Object
field :int, Integer, null: false do
argument :value, Integer
argument :plus, Integer, required: false, default_value: 0
end
def int(value:, plus:)
Wrapper.new(value + plus)
end
field :nested_sum, LazySum, null: false do
argument :value, Integer
end
def nested_sum(value:)
SumAll.new(value)
end
field :nullable_nested_sum, LazySum do
argument :value, Integer
end
def nullable_nested_sum(value:)
if value == MAGIC_NUMBER_THAT_RAISES_ERROR
Wrapper.new { raise GraphQL::ExecutionError.new("#{MAGIC_NUMBER_THAT_RAISES_ERROR} is unlucky") }
elsif value == MAGIC_NUMBER_THAT_RETURNS_NIL
nil
else
SumAll.new(value)
end
end
field :list_sum, [LazySum, null: true] do
argument :values, [Integer]
end
def list_sum(values:)
values.map { |v| v == MAGIC_NUMBER_THAT_RETURNS_NIL ? nil : v }
end
end
module SumAllInstrumentation
def execute_query(query:)
add_check(query, "before #{query.selected_operation.name}")
super
end
def execute_query_lazy(query:, multiplex:)
result = super
multiplex.queries.reverse_each do |q|
add_check(q, "after #{q.selected_operation.name}")
end
result
end
def execute_multiplex(multiplex:)
add_check(multiplex, "before multiplex 1")
# TODO not threadsafe
# This should use multiplex-level context
SumAll.all.clear
result = super
add_check(multiplex, "after multiplex 1")
result
end
private
def add_check(object, text)
checks = object.context[:instrumentation_checks]
if checks
checks << text
end
end
end
module SumAllInstrumentation2
def execute_multiplex(multiplex:)
add_check(multiplex, "before multiplex 2")
result = super
add_check(multiplex, "after multiplex 2")
result
end
private
def add_check(object, text)
checks = object.context[:instrumentation_checks]
if checks
checks << text
end
end
end
class LazySchema < GraphQL::Schema
query(LazyQuery)
mutation(LazyQuery)
lazy_resolve(Wrapper, :item)
lazy_resolve(SumAll, :value)
trace_with(SumAllInstrumentation2)
trace_with(SumAllInstrumentation)
def self.sync_lazy(lazy)
if lazy.is_a?(SumAll) && lazy.own_value > 1000
lazy.value # clear the previous set
lazy.own_value - 900
else
super
end
end
end
def run_query(query_str, **rest)
LazySchema.execute(query_str, **rest)
end
end
|