Skip to content

Commit 0b42a07

Browse files
authored
Add register_indexer_extension schema definition API (#1299)
## Why Ingestion format gems need a way to ensure their indexer-side behavior is active whenever a schema is defined with their schema definition extension--the same guarantee `register_graphql_extension` provides for GraphQL extensions (e.g. how `elasticgraph-apollo` registers its engine extension). ## What - Add `register_indexer_extension` to the schema definition API, mirroring `register_graphql_extension` - Registered extensions are dumped into the `indexer_extension_modules` runtime metadata added in #1298 ## Verification - `script/lint`, `script/type_check` - `script/run_gem_specs elasticgraph-schema_definition` (100% coverage) ## Stack Current PR is marked with `->`. - [#1298 Add indexer_extension_modules to runtime metadata](#1298) - -> [#1299 Add register_indexer_extension schema definition API](#1299) - [#1300 Apply indexer extension modules when the Indexer boots](#1300) - [#1301 Extract an ingestion adapter seam inside elasticgraph-indexer](#1301) - [#1302 Move JSON ingestion into elasticgraph-json_ingestion via an indexer extension](#1302)
1 parent 9f3769c commit 0b42a07

7 files changed

Lines changed: 87 additions & 1 deletion

File tree

config/site/support/doctest_helper.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,16 @@ def self.prepare_for_indexing(value)
157157
::File.write("artist_resolver.rb", "")
158158
end
159159

160+
doctest.before "ElasticGraph::SchemaDefinition::API#register_indexer_extension" do
161+
::FileUtils.mkdir_p "my_gem"
162+
::File.write("my_gem/indexer_extension.rb", <<~EOS)
163+
module MyGem
164+
module IndexerExtension
165+
end
166+
end
167+
EOS
168+
end
169+
160170
[
161171
"ElasticGraph::Apollo@Use elasticgraph-apollo in a project",
162172
"ElasticGraph::Apollo::SchemaDefinition::APIExtension@Define local rake tasks with this extension module",

elasticgraph-schema_definition/lib/elastic_graph/schema_definition/api.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,36 @@ def register_graphql_extension(extension_module, defined_at:, **config)
348348
nil
349349
end
350350

351+
# Registers an indexer extension module that will be loaded and used by `elasticgraph-indexer`. While such
352+
# extension modules can also be configured in a settings YAML file, it can be useful to register it here
353+
# when you want to ensure that the extension is used in all environments. For example, an ingestion format
354+
# library needs to ensure its corresponding indexer extension module is used since events of its format
355+
# would not be ingestible otherwise.
356+
#
357+
# @param extension_module [Module] indexer extension module
358+
# @param defined_at [String] the `require` path of the extension module
359+
# @param config [Hash<Symbol, Object>] configuration options for the extension module
360+
# @return [void]
361+
#
362+
# @example Register an indexer extension module
363+
# # In `my_gem/indexer_extension.rb`:
364+
# module MyGem
365+
# module IndexerExtension
366+
# end
367+
# end
368+
#
369+
# require(indexer_extension_require_path = "./my_gem/indexer_extension")
370+
#
371+
# ElasticGraph.define_schema do |schema|
372+
# schema.register_indexer_extension MyGem::IndexerExtension,
373+
# defined_at: indexer_extension_require_path
374+
# end
375+
def register_indexer_extension(extension_module, defined_at:, **config)
376+
extension = SchemaArtifacts::RuntimeMetadata::Extension.new(extension_module, defined_at, config)
377+
@state.indexer_extension_modules << SchemaArtifacts::RuntimeMetadata::ComponentExtension.new(extension.to_dumpable_hash)
378+
nil
379+
end
380+
351381
# Registers a GraphQL resolver that will be loaded and used by `elasticgraph-graphql`. To use a GraphQL resolver you have
352382
# registered, set a field's `resolver` to the name you provide when registering your resolver.
353383
#

elasticgraph-schema_definition/lib/elastic_graph/schema_definition/results.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def build_runtime_metadata
125125
schema_element_names: state.schema_elements,
126126
graphql_extension_modules: state.graphql_extension_modules,
127127
graphql_resolvers_by_name: state.graphql_resolvers_by_name,
128-
indexer_extension_modules: [],
128+
indexer_extension_modules: state.indexer_extension_modules,
129129
static_script_ids_by_scoped_name: STATIC_SCRIPT_REPO.script_ids_by_scoped_name
130130
).tap { |rm| verify_runtime_metadata(rm) }
131131
end

elasticgraph-schema_definition/lib/elastic_graph/schema_definition/state.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class State < Struct.new(
3939
:reserved_type_names,
4040
:graphql_extension_modules,
4141
:graphql_resolvers_by_name,
42+
:indexer_extension_modules,
4243
:built_in_graphql_resolvers,
4344
:initially_registered_built_in_types,
4445
:built_in_types_customization_blocks,
@@ -86,6 +87,7 @@ def self.with(
8687
reserved_type_names: ::Set.new,
8788
graphql_extension_modules: [],
8889
graphql_resolvers_by_name: {},
90+
indexer_extension_modules: [],
8991
built_in_graphql_resolvers: ::Set.new,
9092
initially_registered_built_in_types: ::Set.new,
9193
built_in_types_customization_blocks: [],

elasticgraph-schema_definition/sig/elastic_graph/schema_definition/api.rbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ module ElasticGraph
7777
@results: Results?
7878
def results: () -> Results
7979
def register_graphql_extension: (::Module, defined_at: ::String, **untyped) -> void
80+
def register_indexer_extension: (::Module, defined_at: ::String, **untyped) -> void
8081
def register_graphql_resolver: (::Symbol, ::Class, defined_at: ::String, ?built_in: bool, **untyped) -> void
8182
def on_built_in_types: () { (SchemaElements::graphQLType) -> void } -> void
8283
def on_root_query_type: () { (SchemaElements::ObjectType) -> void } -> void

elasticgraph-schema_definition/sig/elastic_graph/schema_definition/state.rbs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ module ElasticGraph
1717
attr_reader reserved_type_names: ::Set[::String]
1818
attr_reader graphql_extension_modules: ::Array[SchemaArtifacts::RuntimeMetadata::ComponentExtension]
1919
attr_reader graphql_resolvers_by_name: ::Hash[::Symbol, SchemaArtifacts::RuntimeMetadata::GraphQLResolver]
20+
attr_reader indexer_extension_modules: ::Array[SchemaArtifacts::RuntimeMetadata::ComponentExtension]
2021
attr_reader built_in_graphql_resolvers: ::Set[::Symbol]
2122
attr_accessor initially_registered_built_in_types: ::Set[::String]
2223
attr_accessor built_in_types_customization_blocks: ::Array[^(SchemaElements::graphQLType) -> void]
@@ -50,6 +51,7 @@ module ElasticGraph
5051
reserved_type_names: ::Set[::String],
5152
graphql_extension_modules: ::Array[SchemaArtifacts::RuntimeMetadata::ComponentExtension],
5253
graphql_resolvers_by_name: ::Hash[::Symbol, SchemaArtifacts::RuntimeMetadata::GraphQLResolver],
54+
indexer_extension_modules: ::Array[SchemaArtifacts::RuntimeMetadata::ComponentExtension],
5355
built_in_graphql_resolvers: ::Set[::Symbol],
5456
initially_registered_built_in_types: ::Set[::String],
5557
built_in_types_customization_blocks: ::Array[^(SchemaElements::graphQLType) -> void],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright 2024 - 2026 Block, Inc.
2+
#
3+
# Use of this source code is governed by an MIT-style
4+
# license that can be found in the LICENSE file or at
5+
# https://opensource.org/licenses/MIT.
6+
#
7+
# frozen_string_literal: true
8+
9+
require_relative "runtime_metadata_support"
10+
11+
module ElasticGraph
12+
module SchemaDefinition
13+
RSpec.describe "RuntimeMetadata #indexer_extension_modules" do
14+
include_context "RuntimeMetadata support"
15+
16+
it "includes any modules registered during schema definition" do
17+
extension_module1 = Module.new
18+
extension_module2 = Module.new
19+
20+
metadata = define_schema do |s|
21+
s.register_indexer_extension extension_module1, defined_at: __FILE__
22+
s.register_indexer_extension extension_module2, defined_at: __FILE__
23+
24+
s.object_type "Widget" do |t|
25+
t.field "id", "ID!"
26+
t.index "widgets"
27+
end
28+
end.runtime_metadata
29+
30+
expect(metadata.indexer_extension_modules).to eq [
31+
SchemaArtifacts::RuntimeMetadata::ComponentExtension.new(
32+
SchemaArtifacts::RuntimeMetadata::Extension.new(extension_module1, __FILE__, {}).to_dumpable_hash
33+
),
34+
SchemaArtifacts::RuntimeMetadata::ComponentExtension.new(
35+
SchemaArtifacts::RuntimeMetadata::Extension.new(extension_module2, __FILE__, {}).to_dumpable_hash
36+
)
37+
]
38+
end
39+
end
40+
end
41+
end

0 commit comments

Comments
 (0)