Generalize indexing schema versions - #1284
Conversation
690e775 to
ec0cb6b
Compare
ec0cb6b to
ab31afa
Compare
ab31afa to
609617b
Compare
609617b to
22bce59
Compare
09425ae to
f90f1aa
Compare
|
Pushed d3ff605, which changes the design in one substantive way and fixes five defects. I rewrote the PR description to match. Summary of the delta for anyone who already reviewed:
The breaking changes are gone. The earlier revision broke three things that I had not called out:
All three now accept the legacy name, and the logs emit both the new key and the deprecated alias. Defects fixed. The README and the decoder interface both promised a default to the latest version that the earlier revision had removed; the behaviour is back and both texts are now format neutral. This PR had also added a duplicate decoder section to the JSON gem README that named a class which does not exist. The indexer extension memoized into a name its own One limitation stays open. |
The pipeline now treats `schema_version` as optional, so an ingestion format with no versions (such as protobuf) can omit it. Each ingestion adapter decides what a missing version means. The JSON adapter uses the latest available JSON schema version, and still validates the event against that version, so a malformed event still fails. This removes the breaking changes the previous revision introduced: - `Converters.upsert_event_for` accepts `__schema_version`, the legacy `__json_schema_version`, or neither. An existing generated project keeps working with no edit to `shared_factories.rb`. - The JSON adapter claims and reads the legacy `json_schema_version` envelope key, so a direct caller of `Indexer#processor.process` needs no edit. - The latency log and the warehouse dump log emit `schema_version` and also the deprecated alias `json_schema_version`, so existing dashboards keep working. - The version selection log keeps its JSON-specific field names to match its JSON-specific message type `ElasticGraphMissingJSONSchemaVersion`. It also fixes four defects found in review: - `elasticgraph-indexer/README.md` and `indexing_event_decoder.rb` promised a default to the latest version that the code no longer had. Both texts are now format neutral, and the JSON gem documents its own behaviour. - A duplicate "Indexing Event Decoder" section in the JSON gem README named a class that does not exist. Removed. - `IndexerExtension#ingestion_adapters` memoized into the shared name `@ingestion_adapters` while calling `super`, which assigned the same name. - `select_schema_version` sorted the available versions on every event. The warehouse dumper uses the fixed S3 key segment `unversioned` in place of `v<version>` for a version-less format, so the segment count stays the same.
d3ff605 to
986f6cb
Compare
Why
The indexing pipeline spoke in
json_schema_version. That key is specific to one ingestion format. A proto ingestion format has no JSON schemas, so it cannot supply that value.This PR makes the shared pipeline speak in a format-neutral
schema_version. Each ingestion format maps its own versioning concept onto that key. The key is also optional, so a format with no versions at all can omit it.What
SCHEMA_VERSION_KEY = "schema_version"and use it inelasticgraph-indexer,elasticgraph-warehouse_lambda, and the shared test support.JSONIngestion::IngestionAdapterrestores thejson_schema_versionkey before it validates an event against the JSON schemas, so the artifacts stay unchanged. That patch is private to the JSON gem, soelasticgraph-schema_artifactsgains no new public API and keeps no knowledge of the generic key.JSONIngestion::IndexingEventDecodermaps the publisher'sjson_schema_versionontoschema_versionwhile it decodes JSON Lines.JSONIngestion::IngestionAdapterdispatches on the presence of a schema version and selects the closest available JSON schema version.The schema version is optional
schema_versionis optional at every stage of the pipeline. An ingestion format with no versions, such as the planned proto runtime, omits it. Each adapter decides what a missing version means for its own format.The JSON adapter uses the latest available JSON schema version. It still validates the event against that version, so a malformed event still fails, and it fails with a JSON schema message rather than a missing-version message.
The core indexer no longer requires the key either:
Processorreads the version for its latency log instead of fetching it.WarehouseDumpergroups by an optional version, and writes the fixed S3 key segmentunversionedin place ofv<version>. The segment count stays the same, so a reader that splits the key keeps working.Backward compatibility
Publishers keep sending
json_schema_version. The JSON schema artifacts keep thejson_schema_versionconst. This PR adds no breaking change:JSONIngestion::IngestionAdapterclaims and reads the legacyjson_schema_versionenvelope key. A publisher, or an in-process caller ofIndexer#processor.process, needs no edit.Indexer::TestSupport::Converters.upsert_event_foraccepts__schema_version, the legacy__json_schema_version, or neither. A project generated before this change keeps working with no edit to itsshared_factories.rb.ElasticGraphIndexingLatencieslog and theDumpedToWarehouseFilelog emitschema_versionand also the deprecated aliasjson_schema_version. An existing dashboard or monitor keeps working.ElasticGraphMissingJSONSchemaVersionlog keeps its JSON-specific field namesrequested_json_schema_versionandselected_json_schema_version, which match its JSON-specific message type.Review fixes
Self review of the stack found five defects, all fixed here:
elasticgraph-indexer/README.mdandIndexer::IndexingEventDecoder::Interfacepromised that a missing version selects the latest available version. An earlier revision of this PR had removed that behaviour, which made both texts wrong. The behaviour is back, and both texts are now format neutral: the core indexer states that the key is optional, and the JSON gem documents what it does with a missing version.elasticgraph-json_ingestion/README.md. It duplicated the section from Add configurable indexing event decoder #1220 and named a class that does not exist,ElasticGraph::JSONIngestion::IndexingEventDecoder::JSONLines. Removed.JSONIngestion::IndexerExtension#ingestion_adaptersmemoized into@ingestion_adapterswhile it calledsuper, which assigned the same name. It now uses@json_ingestion_adapters, so a second format gem can copy the pattern safely.select_schema_versionsorted the available versions on every event. The adapter now sorts once and memoizes.Known limitation
handles_event?cannot tell one format from another. The JSON adapter claims an event that carries a schema version under either key. An event with no version reaches the sole available adapter through the existing fallback inOperation::Factory, which covers every single-format deployment.Two live formats need a real discriminator, because a version-less proto event and a version-less JSON event look the same. I plan to have each decoder stamp its format on the decoded event, and have each adapter dispatch on that stamp. That belongs in the PR that adds the proto runtime.
Verification
elasticgraph-indexer,elasticgraph-json_ingestion,elasticgraph-warehouse_lambda,elasticgraph-indexer_lambda,elasticgraph-localandelasticgraph-lambda_supportunit suites: 556 examples, 0 failuresscript/run_gem_specs elasticgraph-json_ingestion: 282 examples, 100% line and branch coveragescript/run_gem_specs elasticgraph-warehouse_lambda: 23 examples, 100% line and branch coveragescript/lint,script/spellcheck,script/type_check: all greenbundle exec rake schema_artifacts:check: artifacts up to dateStack
Current PR is marked with
->.