graphql 1.9.21 → 2.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of graphql might be problematic. Click here for more details.

Files changed (403) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +21 -10
  3. data/lib/generators/graphql/enum_generator.rb +4 -10
  4. data/lib/generators/graphql/field_extractor.rb +31 -0
  5. data/lib/generators/graphql/input_generator.rb +50 -0
  6. data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
  7. data/lib/generators/graphql/{templates → install/templates}/base_mutation.erb +2 -0
  8. data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +2 -0
  9. data/lib/generators/graphql/install_generator.rb +45 -8
  10. data/lib/generators/graphql/interface_generator.rb +7 -7
  11. data/lib/generators/graphql/loader_generator.rb +1 -0
  12. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  13. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  14. data/lib/generators/graphql/mutation_generator.rb +6 -30
  15. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  16. data/lib/generators/graphql/object_generator.rb +28 -12
  17. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  18. data/lib/generators/graphql/relay.rb +49 -0
  19. data/lib/generators/graphql/relay_generator.rb +21 -0
  20. data/lib/generators/graphql/scalar_generator.rb +4 -2
  21. data/lib/generators/graphql/templates/base_argument.erb +2 -0
  22. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  23. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  24. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  25. data/lib/generators/graphql/templates/base_field.erb +2 -0
  26. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  27. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  28. data/lib/generators/graphql/templates/base_object.erb +2 -0
  29. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  30. data/lib/generators/graphql/templates/base_union.erb +2 -0
  31. data/lib/generators/graphql/templates/enum.erb +7 -1
  32. data/lib/generators/graphql/templates/graphql_controller.erb +16 -12
  33. data/lib/generators/graphql/templates/input.erb +9 -0
  34. data/lib/generators/graphql/templates/interface.erb +6 -2
  35. data/lib/generators/graphql/templates/loader.erb +2 -0
  36. data/lib/generators/graphql/templates/mutation.erb +3 -1
  37. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  38. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  39. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  40. data/lib/generators/graphql/templates/node_type.erb +9 -0
  41. data/lib/generators/graphql/templates/object.erb +7 -3
  42. data/lib/generators/graphql/templates/query_type.erb +3 -3
  43. data/lib/generators/graphql/templates/scalar.erb +5 -1
  44. data/lib/generators/graphql/templates/schema.erb +25 -27
  45. data/lib/generators/graphql/templates/union.erb +6 -2
  46. data/lib/generators/graphql/type_generator.rb +47 -10
  47. data/lib/generators/graphql/union_generator.rb +5 -5
  48. data/lib/graphql/analysis/ast/field_usage.rb +31 -2
  49. data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
  50. data/lib/graphql/analysis/ast/query_complexity.rb +175 -68
  51. data/lib/graphql/analysis/ast/query_depth.rb +0 -1
  52. data/lib/graphql/analysis/ast/visitor.rb +17 -8
  53. data/lib/graphql/analysis/ast.rb +14 -14
  54. data/lib/graphql/analysis.rb +0 -7
  55. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  56. data/lib/graphql/backtrace/table.rb +37 -16
  57. data/lib/graphql/backtrace/traced_error.rb +0 -1
  58. data/lib/graphql/backtrace/tracer.rb +39 -9
  59. data/lib/graphql/backtrace.rb +20 -17
  60. data/lib/graphql/dataloader/null_dataloader.rb +24 -0
  61. data/lib/graphql/dataloader/request.rb +19 -0
  62. data/lib/graphql/dataloader/request_all.rb +19 -0
  63. data/lib/graphql/dataloader/source.rb +164 -0
  64. data/lib/graphql/dataloader.rb +311 -0
  65. data/lib/graphql/date_encoding_error.rb +16 -0
  66. data/lib/graphql/deprecation.rb +9 -0
  67. data/lib/graphql/dig.rb +1 -1
  68. data/lib/graphql/execution/directive_checks.rb +2 -2
  69. data/lib/graphql/execution/errors.rb +77 -45
  70. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  71. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  72. data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
  73. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  74. data/lib/graphql/execution/interpreter/resolve.rb +44 -25
  75. data/lib/graphql/execution/interpreter/runtime.rb +755 -395
  76. data/lib/graphql/execution/interpreter.rb +201 -74
  77. data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
  78. data/lib/graphql/execution/lazy.rb +5 -9
  79. data/lib/graphql/execution/lookahead.rb +65 -136
  80. data/lib/graphql/execution/multiplex.rb +5 -152
  81. data/lib/graphql/execution.rb +11 -4
  82. data/lib/graphql/filter.rb +1 -1
  83. data/lib/graphql/integer_decoding_error.rb +17 -0
  84. data/lib/graphql/integer_encoding_error.rb +18 -2
  85. data/lib/graphql/introspection/base_object.rb +2 -5
  86. data/lib/graphql/introspection/directive_location_enum.rb +2 -2
  87. data/lib/graphql/introspection/directive_type.rb +11 -5
  88. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  89. data/lib/graphql/introspection/entry_points.rb +5 -18
  90. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  91. data/lib/graphql/introspection/field_type.rb +9 -5
  92. data/lib/graphql/introspection/input_value_type.rb +41 -11
  93. data/lib/graphql/introspection/introspection_query.rb +6 -92
  94. data/lib/graphql/introspection/schema_type.rb +10 -10
  95. data/lib/graphql/introspection/type_type.rb +34 -17
  96. data/lib/graphql/introspection.rb +100 -0
  97. data/lib/graphql/invalid_null_error.rb +18 -0
  98. data/lib/graphql/language/block_string.rb +20 -5
  99. data/lib/graphql/language/cache.rb +37 -0
  100. data/lib/graphql/language/definition_slice.rb +21 -10
  101. data/lib/graphql/language/document_from_schema_definition.rb +104 -68
  102. data/lib/graphql/language/lexer.rb +83 -40
  103. data/lib/graphql/language/lexer.rl +31 -9
  104. data/lib/graphql/language/nodes.rb +64 -93
  105. data/lib/graphql/language/parser.rb +940 -896
  106. data/lib/graphql/language/parser.y +130 -103
  107. data/lib/graphql/language/printer.rb +48 -23
  108. data/lib/graphql/language/sanitized_printer.rb +222 -0
  109. data/lib/graphql/language/token.rb +0 -4
  110. data/lib/graphql/language/visitor.rb +2 -2
  111. data/lib/graphql/language.rb +3 -1
  112. data/lib/graphql/name_validator.rb +2 -7
  113. data/lib/graphql/pagination/active_record_relation_connection.rb +85 -0
  114. data/lib/graphql/pagination/array_connection.rb +79 -0
  115. data/lib/graphql/pagination/connection.rb +253 -0
  116. data/lib/graphql/pagination/connections.rb +135 -0
  117. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  118. data/lib/graphql/pagination/relation_connection.rb +228 -0
  119. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  120. data/lib/graphql/pagination.rb +6 -0
  121. data/lib/graphql/parse_error.rb +0 -1
  122. data/lib/graphql/query/context.rb +172 -198
  123. data/lib/graphql/query/fingerprint.rb +26 -0
  124. data/lib/graphql/query/input_validation_result.rb +33 -7
  125. data/lib/graphql/query/null_context.rb +21 -8
  126. data/lib/graphql/query/validation_pipeline.rb +16 -38
  127. data/lib/graphql/query/variable_validation_error.rb +3 -3
  128. data/lib/graphql/query/variables.rb +39 -12
  129. data/lib/graphql/query.rb +74 -38
  130. data/lib/graphql/railtie.rb +6 -102
  131. data/lib/graphql/rake_task/validate.rb +4 -1
  132. data/lib/graphql/rake_task.rb +41 -10
  133. data/lib/graphql/relay/range_add.rb +17 -10
  134. data/lib/graphql/relay.rb +0 -15
  135. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  136. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  137. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  138. data/lib/graphql/rubocop.rb +4 -0
  139. data/lib/graphql/schema/addition.rb +245 -0
  140. data/lib/graphql/schema/argument.rb +286 -31
  141. data/lib/graphql/schema/base_64_encoder.rb +2 -0
  142. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
  143. data/lib/graphql/schema/build_from_definition/resolve_map.rb +13 -5
  144. data/lib/graphql/schema/build_from_definition.rb +334 -220
  145. data/lib/graphql/schema/built_in_types.rb +5 -5
  146. data/lib/graphql/schema/directive/deprecated.rb +18 -0
  147. data/lib/graphql/schema/directive/feature.rb +1 -1
  148. data/lib/graphql/schema/directive/flagged.rb +57 -0
  149. data/lib/graphql/schema/directive/include.rb +2 -2
  150. data/lib/graphql/schema/directive/one_of.rb +12 -0
  151. data/lib/graphql/schema/directive/skip.rb +2 -2
  152. data/lib/graphql/schema/directive/transform.rb +14 -2
  153. data/lib/graphql/schema/directive.rb +117 -14
  154. data/lib/graphql/schema/enum.rb +113 -22
  155. data/lib/graphql/schema/enum_value.rb +16 -21
  156. data/lib/graphql/schema/field/connection_extension.rb +50 -20
  157. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  158. data/lib/graphql/schema/field.rb +491 -329
  159. data/lib/graphql/schema/field_extension.rb +89 -2
  160. data/lib/graphql/schema/find_inherited_value.rb +17 -1
  161. data/lib/graphql/schema/finder.rb +16 -14
  162. data/lib/graphql/schema/input_object.rb +182 -60
  163. data/lib/graphql/schema/interface.rb +28 -43
  164. data/lib/graphql/schema/introspection_system.rb +101 -38
  165. data/lib/graphql/schema/late_bound_type.rb +7 -2
  166. data/lib/graphql/schema/list.rb +61 -3
  167. data/lib/graphql/schema/loader.rb +144 -102
  168. data/lib/graphql/schema/member/base_dsl_methods.rb +33 -32
  169. data/lib/graphql/schema/member/build_type.rb +24 -15
  170. data/lib/graphql/schema/member/has_arguments.rb +261 -24
  171. data/lib/graphql/schema/member/has_ast_node.rb +20 -0
  172. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  173. data/lib/graphql/schema/member/has_directives.rb +113 -0
  174. data/lib/graphql/schema/member/has_fields.rb +99 -34
  175. data/lib/graphql/schema/member/has_interfaces.rb +88 -0
  176. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  177. data/lib/graphql/schema/member/has_validators.rb +31 -0
  178. data/lib/graphql/schema/member/relay_shortcuts.rb +28 -2
  179. data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
  180. data/lib/graphql/schema/member/validates_input.rb +33 -0
  181. data/lib/graphql/schema/member.rb +11 -6
  182. data/lib/graphql/schema/mutation.rb +4 -9
  183. data/lib/graphql/schema/non_null.rb +34 -4
  184. data/lib/graphql/schema/object.rb +38 -60
  185. data/lib/graphql/schema/printer.rb +16 -35
  186. data/lib/graphql/schema/relay_classic_mutation.rb +90 -43
  187. data/lib/graphql/schema/resolver/has_payload_type.rb +46 -6
  188. data/lib/graphql/schema/resolver.rb +146 -93
  189. data/lib/graphql/schema/scalar.rb +40 -15
  190. data/lib/graphql/schema/subscription.rb +55 -26
  191. data/lib/graphql/schema/timeout.rb +29 -15
  192. data/lib/graphql/schema/type_expression.rb +21 -13
  193. data/lib/graphql/schema/type_membership.rb +22 -5
  194. data/lib/graphql/schema/union.rb +48 -14
  195. data/lib/graphql/schema/unique_within_type.rb +1 -2
  196. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  197. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  198. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  199. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  200. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  201. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  202. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  203. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  204. data/lib/graphql/schema/validator.rb +171 -0
  205. data/lib/graphql/schema/warden.rb +187 -33
  206. data/lib/graphql/schema/wrapper.rb +0 -5
  207. data/lib/graphql/schema.rb +773 -892
  208. data/lib/graphql/static_validation/all_rules.rb +3 -0
  209. data/lib/graphql/static_validation/base_visitor.rb +21 -31
  210. data/lib/graphql/static_validation/definition_dependencies.rb +7 -2
  211. data/lib/graphql/static_validation/error.rb +3 -1
  212. data/lib/graphql/static_validation/literal_validator.rb +55 -26
  213. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +45 -83
  214. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +22 -6
  215. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +35 -26
  216. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  217. data/lib/graphql/static_validation/rules/directives_are_defined.rb +12 -6
  218. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +14 -14
  219. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
  220. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
  221. data/lib/graphql/static_validation/rules/fields_will_merge.rb +94 -51
  222. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  223. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  224. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  225. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  226. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  227. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
  228. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
  229. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  230. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  231. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -2
  232. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +9 -10
  233. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +13 -7
  234. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +12 -13
  235. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -14
  236. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  237. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +5 -3
  238. data/lib/graphql/static_validation/type_stack.rb +2 -2
  239. data/lib/graphql/static_validation/validation_context.rb +13 -3
  240. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  241. data/lib/graphql/static_validation/validator.rb +31 -19
  242. data/lib/graphql/static_validation.rb +1 -2
  243. data/lib/graphql/string_encoding_error.rb +13 -3
  244. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +129 -22
  245. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  246. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +58 -0
  247. data/lib/graphql/subscriptions/event.rb +85 -31
  248. data/lib/graphql/subscriptions/instrumentation.rb +0 -47
  249. data/lib/graphql/subscriptions/serialize.rb +53 -6
  250. data/lib/graphql/subscriptions.rb +137 -57
  251. data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -17
  252. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  253. data/lib/graphql/tracing/appsignal_tracing.rb +23 -0
  254. data/lib/graphql/tracing/data_dog_tracing.rb +34 -2
  255. data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
  256. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  257. data/lib/graphql/tracing/platform_tracing.rb +67 -38
  258. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  259. data/lib/graphql/tracing/prometheus_tracing.rb +8 -0
  260. data/lib/graphql/tracing/scout_tracing.rb +19 -0
  261. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  262. data/lib/graphql/tracing.rb +15 -36
  263. data/lib/graphql/types/big_int.rb +5 -1
  264. data/lib/graphql/types/int.rb +10 -3
  265. data/lib/graphql/types/iso_8601_date.rb +20 -9
  266. data/lib/graphql/types/iso_8601_date_time.rb +36 -10
  267. data/lib/graphql/types/relay/base_connection.rb +18 -90
  268. data/lib/graphql/types/relay/base_edge.rb +2 -34
  269. data/lib/graphql/types/relay/connection_behaviors.rb +158 -0
  270. data/lib/graphql/types/relay/default_relay.rb +27 -0
  271. data/lib/graphql/types/relay/edge_behaviors.rb +65 -0
  272. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  273. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  274. data/lib/graphql/types/relay/node.rb +2 -4
  275. data/lib/graphql/types/relay/node_behaviors.rb +19 -0
  276. data/lib/graphql/types/relay/page_info.rb +2 -14
  277. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  278. data/lib/graphql/types/relay.rb +11 -5
  279. data/lib/graphql/types/string.rb +8 -2
  280. data/lib/graphql/unauthorized_error.rb +2 -2
  281. data/lib/graphql/unresolved_type_error.rb +2 -2
  282. data/lib/graphql/version.rb +1 -1
  283. data/lib/graphql.rb +41 -58
  284. data/readme.md +3 -6
  285. metadata +103 -237
  286. data/lib/graphql/analysis/analyze_query.rb +0 -91
  287. data/lib/graphql/analysis/field_usage.rb +0 -45
  288. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  289. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  290. data/lib/graphql/analysis/query_complexity.rb +0 -88
  291. data/lib/graphql/analysis/query_depth.rb +0 -43
  292. data/lib/graphql/analysis/reducer_state.rb +0 -48
  293. data/lib/graphql/argument.rb +0 -159
  294. data/lib/graphql/authorization.rb +0 -82
  295. data/lib/graphql/backwards_compatibility.rb +0 -60
  296. data/lib/graphql/base_type.rb +0 -226
  297. data/lib/graphql/boolean_type.rb +0 -2
  298. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  299. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  300. data/lib/graphql/compatibility/execution_specification.rb +0 -435
  301. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  302. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -213
  303. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -91
  304. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  305. data/lib/graphql/compatibility/query_parser_specification.rb +0 -264
  306. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -680
  307. data/lib/graphql/compatibility.rb +0 -5
  308. data/lib/graphql/define/assign_argument.rb +0 -12
  309. data/lib/graphql/define/assign_connection.rb +0 -13
  310. data/lib/graphql/define/assign_enum_value.rb +0 -18
  311. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  312. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  313. data/lib/graphql/define/assign_object_field.rb +0 -42
  314. data/lib/graphql/define/defined_object_proxy.rb +0 -53
  315. data/lib/graphql/define/instance_definable.rb +0 -311
  316. data/lib/graphql/define/no_definition_error.rb +0 -7
  317. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  318. data/lib/graphql/define/type_definer.rb +0 -31
  319. data/lib/graphql/define.rb +0 -31
  320. data/lib/graphql/deprecated_dsl.rb +0 -42
  321. data/lib/graphql/directive/deprecated_directive.rb +0 -13
  322. data/lib/graphql/directive/include_directive.rb +0 -2
  323. data/lib/graphql/directive/skip_directive.rb +0 -2
  324. data/lib/graphql/directive.rb +0 -104
  325. data/lib/graphql/enum_type.rb +0 -193
  326. data/lib/graphql/execution/execute.rb +0 -326
  327. data/lib/graphql/execution/flatten.rb +0 -40
  328. data/lib/graphql/execution/instrumentation.rb +0 -92
  329. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
  330. data/lib/graphql/execution/lazy/resolve.rb +0 -91
  331. data/lib/graphql/execution/typecast.rb +0 -50
  332. data/lib/graphql/field/resolve.rb +0 -59
  333. data/lib/graphql/field.rb +0 -330
  334. data/lib/graphql/float_type.rb +0 -2
  335. data/lib/graphql/function.rb +0 -153
  336. data/lib/graphql/id_type.rb +0 -2
  337. data/lib/graphql/input_object_type.rb +0 -154
  338. data/lib/graphql/int_type.rb +0 -2
  339. data/lib/graphql/interface_type.rb +0 -86
  340. data/lib/graphql/internal_representation/document.rb +0 -27
  341. data/lib/graphql/internal_representation/node.rb +0 -206
  342. data/lib/graphql/internal_representation/print.rb +0 -51
  343. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  344. data/lib/graphql/internal_representation/scope.rb +0 -88
  345. data/lib/graphql/internal_representation/visit.rb +0 -36
  346. data/lib/graphql/internal_representation.rb +0 -7
  347. data/lib/graphql/list_type.rb +0 -80
  348. data/lib/graphql/literal_validation_error.rb +0 -6
  349. data/lib/graphql/non_null_type.rb +0 -81
  350. data/lib/graphql/object_type.rb +0 -141
  351. data/lib/graphql/query/arguments.rb +0 -187
  352. data/lib/graphql/query/arguments_cache.rb +0 -25
  353. data/lib/graphql/query/executor.rb +0 -53
  354. data/lib/graphql/query/literal_input.rb +0 -116
  355. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  356. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  357. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  358. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  359. data/lib/graphql/query/serial_execution.rb +0 -39
  360. data/lib/graphql/relay/array_connection.rb +0 -85
  361. data/lib/graphql/relay/base_connection.rb +0 -172
  362. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  363. data/lib/graphql/relay/connection_resolve.rb +0 -43
  364. data/lib/graphql/relay/connection_type.rb +0 -40
  365. data/lib/graphql/relay/edge.rb +0 -27
  366. data/lib/graphql/relay/edge_type.rb +0 -18
  367. data/lib/graphql/relay/edges_instrumentation.rb +0 -40
  368. data/lib/graphql/relay/global_id_resolve.rb +0 -18
  369. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  370. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  371. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  372. data/lib/graphql/relay/mutation/result.rb +0 -38
  373. data/lib/graphql/relay/mutation.rb +0 -190
  374. data/lib/graphql/relay/node.rb +0 -36
  375. data/lib/graphql/relay/page_info.rb +0 -7
  376. data/lib/graphql/relay/relation_connection.rb +0 -190
  377. data/lib/graphql/relay/type_extensions.rb +0 -30
  378. data/lib/graphql/scalar_type.rb +0 -133
  379. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  380. data/lib/graphql/schema/default_parse_error.rb +0 -10
  381. data/lib/graphql/schema/default_type_error.rb +0 -15
  382. data/lib/graphql/schema/member/accepts_definition.rb +0 -152
  383. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -26
  384. data/lib/graphql/schema/member/instrumentation.rb +0 -132
  385. data/lib/graphql/schema/middleware_chain.rb +0 -82
  386. data/lib/graphql/schema/possible_types.rb +0 -39
  387. data/lib/graphql/schema/rescue_middleware.rb +0 -60
  388. data/lib/graphql/schema/timeout_middleware.rb +0 -86
  389. data/lib/graphql/schema/traversal.rb +0 -228
  390. data/lib/graphql/schema/validation.rb +0 -303
  391. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  392. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  393. data/lib/graphql/string_type.rb +0 -2
  394. data/lib/graphql/subscriptions/subscription_root.rb +0 -74
  395. data/lib/graphql/tracing/skylight_tracing.rb +0 -62
  396. data/lib/graphql/types/relay/base_field.rb +0 -22
  397. data/lib/graphql/types/relay/base_interface.rb +0 -29
  398. data/lib/graphql/types/relay/base_object.rb +0 -26
  399. data/lib/graphql/types/relay/node_field.rb +0 -43
  400. data/lib/graphql/types/relay/nodes_field.rb +0 -45
  401. data/lib/graphql/union_type.rb +0 -135
  402. data/lib/graphql/upgrader/member.rb +0 -936
  403. data/lib/graphql/upgrader/schema.rb +0 -37
@@ -9,13 +9,12 @@ module GraphQL
9
9
  # {TracedError} provides a GraphQL backtrace with arguments and return values.
10
10
  # The underlying error is available as {TracedError#cause}.
11
11
  #
12
- # WARNING: {.enable} is not threadsafe because {GraphQL::Tracing.install} is not threadsafe.
13
- #
14
12
  # @example toggling backtrace annotation
15
- # # to enable:
16
- # GraphQL::Backtrace.enable
17
- # # later, to disable:
18
- # GraphQL::Backtrace.disable
13
+ # class MySchema < GraphQL::Schema
14
+ # if Rails.env.development? || Rails.env.test?
15
+ # use GraphQL::Backtrace
16
+ # end
17
+ # end
19
18
  #
20
19
  class Backtrace
21
20
  include Enumerable
@@ -23,17 +22,6 @@ module GraphQL
23
22
 
24
23
  def_delegators :to_a, :each, :[]
25
24
 
26
- def self.enable
27
- warn("GraphQL::Backtrace.enable is deprecated, add `use GraphQL::Backtrace` to your schema definition instead.")
28
- GraphQL::Tracing.install(Backtrace::Tracer)
29
- nil
30
- end
31
-
32
- def self.disable
33
- GraphQL::Tracing.uninstall(Backtrace::Tracer)
34
- nil
35
- end
36
-
37
25
  def self.use(schema_defn)
