Skip to content

Extract indexing field metadata behind a format-neutral value object - #1351

Open
jwils wants to merge 1 commit into
joshuaw/indexer-ingestion-adaptersfrom
joshuaw/indexing-field-metadata
Open

Extract indexing field metadata behind a format-neutral value object#1351
jwils wants to merge 1 commit into
joshuaw/indexer-ingestion-adaptersfrom
joshuaw/indexing-field-metadata

Conversation

@jwils

@jwils jwils commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

Why

Indexer::RecordPreparer read its per-field indexing metadata straight out of the JSON schema artifacts. It received raw hashes shaped like {"type" => "ID!", "nameInIndex" => "id"} and called eg_meta.fetch("nameInIndex") directly.

That made the JSON schema representation part of the indexer's record-preparation contract. elasticgraph-indexer is meant to stay ingestion-format-neutral, but an ingestion format with no JSON schemas (such as the planned elasticgraph-proto_ingestion runtime) could only supply metadata by synthesizing JSON-schema-shaped hashes with camelCase keys.

What

  • Add RecordPreparer::FieldMetadata, a value object with type and name_in_index.
  • RecordPreparer::TypeMetadata now exposes fields_by_name (a Hash<String, FieldMetadata>) instead of eg_meta_by_field_name.
  • RecordPreparer uses field.name_in_index and field.type instead of fetching camelCase JSON schema keys.
  • JSONIngestion::RecordPreparerFactory converts the JSON schema ElasticGraph metadata into FieldMetadata, so the JSON schema key names stay inside elasticgraph-json_ingestion.
  • Add a spec that builds a RecordPreparer directly from TypeMetadata and FieldMetadata, with no JSON schema involved. This is the path a non-JSON ingestion format will use.

Behavior is unchanged. This is a pure refactor of the contract between the indexer and the ingestion format gems.

Follow-up

This removes the shape coupling. A later PR still needs to give non-JSON formats a source for this metadata. Today name_in_index and the indexing type are recorded only in the versioned JSON schema artifacts.

Runtime metadata is not a sufficient substitute. Its graphql_fields_by_name entries record name_in_index, but they carry no field type, which RecordPreparer needs to select a scalar indexing preparer and to recurse into nested objects. The entries are also unversioned and describe the GraphQL field set, not the ingestion field set.

Verification

  • elasticgraph-indexer, elasticgraph-json_ingestion, elasticgraph-indexer_lambda, elasticgraph-warehouse_lambda, elasticgraph-lambda_support, elasticgraph-warehouse, elasticgraph-local and elasticgraph-apollo unit suites: 673 examples, 0 failures
  • script/lint, script/spellcheck, script/type_check: all green
  • bundle exec rake schema_artifacts:check: artifacts up to date

Stack

Current PR is marked with ->.

@jwils
jwils force-pushed the joshuaw/indexing-field-metadata branch from 228eda8 to a6b87d9 Compare August 21, 2026 13:41
@jwils
jwils force-pushed the joshuaw/indexing-field-metadata branch from a6b87d9 to 2a84c58 Compare September 5, 2026 19:18
@jwils
jwils force-pushed the joshuaw/indexing-field-metadata branch 2 times, most recently from 672592b to e3d4ceb Compare September 9, 2026 14:36
@jwils
jwils force-pushed the joshuaw/indexing-field-metadata branch from e3d4ceb to bfdfe9a Compare September 10, 2026 17:42
@jwils
jwils force-pushed the joshuaw/indexing-field-metadata branch from bfdfe9a to b271dba Compare September 10, 2026 18:13
@jwils
jwils force-pushed the joshuaw/indexing-field-metadata branch from b271dba to 9dc4994 Compare September 11, 2026 15:12
@jwils
jwils force-pushed the joshuaw/indexing-field-metadata branch from 9dc4994 to 9cad9e4 Compare September 11, 2026 15:25
@jwils
jwils force-pushed the joshuaw/indexing-field-metadata branch from 9cad9e4 to 5b42c62 Compare September 11, 2026 15:39
@jwils
jwils force-pushed the joshuaw/indexing-field-metadata branch from 5b42c62 to a93dd5e Compare September 11, 2026 15:55
@jwils
jwils force-pushed the joshuaw/indexing-field-metadata branch from a93dd5e to f88251c Compare September 11, 2026 16:34
jwils added a commit that referenced this pull request Sep 11, 2026
## Why

`Operation::Factory` performs JSON-schema validation and version-based
record-preparer selection inline, which couples the indexer core to the
JSON ingestion format. To support other formats such as protobuf, that
logic needs to live behind a format-neutral seam.

## What

- Add `Indexer::IngestionAdapter`, an interface for validating an event
and providing its record preparer
- Add `Indexer#ingestion_adapters_by_format`, keyed by the event's
`ingestion_format`
- Route each event to one adapter by format; untagged events default to
`json`, while unknown formats produce an actionable `FailedEventError`
- Preserve multiple indexing operations from the selected adapter's
event
- Extract the existing JSON validation and version selection into
`IngestionAdapter::JSONEvents`; the next PR moves it out of
`elasticgraph-indexer`
- Allow tests to inject the complete adapter registry through
`Indexer#initialize`

## Verification

No manual testing.

## Stack
Current PR is marked with `->`.

- -> [#1301 Extract an ingestion adapter seam inside
elasticgraph-indexer](#1301)
- [#1302 Move JSON ingestion into elasticgraph-json_ingestion via an
indexer extension](#1302)
- [#1220 Add configurable indexing event
decoder](#1220)
- [#1351 Extract indexing field metadata behind a format-neutral value
object](#1351)
- [#1284 Keep ingestion schema versions
adapter-owned](#1284)
- [#1376 Pass transport metadata to event
decoders](#1376)
@jwils
jwils force-pushed the joshuaw/indexing-field-metadata branch 2 times, most recently from ecd9040 to 710aae4 Compare September 11, 2026 20:26
@jwils
jwils force-pushed the joshuaw/indexing-field-metadata branch from 710aae4 to 125ea0b Compare September 12, 2026 21:47
@jwils
jwils force-pushed the joshuaw/indexing-field-metadata branch 2 times, most recently from d871497 to 9b4e63e Compare September 12, 2026 22:26
@jwils
jwils force-pushed the joshuaw/indexing-field-metadata branch 2 times, most recently from 9b4e63e to 5c75027 Compare September 12, 2026 22:36
@jwils
jwils force-pushed the joshuaw/indexing-field-metadata branch from 5c75027 to 198b65f Compare September 12, 2026 22:52
`Indexer::RecordPreparer` read its per-field metadata straight out of the
JSON schema artifacts: it received raw `{"type" => ..., "nameInIndex" =>
...}` hashes and called `eg_meta.fetch("nameInIndex")`. That made the
JSON schema representation part of the indexer's record-preparation
contract, so an ingestion format that has no JSON schemas could only
supply metadata by synthesizing JSON-schema-shaped hashes.

The metadata is now a `RecordPreparer::FieldMetadata` value object with
`type` and `name_in_index`, and `RecordPreparer::TypeMetadata` exposes
`fields_by_name` instead of `eg_meta_by_field_name`. The JSON schema key
names stay inside `elasticgraph-json_ingestion`, which converts them when
it builds its type metadata. Behavior is unchanged.
@jwils
jwils force-pushed the joshuaw/indexing-field-metadata branch from 198b65f to 46ad2bf Compare September 12, 2026 22:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant