elasticgraph-schema_definition 0.19.1.1 → 0.19.2.0
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.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/lib/elastic_graph/schema_definition/api.rb +111 -6
- data/lib/elastic_graph/schema_definition/factory.rb +25 -23
- data/lib/elastic_graph/schema_definition/indexing/derived_fields/append_only_set.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/derived_fields/field_initializer_support.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/derived_fields/immutable_value.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/derived_fields/min_or_max_value.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/derived_indexed_type.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/event_envelope.rb +12 -3
- data/lib/elastic_graph/schema_definition/indexing/field.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/field_reference.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/field_type/enum.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/field_type/object.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/field_type/scalar.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/field_type/union.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/index.rb +4 -2
- data/lib/elastic_graph/schema_definition/indexing/json_schema_field_metadata.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/json_schema_with_metadata.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/list_counts_mapping.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/relationship_resolver.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/rollover_config.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/update_target_factory.rb +1 -1
- data/lib/elastic_graph/schema_definition/indexing/update_target_resolver.rb +1 -1
- data/lib/elastic_graph/schema_definition/json_schema_pruner.rb +4 -2
- data/lib/elastic_graph/schema_definition/mixins/can_be_graphql_only.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/has_derived_graphql_type_customizations.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/has_directives.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/has_documentation.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/has_indices.rb +40 -4
- data/lib/elastic_graph/schema_definition/mixins/has_readable_to_s_and_inspect.rb +2 -1
- data/lib/elastic_graph/schema_definition/mixins/has_subtypes.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/has_type_info.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/implements_interfaces.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/supports_default_value.rb +1 -1
- data/lib/elastic_graph/schema_definition/mixins/supports_filtering_and_aggregation.rb +9 -3
- data/lib/elastic_graph/schema_definition/mixins/verifies_graphql_name.rb +1 -1
- data/lib/elastic_graph/schema_definition/rake_tasks.rb +1 -1
- data/lib/elastic_graph/schema_definition/results.rb +133 -13
- data/lib/elastic_graph/schema_definition/schema_artifact_manager.rb +4 -4
- data/lib/elastic_graph/schema_definition/schema_elements/argument.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/built_in_types.rb +47 -15
- data/lib/elastic_graph/schema_definition/schema_elements/deprecated_element.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/directive.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/enum_type.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/enum_value.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/enum_value_namer.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/enums_for_indexed_types.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/field.rb +15 -10
- data/lib/elastic_graph/schema_definition/schema_elements/field_path.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/field_source.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/graphql_sdl_enumerator.rb +4 -78
- data/lib/elastic_graph/schema_definition/schema_elements/input_field.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/input_type.rb +6 -2
- data/lib/elastic_graph/schema_definition/schema_elements/interface_type.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/list_counts_state.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/object_type.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/relationship.rb +8 -2
- data/lib/elastic_graph/schema_definition/schema_elements/scalar_type.rb +3 -3
- data/lib/elastic_graph/schema_definition/schema_elements/sort_order_enum_value.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/sub_aggregation_path.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/type_namer.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/type_reference.rb +1 -1
- data/lib/elastic_graph/schema_definition/schema_elements/type_with_subfields.rb +4 -5
- data/lib/elastic_graph/schema_definition/schema_elements/union_type.rb +1 -1
- data/lib/elastic_graph/schema_definition/scripting/file_system_repository.rb +1 -1
- data/lib/elastic_graph/schema_definition/scripting/script.rb +1 -1
- data/lib/elastic_graph/schema_definition/state.rb +4 -1
- data/lib/elastic_graph/schema_definition/test_support.rb +23 -3
- metadata +32 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22e12695336b4d4f8783be5181dfe89462829d9603709092c1748be483582d34
|
4
|
+
data.tar.gz: ad51712ce4e2c784c68472a9ca3d7708aeb12bc4394eb884d946335bad7353a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 922823d7384a8ff245530e51ccd465fcadf53d8a072b996fbc9417a520df031db98c5782ad416bcce233e3b0d2fec5584ce1840a6be39e9b87944d195f303e7f
|
7
|
+
data.tar.gz: 347c485375ea7dc41e2ee212fe155a1cbcf937008956b9387c78e97b97c02869057f103f23adc1a98f2a3c2972ac1fa09a34f61001d030c4c0fcb779c9a8282e
|
data/LICENSE.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -8,6 +8,7 @@
|
|
8
8
|
|
9
9
|
require "elastic_graph/errors"
|
10
10
|
require "elastic_graph/schema_artifacts/runtime_metadata/extension"
|
11
|
+
require "elastic_graph/schema_artifacts/runtime_metadata/graphql_resolver"
|
11
12
|
require "elastic_graph/schema_definition/mixins/has_readable_to_s_and_inspect"
|
12
13
|
require "elastic_graph/schema_definition/results"
|
13
14
|
require "elastic_graph/schema_definition/state"
|
@@ -130,7 +131,7 @@ module ElasticGraph
|
|
130
131
|
nil
|
131
132
|
end
|
132
133
|
|
133
|
-
# Defines a [GraphQL interface](https://graphql.org/learn/schema/#
|
134
|
+
# Defines a [GraphQL interface](https://graphql.org/learn/schema/#interface-types). Use it to define an abstract supertype with
|
134
135
|
# one or more fields that concrete implementations of the interface must also define. Each implementation can be an
|
135
136
|
# {SchemaElements::ObjectType} or {SchemaElements::InterfaceType}.
|
136
137
|
#
|
@@ -164,7 +165,7 @@ module ElasticGraph
|
|
164
165
|
nil
|
165
166
|
end
|
166
167
|
|
167
|
-
# Defines a [GraphQL enum type](https://graphql.org/learn/schema/#
|
168
|
+
# Defines a [GraphQL enum type](https://graphql.org/learn/schema/#enum-types).
|
168
169
|
# The type is restricted to an enumerated set of values, each with a unique name.
|
169
170
|
# Use `value` or `values` to define the enum values in the passed block.
|
170
171
|
#
|
@@ -275,7 +276,7 @@ module ElasticGraph
|
|
275
276
|
#
|
276
277
|
# @param extension_module [Module] GraphQL extension module
|
277
278
|
# @param defined_at [String] the `require` path of the extension module
|
278
|
-
# @param
|
279
|
+
# @param config [Hash<Symbol, Object>] configuration options for the extension module
|
279
280
|
# @return [void]
|
280
281
|
#
|
281
282
|
# @example Register `elasticgraph-query_registry` extension module
|
@@ -285,8 +286,94 @@ module ElasticGraph
|
|
285
286
|
# schema.register_graphql_extension ElasticGraph::QueryRegistry::GraphQLExtension,
|
286
287
|
# defined_at: query_registry_require_path
|
287
288
|
# end
|
288
|
-
def register_graphql_extension(extension_module, defined_at:, **
|
289
|
-
@state.graphql_extension_modules << SchemaArtifacts::RuntimeMetadata::Extension.new(extension_module, defined_at,
|
289
|
+
def register_graphql_extension(extension_module, defined_at:, **config)
|
290
|
+
@state.graphql_extension_modules << SchemaArtifacts::RuntimeMetadata::Extension.new(extension_module, defined_at, config)
|
291
|
+
nil
|
292
|
+
end
|
293
|
+
|
294
|
+
# Registers a GraphQL resolver that will be loaded and used by `elasticgraph-graphql`. To use a GraphQL resolver you have
|
295
|
+
# registered, set a field's `resolver` to the name you provide when registering your resolver.
|
296
|
+
#
|
297
|
+
# @param name [Symbol] unique name of the resolver
|
298
|
+
# @param klass [Class] resolver class
|
299
|
+
# @param defined_at [String] the `require` path of the resolver
|
300
|
+
# @param resolver_config [Hash<Symbol, Object>] configuration options for the resolver, to support parameterized resolvers
|
301
|
+
# @return [void]
|
302
|
+
#
|
303
|
+
# @example Register a custom resolver for use by a custom `Query` field
|
304
|
+
# # In `add_resolver.rb`:
|
305
|
+
# class AddResolver
|
306
|
+
# def initialize(elasticgraph_graphql:, config:)
|
307
|
+
# end
|
308
|
+
#
|
309
|
+
# def resolve(field:, object:, args:, context:)
|
310
|
+
# args.fetch("x") + args.fetch("y")
|
311
|
+
# end
|
312
|
+
# end
|
313
|
+
#
|
314
|
+
# # In `config/schema.rb`:
|
315
|
+
# ElasticGraph.define_schema do |schema|
|
316
|
+
# require(resolver_path = "add_resolver")
|
317
|
+
# schema.register_graphql_resolver :add, AddResolver, defined_at: resolver_path
|
318
|
+
#
|
319
|
+
# schema.on_root_query_type do |t|
|
320
|
+
# t.field "add", "Int" do |f|
|
321
|
+
# f.argument "x", "Int!"
|
322
|
+
# f.argument "y", "Int!"
|
323
|
+
# f.resolver = :add
|
324
|
+
# end
|
325
|
+
# end
|
326
|
+
# end
|
327
|
+
#
|
328
|
+
# @example Register a custom resolver that uses lookahead
|
329
|
+
#
|
330
|
+
# # In `artist_resolver.rb`:
|
331
|
+
# class ArtistResolver
|
332
|
+
# def initialize(elasticgraph_graphql:, config:)
|
333
|
+
# end
|
334
|
+
#
|
335
|
+
# def resolve(field:, object:, args:, context:, lookahead:)
|
336
|
+
# # The extra `lookahead` argument can be used to see what child fields are selected.
|
337
|
+
# # See https://graphql-ruby.org/queries/lookahead.html for details.
|
338
|
+
# #
|
339
|
+
# # Note: there is overhead involved in providing the `lookahead`, so it's best to not
|
340
|
+
# # request it (by defining it as one of the `resolve` arguments) unless it's really needed.
|
341
|
+
# end
|
342
|
+
# end
|
343
|
+
#
|
344
|
+
# # In `config/schema.rb`:
|
345
|
+
# ElasticGraph.define_schema do |schema|
|
346
|
+
# require(resolver_path = "artist_resolver")
|
347
|
+
# schema.register_graphql_resolver :artist, ArtistResolver, defined_at: resolver_path
|
348
|
+
#
|
349
|
+
# schema.object_type "Artist" do |t|
|
350
|
+
# t.field "name", "String"
|
351
|
+
# # ...
|
352
|
+
# end
|
353
|
+
#
|
354
|
+
# schema.on_root_query_type do |t|
|
355
|
+
# t.field "artist", "Artist" do |f|
|
356
|
+
# f.resolver = :artist
|
357
|
+
# end
|
358
|
+
# end
|
359
|
+
# end
|
360
|
+
def register_graphql_resolver(name, klass, defined_at:, **resolver_config)
|
361
|
+
extension = SchemaArtifacts::RuntimeMetadata::Extension.new(klass, defined_at, resolver_config)
|
362
|
+
|
363
|
+
needs_lookahead =
|
364
|
+
if extension.verify_against(SchemaArtifacts::RuntimeMetadata::GraphQLResolver::InterfaceWithLookahead).empty?
|
365
|
+
true
|
366
|
+
else
|
367
|
+
extension.verify_against!(SchemaArtifacts::RuntimeMetadata::GraphQLResolver::InterfaceWithoutLookahead)
|
368
|
+
false
|
369
|
+
end
|
370
|
+
|
371
|
+
resolver = SchemaArtifacts::RuntimeMetadata::GraphQLResolver.new(
|
372
|
+
needs_lookahead: needs_lookahead,
|
373
|
+
resolver_ref: extension.to_dumpable_hash
|
374
|
+
)
|
375
|
+
|
376
|
+
@state.graphql_resolvers_by_name[name] = resolver
|
290
377
|
nil
|
291
378
|
end
|
292
379
|
|
@@ -343,6 +430,24 @@ module ElasticGraph
|
|
343
430
|
nil
|
344
431
|
end
|
345
432
|
|
433
|
+
# Registers a customization callback that will be applied to the root `Query` type when it is generated.
|
434
|
+
#
|
435
|
+
# @yield [SchemaElements::ObjectType] the root `Query` type
|
436
|
+
# @return [void]
|
437
|
+
#
|
438
|
+
# @example Customize documentation of built-in types
|
439
|
+
# ElasticGraph.define_schema do |schema|
|
440
|
+
# schema.on_root_query_type do |type|
|
441
|
+
# type.append_to_documentation "This schema has been generated by ElasticGraph."
|
442
|
+
# end
|
443
|
+
# end
|
444
|
+
def on_root_query_type(&customization_block)
|
445
|
+
on_built_in_types do |type|
|
446
|
+
customization_block.call(_ = type) if type.name == "Query"
|
447
|
+
end
|
448
|
+
nil
|
449
|
+
end
|
450
|
+
|
346
451
|
# While the block executes, makes any `ElasticGraph.define_schema` calls operate on this `API` instance.
|
347
452
|
#
|
348
453
|
# @private
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -115,8 +115,8 @@ module ElasticGraph
|
|
115
115
|
end
|
116
116
|
@@field_new = prevent_non_factory_instantiation_of(SchemaElements::Field)
|
117
117
|
|
118
|
-
def new_graphql_sdl_enumerator(
|
119
|
-
@@graphql_sdl_enumerator_new.call(@state,
|
118
|
+
def new_graphql_sdl_enumerator(all_types)
|
119
|
+
@@graphql_sdl_enumerator_new.call(@state, all_types)
|
120
120
|
end
|
121
121
|
@@graphql_sdl_enumerator_new = prevent_non_factory_instantiation_of(SchemaElements::GraphQLSDLEnumerator)
|
122
122
|
|
@@ -137,6 +137,8 @@ module ElasticGraph
|
|
137
137
|
@@input_type_new = prevent_non_factory_instantiation_of(SchemaElements::InputType)
|
138
138
|
|
139
139
|
def new_filter_input_type(source_type, name_prefix: source_type, category: :filter_input)
|
140
|
+
all_of = @state.schema_elements.all_of
|
141
|
+
any_of = @state.schema_elements.any_of
|
140
142
|
new_input_type(@state.type_ref(name_prefix).as_static_derived_type(category).name) do |t|
|
141
143
|
t.documentation <<~EOS
|
142
144
|
Input type used to specify filters on `#{source_type}` fields.
|
@@ -154,6 +156,18 @@ module ElasticGraph
|
|
154
156
|
EOS
|
155
157
|
end
|
156
158
|
|
159
|
+
t.field @state.schema_elements.all_of, "[#{t.name}!]" do |f|
|
160
|
+
f.documentation <<~EOS
|
161
|
+
Matches records where all of the provided sub-filters evaluate to true. This works just like an AND operator in SQL.
|
162
|
+
|
163
|
+
Note: multiple filters are automatically ANDed together. This is only needed when you have multiple filters that can't
|
164
|
+
be provided on a single `#{t.name}` input because of collisions between key names. For example, if you want to AND multiple
|
165
|
+
OR'd sub-filters (the equivalent of (A OR B) AND (C OR D)), you could do #{all_of}: [{#{any_of}: [...]}, {#{any_of}: [...]}].
|
166
|
+
|
167
|
+
When `null` or an empty list is passed, matches all documents.
|
168
|
+
EOS
|
169
|
+
end
|
170
|
+
|
157
171
|
t.field @state.schema_elements.not, t.name do |f|
|
158
172
|
f.documentation <<~EOS
|
159
173
|
Matches records where the provided sub-filter evaluates to false.
|
@@ -272,7 +286,8 @@ module ElasticGraph
|
|
272
286
|
new_object_type @state.type_ref(index_leaf_type).as_aggregated_values.name do |type|
|
273
287
|
type.graphql_only true
|
274
288
|
type.documentation "A return type used from aggregations to provided aggregated values over `#{index_leaf_type}` fields."
|
275
|
-
type.
|
289
|
+
type.default_graphql_resolver = :object_with_lookahead
|
290
|
+
type.override_runtime_metadata(elasticgraph_category: :scalar_aggregated_values)
|
276
291
|
|
277
292
|
type.field @state.schema_elements.approximate_distinct_value_count, "JsonSafeLong", graphql_only: true do |f|
|
278
293
|
# Note: the 1-6% accuracy figure comes from the Elasticsearch docs:
|
@@ -296,7 +311,6 @@ module ElasticGraph
|
|
296
311
|
|
297
312
|
def new_list_filter_input_type(source_type, name_prefix:, any_satisfy_type_category:)
|
298
313
|
any_satisfy = @state.schema_elements.any_satisfy
|
299
|
-
all_of = @state.schema_elements.all_of
|
300
314
|
|
301
315
|
new_filter_input_type "[#{source_type}]", name_prefix: name_prefix, category: :list_filter_input do |t|
|
302
316
|
t.field any_satisfy, @state.type_ref(name_prefix).as_static_derived_type(any_satisfy_type_category).name do |f|
|
@@ -307,18 +321,6 @@ module ElasticGraph
|
|
307
321
|
EOS
|
308
322
|
end
|
309
323
|
|
310
|
-
t.field all_of, "[#{t.name}!]" do |f|
|
311
|
-
f.documentation <<~EOS
|
312
|
-
Matches records where all of the provided sub-filters evaluate to true. This works just like an AND operator in SQL.
|
313
|
-
|
314
|
-
Note: multiple filters are automatically ANDed together. This is only needed when you have multiple filters that can't
|
315
|
-
be provided on a single `#{t.name}` input because of collisions between key names. For example, if you want to provide
|
316
|
-
multiple `#{any_satisfy}: ...` filters, you could do `#{all_of}: [{#{any_satisfy}: ...}, {#{any_satisfy}: ...}]`.
|
317
|
-
|
318
|
-
When `null` or an empty list is passed, matches all documents.
|
319
|
-
EOS
|
320
|
-
end
|
321
|
-
|
322
324
|
define_list_counts_filter_field_on(t)
|
323
325
|
end
|
324
326
|
end
|
@@ -433,7 +435,8 @@ module ElasticGraph
|
|
433
435
|
type_ref = @state.type_ref(type_name)
|
434
436
|
new_object_type type_ref.as_edge.name do |t|
|
435
437
|
t.relay_pagination_type = true
|
436
|
-
t.
|
438
|
+
t.default_graphql_resolver = :object_without_lookahead
|
439
|
+
t.override_runtime_metadata(elasticgraph_category: :relay_edge)
|
437
440
|
|
438
441
|
t.documentation <<~EOS
|
439
442
|
Represents a specific `#{type_name}` in the context of a `#{type_ref.as_connection.name}`,
|
@@ -460,7 +463,8 @@ module ElasticGraph
|
|
460
463
|
type_ref = @state.type_ref(type_name)
|
461
464
|
new_object_type type_ref.as_connection.name do |t|
|
462
465
|
t.relay_pagination_type = true
|
463
|
-
t.
|
466
|
+
t.default_graphql_resolver = :object_without_lookahead
|
467
|
+
t.override_runtime_metadata(elasticgraph_category: :relay_connection)
|
464
468
|
|
465
469
|
if support_pagination
|
466
470
|
t.documentation <<~EOS
|
@@ -483,10 +487,8 @@ module ElasticGraph
|
|
483
487
|
f.documentation "The list of `#{type_name}` results."
|
484
488
|
end
|
485
489
|
|
486
|
-
|
487
|
-
|
488
|
-
f.documentation "Provides pagination-related information."
|
489
|
-
end
|
490
|
+
t.field @state.schema_elements.page_info, "PageInfo!" do |f|
|
491
|
+
f.documentation "Provides pagination-related information."
|
490
492
|
end
|
491
493
|
|
492
494
|
if include_total_edge_count
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -21,41 +21,50 @@ module ElasticGraph
|
|
21
21
|
def self.json_schema(indexed_type_names, json_schema_version)
|
22
22
|
{
|
23
23
|
"type" => "object",
|
24
|
+
"description" => "Required by ElasticGraph to wrap every data event.",
|
24
25
|
"properties" => {
|
25
26
|
"op" => {
|
27
|
+
"description" => "Indicates what type of operation the event represents. For now, only `upsert` is supported, but we plan to support other operations in the future.",
|
26
28
|
"type" => "string",
|
27
29
|
"enum" => %w[upsert]
|
28
30
|
},
|
29
31
|
"type" => {
|
32
|
+
"description" => "The type of object present in `record`.",
|
30
33
|
"type" => "string",
|
31
34
|
# Sorting doesn't really matter here, but it's nice for the output in the schema artifact to be consistent.
|
32
35
|
"enum" => indexed_type_names.sort
|
33
36
|
},
|
34
37
|
"id" => {
|
38
|
+
"description" => "The unique identifier of the record.",
|
35
39
|
"type" => "string",
|
36
40
|
"maxLength" => DEFAULT_MAX_KEYWORD_LENGTH
|
37
41
|
},
|
38
42
|
"version" => {
|
43
|
+
"description" => 'Used to handle duplicate and out-of-order events. When ElasticGraph ingests multiple events for the same `type` and `id`, the one with the largest `version` will "win".',
|
39
44
|
"type" => "integer",
|
40
45
|
"minimum" => 0,
|
41
46
|
"maximum" => (2**63) - 1
|
42
47
|
},
|
43
48
|
"record" => {
|
49
|
+
"description" => "The record of this event. The payload of this field must match the JSON schema of the named `type`.",
|
44
50
|
"type" => "object"
|
45
51
|
},
|
46
52
|
"latency_timestamps" => {
|
53
|
+
"description" => "Timestamps from which ElasticGraph measures indexing latency. The `ElasticGraphIndexingLatencies` log message produced for each event will include a measurement from each timestamp included in this map.",
|
47
54
|
"type" => "object",
|
48
55
|
"additionalProperties" => false,
|
49
56
|
"patternProperties" => {
|
57
|
+
"description" => "A timestamp from which ElasticGraph will measure indexing latency. The timestamp name must end in `_at`.",
|
50
58
|
"^\\w+_at$" => {"type" => "string", "format" => "date-time"}
|
51
59
|
}
|
52
60
|
},
|
53
61
|
JSON_SCHEMA_VERSION_KEY => {
|
62
|
+
"description" => "The version of the JSON schema the publisher was using when the event was published. ElasticGraph will use the JSON schema matching this version to process the event.",
|
54
63
|
"const" => json_schema_version
|
55
64
|
},
|
56
65
|
"message_id" => {
|
57
|
-
"
|
58
|
-
"
|
66
|
+
"description" => "The optional ID of the message containing this event from whatever messaging system is being used between the publisher and the ElasticGraph indexer.",
|
67
|
+
"type" => "string"
|
59
68
|
}
|
60
69
|
},
|
61
70
|
"additionalProperties" => false,
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -248,7 +248,9 @@ module ElasticGraph
|
|
248
248
|
"index.mapping.ignore_malformed" => false,
|
249
249
|
"index.mapping.coerce" => false,
|
250
250
|
"index.number_of_replicas" => 1,
|
251
|
-
"index.number_of_shards" => 1
|
251
|
+
"index.number_of_shards" => 1,
|
252
|
+
# 10K is the default: https://www.elastic.co/guide/en/elasticsearch/reference/8.17/index-modules.html#dynamic-index-settings
|
253
|
+
"index.max_result_window" => 10000
|
252
254
|
}
|
253
255
|
|
254
256
|
def mappings
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -21,7 +21,9 @@ module ElasticGraph
|
|
21
21
|
types_to_keep = referenced_type_names(initial_type_names, original_json_schema["$defs"])
|
22
22
|
|
23
23
|
# The .select will preserve the sort order of the original hash
|
24
|
+
# standard:disable Style/HashSlice -- https://github.com/soutaro/steep/issues/1503
|
24
25
|
pruned_defs = original_json_schema["$defs"].select { |k, _v| types_to_keep.include?(k) }
|
26
|
+
# standard:enable Style/HashSlice
|
25
27
|
|
26
28
|
original_json_schema.merge("$defs" => pruned_defs)
|
27
29
|
end
|
@@ -31,7 +33,7 @@ module ElasticGraph
|
|
31
33
|
def self.referenced_type_names(source_type_names, original_defs)
|
32
34
|
return Set.new if source_type_names.empty?
|
33
35
|
|
34
|
-
referenced_type_defs = original_defs.
|
36
|
+
referenced_type_defs = original_defs.slice(*source_type_names)
|
35
37
|
ref_names = collect_ref_names(referenced_type_defs)
|
36
38
|
|
37
39
|
referenced_type_names(ref_names, original_defs) + source_type_names
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -7,6 +7,7 @@
|
|
7
7
|
# frozen_string_literal: true
|
8
8
|
|
9
9
|
require "elastic_graph/constants"
|
10
|
+
require "elastic_graph/errors"
|
10
11
|
require "elastic_graph/schema_definition/indexing/update_target_factory"
|
11
12
|
|
12
13
|
module ElasticGraph
|
@@ -16,12 +17,17 @@ module ElasticGraph
|
|
16
17
|
module HasIndices
|
17
18
|
# @dynamic runtime_metadata_overrides
|
18
19
|
# @private
|
19
|
-
|
20
|
+
attr_reader :runtime_metadata_overrides
|
21
|
+
|
22
|
+
# @return [::Symbol, nil] the default GraphQL resolver to use for fields on this type
|
23
|
+
attr_accessor :default_graphql_resolver
|
24
|
+
# @dynamic default_graphql_resolver, default_graphql_resolver=
|
20
25
|
|
21
26
|
# @private
|
22
27
|
def initialize(*args, **options)
|
23
28
|
super(*args, **options)
|
24
|
-
|
29
|
+
@runtime_metadata_overrides = {}
|
30
|
+
self.default_graphql_resolver = :get_record_field_value
|
25
31
|
yield self
|
26
32
|
|
27
33
|
# Freeze `indices` so that the indexable status of a type does not change after instantiation.
|
@@ -150,6 +156,15 @@ module ElasticGraph
|
|
150
156
|
@derived_indexed_types ||= []
|
151
157
|
end
|
152
158
|
|
159
|
+
# Configures overrides for runtime metadata. The provided runtime metadata values will be persisted in the
|
160
|
+
# `runtime_metadata.yaml` schema artifact and made available at runtime to `elasticgraph-graphql` and
|
161
|
+
# `elasticgraph-indexer`.
|
162
|
+
#
|
163
|
+
# @return [void]
|
164
|
+
def override_runtime_metadata(**overrides)
|
165
|
+
@runtime_metadata_overrides.merge!(overrides)
|
166
|
+
end
|
167
|
+
|
153
168
|
# @private
|
154
169
|
def runtime_metadata(extra_update_targets)
|
155
170
|
SchemaArtifacts::RuntimeMetadata::ObjectType.new(
|
@@ -255,7 +270,28 @@ module ElasticGraph
|
|
255
270
|
end
|
256
271
|
|
257
272
|
def runtime_metadata_graphql_fields_by_name
|
258
|
-
graphql_fields_by_name.transform_values
|
273
|
+
graphql_fields_by_name.transform_values do |field|
|
274
|
+
field_metadata = field.runtime_metadata_graphql_field
|
275
|
+
|
276
|
+
if field_metadata.resolver.nil?
|
277
|
+
if default_graphql_resolver
|
278
|
+
field_metadata.with(resolver: default_graphql_resolver)
|
279
|
+
else
|
280
|
+
parent_type_option =
|
281
|
+
if name == "Query"
|
282
|
+
# With `Query`, we don't want to use the `default_graphql_resolver`. Each field should set its own resolver.
|
283
|
+
""
|
284
|
+
else
|
285
|
+
"the `default_graphql_resolver` on the parent type (`#{name}`) or "
|
286
|
+
end
|
287
|
+
|
288
|
+
raise Errors::SchemaError, "`#{name}.#{field.name}` needs a resolver. Fix by assigning #{parent_type_option}" \
|
289
|
+
"a `resolver` on the field (`#{field.name}`)."
|
290
|
+
end
|
291
|
+
else
|
292
|
+
field_metadata
|
293
|
+
end
|
294
|
+
end
|
259
295
|
end
|
260
296
|
|
261
297
|
# Provides a "best effort" conversion of a type name to the plural form.
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
1
|
+
# Copyright 2024 - 2025 Block, Inc.
|
2
2
|
#
|
3
3
|
# Use of this source code is governed by an MIT-style
|
4
4
|
# license that can be found in the LICENSE file or at
|
@@ -29,6 +29,7 @@ module ElasticGraph
|
|
29
29
|
def initialize
|
30
30
|
if block_given?
|
31
31
|
define_method :to_s do
|
32
|
+
# @type self: HasReadableToSAndInspect
|
32
33
|
"#<#{self.class.name} #{yield self}>"
|
33
34
|
end
|
34
35
|
else
|