38
26
  schema_defn.tracer(self::Tracer)
39
27
  end
@@ -51,5 +39,20 @@ module GraphQL
51
39
  def to_a
52
40
  @table.to_backtrace
53
41
  end
42
+
43
+ # Used for internal bookkeeping
44
+ # @api private
45
+ class Frame
46
+ attr_reader :path, :query, :ast_node, :object, :field, :arguments, :parent_frame
47
+ def initialize(path:, query:, ast_node:, object:, field:, arguments:, parent_frame:)
48
+ @path = path
49
+ @query = query
50
+ @ast_node = ast_node
51
+ @field = field
52
+ @object = object
53
+ @arguments = arguments
54
+ @parent_frame = parent_frame
55
+ end
56
+ end
54
57
  end
55
58
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Dataloader
5
+ # The default implementation of dataloading -- all no-ops.
6
+ #
7
+ # The Dataloader interface isn't public, but it enables
8
+ # simple internal code while adding the option to add Dataloader.
9
+ class NullDataloader < Dataloader
10
+ # These are all no-ops because code was
11
+ # executed sychronously.
12
+ def run; end
13
+ def run_isolated; yield; end
14
+ def yield
15
+ raise GraphQL::Error, "GraphQL::Dataloader is not running -- add `use GraphQL::Dataloader` to your schema to use Dataloader sources."
16
+ end
17
+
18
+ def append_job
19
+ yield
20
+ nil
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Dataloader
4
+ # @see Source#request which returns an instance of this
5
+ class Request
6
+ def initialize(source, key)
7
+ @source = source
8
+ @key = key
9
+ end
10
+
11
+ # Call this method to cause the current Fiber to wait for the results of this request.
12
+ #
13
+ # @return [Object] the object loaded for `key`
14
+ def load
15
+ @source.load(@key)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Dataloader
4
+ # @see Source#request_all which returns an instance of this.
5
+ class RequestAll < Request
6
+ def initialize(source, keys)
7
+ @source = source
8
+ @keys = keys
9
+ end
10
+
11
+ # Call this method to cause the current Fiber to wait for the results of this request.
12
+ #
13
+ # @return [Array<Object>] One object for each of `keys`
14
+ def load
15
+ @source.load_all(@keys)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,164 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Dataloader
5
+ class Source
6
+ # Called by {Dataloader} to prepare the {Source}'s internal state
7
+ # @api private
8
+ def setup(dataloader)
9
+ # These keys have been requested but haven't been fetched yet
10
+ @pending_keys = []
11
+ # These keys have been passed to `fetch` but haven't been finished yet
12
+ @fetching_keys = []
13
+ # { key => result }
14
+ @results = {}
15
+ @dataloader = dataloader
16
+ end
17
+
18
+ attr_reader :dataloader
19
+
20
+ # @return [Dataloader::Request] a pending request for a value from `key`. Call `.load` on that object to wait for the result.
21
+ def request(key)
22
+ if !@results.key?(key)
23
+ @pending_keys << key
24
+ end
25
+ Dataloader::Request.new(self, key)
26
+ end
27
+
28
+ # @return [Dataloader::Request] a pending request for a values from `keys`. Call `.load` on that object to wait for the results.
29
+ def request_all(keys)
30
+ pending_keys = keys.select { |k| !@results.key?(k) }
31
+ @pending_keys.concat(pending_keys)
32
+ Dataloader::RequestAll.new(self, keys)
33
+ end
34
+
35
+ # @param key [Object] A loading key which will be passed to {#fetch} if it isn't already in the internal cache.
36
+ # @return [Object] The result from {#fetch} for `key`. If `key` hasn't been loaded yet, the Fiber will yield until it's loaded.
37
+ def load(key)
38
+ if @results.key?(key)
39
+ result_for(key)
40
+ else
41
+ @pending_keys << key
42
+ sync
43
+ result_for(key)
44
+ end
45
+ end
46
+
47
+ # @param keys [Array<Object>] Loading keys which will be passed to `#fetch` (or read from the internal cache).
48
+ # @return [Object] The result from {#fetch} for `keys`. If `keys` haven't been loaded yet, the Fiber will yield until they're loaded.
49
+ def load_all(keys)
50
+ if keys.any? { |k| !@results.key?(k) }
51
+ pending_keys = keys.select { |k| !@results.key?(k) }
52
+ @pending_keys.concat(pending_keys)
53
+ sync
54
+ end
55
+
56
+ keys.map { |k| result_for(k) }
57
+ end
58
+
59
+ # Subclasses must implement this method to return a value for each of `keys`
60
+ # @param keys [Array<Object>] keys passed to {#load}, {#load_all}, {#request}, or {#request_all}
61
+ # @return [Array<Object>] A loaded value for each of `keys`. The array must match one-for-one to the list of `keys`.
62
+ def fetch(keys)
63
+ # somehow retrieve these from the backend
64
+ raise "Implement `#{self.class}#fetch(#{keys.inspect}) to return a record for each of the keys"
65
+ end
66
+
67
+ # Wait for a batch, if there's anything to batch.
68
+ # Then run the batch and update the cache.
69
+ # @return [void]
70
+ def sync
71
+ pending_keys = @pending_keys.dup
72
+ @dataloader.yield
73
+ iterations = 0
74
+ while pending_keys.any? { |k| !@results.key?(k) }
75
+ iterations += 1
76
+ if iterations > 1000
77
+ raise "#{self.class}#sync tried 1000 times to load pending keys (#{pending_keys}), but they still weren't loaded. There is likely a circular dependency."
78
+ end
79
+ @dataloader.yield
80
+ end
81
+ nil
82
+ end
83
+
84
+ # @return [Boolean] True if this source has any pending requests for data.
85
+ def pending?
86
+ !@pending_keys.empty?
87
+ end
88
+
89
+ # Add these key-value pairs to this source's cache
90
+ # (future loads will use these merged values).
91
+ # @param results [Hash<Object => Object>] key-value pairs to cache in this source
92
+ # @return [void]
93
+ def merge(results)
94
+ @results.merge!(results)
95
+ nil
96
+ end
97
+
98
+ # Called by {GraphQL::Dataloader} to resolve and pending requests to this source.
99
+ # @api private
100
+ # @return [void]
101
+ def run_pending_keys
102
+ if !@fetching_keys.empty?
103
+ @pending_keys -= @fetching_keys
104
+ end
105
+ return if @pending_keys.empty?
106
+ fetch_keys = @pending_keys.uniq
107
+ @fetching_keys.concat(fetch_keys)
108
+ @pending_keys = []
109
+ results = fetch(fetch_keys)
110
+ fetch_keys.each_with_index do |key, idx|
111
+ @results[key] = results[idx]
112
+ end
113
+ nil
114
+ rescue StandardError => error
115
+ fetch_keys.each { |key| @results[key] = error }
116
+ ensure
117
+ if fetch_keys
118
+ @fetching_keys -= fetch_keys
119
+ end
120
+ end
121
+
122
+ # These arguments are given to `dataloader.with(source_class, ...)`. The object
123
+ # returned from this method is used to de-duplicate batch loads under the hood
124
+ # by using it as a Hash key.
125
+ #
126
+ # By default, the arguments are all put in an Array. To customize how this source's
127
+ # batches are merged, override this method to return something else.
128
+ #
129
+ # For example, if you pass `ActiveRecord::Relation`s to `.with(...)`, you could override
130
+ # this method to call `.to_sql` on them, thus merging `.load(...)` calls when they apply
131
+ # to equivalent relations.
132
+ #
133
+ # @param batch_args [Array<Object>]
134
+ # @param batch_kwargs [Hash]
135
+ # @return [Object]
136
+ def self.batch_key_for(*batch_args, **batch_kwargs)
137
+ [*batch_args, **batch_kwargs]
138
+ end
139
+
140
+ attr_reader :pending_keys
141
+
142
+ private
143
+
144
+ # Reads and returns the result for the key from the internal cache, or raises an error if the result was an error
145
+ # @param key [Object] key passed to {#load} or {#load_all}
146
+ # @return [Object] The result from {#fetch} for `key`.
147
+ # @api private
148
+ def result_for(key)
149
+ if !@results.key?(key)
150
+ raise GraphQL::InvariantError, <<-ERR
151
+ Fetching result for a key on #{self.class} that hasn't been loaded yet (#{key.inspect}, loaded: #{@results.keys})
152
+
153
+ This key should have been loaded already. This is a bug in GraphQL::Dataloader, please report it on GitHub: https://github.com/rmosolgo/graphql-ruby/issues/new.
154
+ ERR
155
+ end
156
+ result = @results[key]
157
+
158
+ raise result if result.class <= StandardError
159
+
160
+ result
161
+ end
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,311 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "graphql/dataloader/null_dataloader"
4
+ require "graphql/dataloader/request"
5
+ require "graphql/dataloader/request_all"
6
+ require "graphql/dataloader/source"
7
+
8
+ module GraphQL
9
+ # This plugin supports Fiber-based concurrency, along with {GraphQL::Dataloader::Source}.
10
+ #
11
+ # @example Installing Dataloader
12
+ #
13
+ # class MySchema < GraphQL::Schema
14
+ # use GraphQL::Dataloader
15
+ # end
16
+ #
17
+ # @example Waiting for batch-loaded data in a GraphQL field
18
+ #
19
+ # field :team, Types::Team, null: true
20
+ #
21
+ # def team
22
+ # dataloader.with(Sources::Record, Team).load(object.team_id)
23
+ # end
24
+ #
25
+ class Dataloader
26
+ class << self
27
+ attr_accessor :default_nonblocking
28
+ end
29
+
30
+ AsyncDataloader = Class.new(self) { self.default_nonblocking = true }
31
+
32
+ def self.use(schema, nonblocking: nil)
33
+ schema.dataloader_class = if nonblocking
34
+ AsyncDataloader
35
+ else
36
+ self
37
+ end
38
+ end
39
+
40
+ # Call the block with a Dataloader instance,
41
+ # then run all enqueued jobs and return the result of the block.
42
+ def self.with_dataloading(&block)
43
+ dataloader = self.new
44
+ result = nil
45
+ dataloader.append_job {
46
+ result = block.call(dataloader)
47
+ }
48
+ dataloader.run
49
+ result
50
+ end
51
+
52
+ def initialize(nonblocking: self.class.default_nonblocking)
53
+ @source_cache = Hash.new { |h, k| h[k] = {} }
54
+ @pending_jobs = []
55
+ if !nonblocking.nil?
56
+ @nonblocking = nonblocking
57
+ end
58
+ end
59
+
60
+ def nonblocking?
61
+ @nonblocking
62
+ end
63
+
64
+ # Get a Source instance from this dataloader, for calling `.load(...)` or `.request(...)` on.
65
+ #
66
+ # @param source_class [Class<GraphQL::Dataloader::Source]
67
+ # @param batch_parameters [Array<Object>]
68
+ # @return [GraphQL::Dataloader::Source] An instance of {source_class}, initialized with `self, *batch_parameters`,
69
+ # and cached for the lifetime of this {Multiplex}.
70
+ if RUBY_VERSION < "3" || RUBY_ENGINE != "ruby" # truffle-ruby wasn't doing well with the implementation below
71
+ def with(source_class, *batch_args)
72
+ batch_key = source_class.batch_key_for(*batch_args)
73
+ @source_cache[source_class][batch_key] ||= begin
74
+ source = source_class.new(*batch_args)
75
+ source.setup(self)
76
+ source
77
+ end
78
+ end
79
+ else
80
+ def with(source_class, *batch_args, **batch_kwargs)
81
+ batch_key = source_class.batch_key_for(*batch_args, **batch_kwargs)
82
+ @source_cache[source_class][batch_key] ||= begin
83
+ source = source_class.new(*batch_args, **batch_kwargs)
84
+ source.setup(self)
85
+ source
86
+ end
87
+ end
88
+ end
89
+ # Tell the dataloader that this fiber is waiting for data.
90
+ #
91
+ # Dataloader will resume the fiber after the requested data has been loaded (by another Fiber).
92
+ #
93
+ # @return [void]
94
+ def yield
95
+ Fiber.yield
96
+ nil
97
+ end
98
+
99
+ # @api private Nothing to see here
100
+ def append_job(&job)
101
+ # Given a block, queue it up to be worked through when `#run` is called.
102
+ # (If the dataloader is already running, than a Fiber will pick this up later.)
103
+ @pending_jobs.push(job)
104
+ nil
105
+ end
106
+
107
+ # Use a self-contained queue for the work in the block.
108
+ def run_isolated
109
+ prev_queue = @pending_jobs
110
+ prev_pending_keys = {}
111
+ @source_cache.each do |source_class, batched_sources|
112
+ batched_sources.each do |batch_args, batched_source_instance|
113
+ if batched_source_instance.pending?
114
+ prev_pending_keys[batched_source_instance] = batched_source_instance.pending_keys.dup
115
+ batched_source_instance.pending_keys.clear
116
+ end
117
+ end
118
+ end
119
+
120
+ @pending_jobs = []
121
+ res = nil
122
+ # Make sure the block is inside a Fiber, so it can `Fiber.yield`
123
+ append_job {
124
+ res = yield
125
+ }
126
+ run
127
+ res
128
+ ensure
129
+ @pending_jobs = prev_queue
130
+ prev_pending_keys.each do |source_instance, pending_keys|
131
+ source_instance.pending_keys.concat(pending_keys)
132
+ end
133
+ end
134
+
135
+ # @api private Move along, move along
136
+ def run
137
+ if @nonblocking && !Fiber.scheduler
138
+ raise "`nonblocking: true` requires `Fiber.scheduler`, assign one with `Fiber.set_scheduler(...)` before executing GraphQL."
139
+ end
140
+ # At a high level, the algorithm is:
141
+ #
142
+ # A) Inside Fibers, run jobs from the queue one-by-one
143
+ # - When one of the jobs yields to the dataloader (`Fiber.yield`), then that fiber will pause
144
+ # - In that case, if there are still pending jobs, a new Fiber will be created to run jobs
145
+ # - Continue until all jobs have been _started_ by a Fiber. (Any number of those Fibers may be waiting to be resumed, after their data is loaded)
146
+ # B) Once all known jobs have been run until they are complete or paused for data, run all pending data sources.
147
+ # - Similarly, create a Fiber to consume pending sources and tell them to load their data.
148
+ # - If one of those Fibers pauses, then create a new Fiber to continue working through remaining pending sources.
149
+ # - When a source causes another source to become pending, run the newly-pending source _first_, since it's a dependency of the previous one.
150
+ # C) After all pending sources have been completely loaded (there are no more pending sources), resume any Fibers that were waiting for data.
151
+ # - Those Fibers assume that source caches will have been populated with the data they were waiting for.
152
+ # - Those Fibers may request data from a source again, in which case they will yeilded and be added to a new pending fiber list.
153
+ # D) Once all pending fibers have been resumed once, return to `A` above.
154
+ #
155
+ # For whatever reason, the best implementation I could find was to order the steps `[D, A, B, C]`, with a special case for skipping `D`
156
+ # on the first pass. I just couldn't find a better way to write the loops in a way that was DRY and easy to read.
157
+ #
158
+ pending_fibers = []
159
+ next_fibers = []
160
+ pending_source_fibers = []
161
+ next_source_fibers = []
162
+ first_pass = true
163
+
164
+ while first_pass || (f = pending_fibers.shift)
165
+ if first_pass
166
+ first_pass = false
167
+ else
168
+ # These fibers were previously waiting for sources to load data,
169
+ # resume them. (They might wait again, in which case, re-enqueue them.)
170
+ resume(f)
171
+ if f.alive?
172
+ next_fibers << f
173
+ end
174
+ end
175
+
176
+ while @pending_jobs.any?
177
+ # Create a Fiber to consume jobs until one of the jobs yields
178
+ # or jobs run out
179
+ f = spawn_fiber {
180
+ while (job = @pending_jobs.shift)
181
+ job.call
182
+ end
183
+ }
184
+ resume(f)
185
+ # In this case, the job yielded. Queue it up to run again after
186
+ # we load whatever it's waiting for.
187
+ if f.alive?
188
+ next_fibers << f
189
+ end
190
+ end
191
+
192
+ if pending_fibers.empty?
193
+ # Now, run all Sources which have become pending _before_ resuming GraphQL execution.
194
+ # Sources might queue up other Sources, which is fine -- those will also run before resuming execution.
195
+ #
196
+ # This is where an evented approach would be even better -- can we tell which
197
+ # fibers are ready to continue, and continue execution there?
198
+ #
199
+ if (first_source_fiber = create_source_fiber)
200
+ pending_source_fibers << first_source_fiber
201
+ end
202
+
203
+ while pending_source_fibers.any?
204
+ while (outer_source_fiber = pending_source_fibers.pop)
205
+ resume(outer_source_fiber)
206
+ if outer_source_fiber.alive?
207
+ next_source_fibers << outer_source_fiber
208
+ end
209
+ if (next_source_fiber = create_source_fiber)
210
+ pending_source_fibers << next_source_fiber
211
+ end
212
+ end
213
+ join_queues(pending_source_fibers, next_source_fibers)
214
+ next_source_fibers.clear
215
+ end
216
+ # Move newly-enqueued Fibers on to the list to be resumed.
217
+ # Clear out the list of next-round Fibers, so that
218
+ # any Fibers that pause can be put on it.
219
+ join_queues(pending_fibers, next_fibers)
220
+ next_fibers.clear
221
+ end
222
+ end
223
+
224
+ if @pending_jobs.any?
225
+ raise "Invariant: #{@pending_jobs.size} pending jobs"
226
+ elsif pending_fibers.any?
227
+ raise "Invariant: #{pending_fibers.size} pending fibers"
228
+ elsif next_fibers.any?
229
+ raise "Invariant: #{next_fibers.size} next fibers"
230
+ end
231
+ nil
232
+ end
233
+
234
+ def join_queues(previous_queue, next_queue)
235
+ if @nonblocking
236
+ Fiber.scheduler.run
237
+ next_queue.select!(&:alive?)
238
+ end
239
+ previous_queue.concat(next_queue)
240
+ end
241
+
242
+ private
243
+
244
+ # If there are pending sources, return a fiber for running them.
245
+ # Otherwise, return `nil`.
246
+ #
247
+ # @return [Fiber, nil]
248
+ def create_source_fiber
249
+ pending_sources = nil
250
+ @source_cache.each_value do |source_by_batch_params|
251
+ source_by_batch_params.each_value do |source|
252
+ if source.pending?
253
+ pending_sources ||= []
254
+ pending_sources << source
255
+ end
256
+ end
257
+ end
258
+
259
+ if pending_sources
260
+ # By passing the whole array into this Fiber, it's possible that we set ourselves up for a bunch of no-ops.
261
+ # For example, if you have sources `[a, b, c]`, and `a` is loaded, then `b` yields to wait for `d`, then
262
+ # the next fiber would be dispatched with `[c, d]`. It would fulfill `c`, then `d`, then eventually
263
+ # the previous fiber would start up again. `c` would no longer be pending, but it would still receive `.run_pending_keys`.
264
+ # That method is short-circuited since it isn't pending any more, but it's still a waste.
265
+ #
266
+ # This design could probably be improved by maintaining a `@pending_sources` queue which is shared by the fibers,
267
+ # similar to `@pending_jobs`. That way, when a fiber is resumed, it would never pick up work that was finished by a different fiber.
268
+ source_fiber = spawn_fiber do
269
+ pending_sources.each(&:run_pending_keys)
270
+ end
271
+ end
272
+
273
+ source_fiber
274
+ end
275
+
276
+ def resume(fiber)
277
+ fiber.resume
278
+ rescue UncaughtThrowError => e
279
+ throw e.tag, e.value
280
+ end
281
+
282
+ # Copies the thread local vars into the fiber thread local vars. Many
283
+ # gems (such as RequestStore, MiniRacer, etc.) rely on thread local vars
284
+ # to keep track of execution context, and without this they do not
285
+ # behave as expected.
286
+ #
287
+ # @see https://github.com/rmosolgo/graphql-ruby/issues/3449
288
+ def spawn_fiber
289
+ fiber_locals = {}
290
+
291
+ Thread.current.keys.each do |fiber_var_key|
292
+ # This variable should be fresh in each new fiber
293
+ if fiber_var_key != :__graphql_runtime_info
294
+ fiber_locals[fiber_var_key] = Thread.current[fiber_var_key]
295
+ end
296
+ end
297
+
298
+ if @nonblocking
299
+ Fiber.new(blocking: false) do
300
+ fiber_locals.each { |k, v| Thread.current[k] = v }
301
+ yield
302
+ end
303
+ else
304
+ Fiber.new do
305
+ fiber_locals.each { |k, v| Thread.current[k] = v }
306
+ yield
307
+ end
308
+ end
309
+ end
310
+ end
311
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ # This error is raised when `Types::ISO8601Date` is asked to return a value
4
+ # that cannot be parsed to a Ruby Date.
5
+ #
6
+ # @see GraphQL::Types::ISO8601Date which raises this error
7
+ class DateEncodingError < GraphQL::RuntimeTypeError
8
+ # The value which couldn't be encoded
9
+ attr_reader :date_value
10
+
11
+ def initialize(value)
12
+ @date_value = value
13
+ super("Date cannot be parsed: #{value}. \nDate must be be able to be parsed as a Ruby Date object.")
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Deprecation
5
+ def self.warn(message)
6
+ Kernel.warn(message)
7
+ end
8
+ end
9
+ end
data/lib/graphql/dig.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  module GraphQL
3
3
  module Dig
4
4
  # implemented using the old activesupport #dig instead of the ruby built-in
5
- # so we can use some of the magic in Schema::InputObject and Query::Arguments
5
+ # so we can use some of the magic in Schema::InputObject and Interpreter::Arguments
6
6
  # to handle stringified/symbolized keys.
7
7
  #
8
8
  # @param args [Array<[String, Symbol>] Retrieves the value object corresponding to the each key objects repeatedly
@@ -18,12 +18,12 @@ module GraphQL
18
18
  case name
19
19
  when SKIP
20
20
  args = query.arguments_for(directive_ast_node, directive_defn)
21
- if args['if'] == true
21
+ if args[:if] == true
22
22
  return false
23
23
  end
24
24
  when INCLUDE
25
25
  args = query.arguments_for(directive_ast_node, directive_defn)
26
- if args['if'] == false
26
+ if args[:if] == false
27
27
  return false
28
28
  end
29
29
  else