Module: ElasticGraph::JSONIngestion::SchemaDefinition::APIExtension

Defined in:
elasticgraph-json_ingestion/lib/elastic_graph/json_ingestion/schema_definition/api_extension.rb

Overview

Module designed to be extended onto an SchemaDefinition::API instance to add JSON Schema ingestion serializer capabilities.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(api) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Wires up the JSON ingestion extensions when this module is extended onto an API instance.

Parameters:



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'elasticgraph-json_ingestion/lib/elastic_graph/json_ingestion/schema_definition/api_extension.rb', line 27

def self.extended(api)
  state = api.state.extend(StateExtension) # : ElasticGraph::SchemaDefinition::State & StateExtension
  state.reserved_type_names << EVENT_ENVELOPE_JSON_SCHEMA_NAME
  api.factory.extend(FactoryExtension)

  api.on_built_in_types do |type|
    if type.name == api.state.type_ref("GeoLocation").to_final_form.name
      # @type var geo_location_type: ElasticGraph::SchemaDefinition::SchemaElements::TypeWithSubfields & SchemaElements::TypeWithSubfieldsExtension
      geo_location_type = _ = type
      names = api.state.schema_elements

      # We use `nullable: false` because `GeoLocation` is indexed as a single `geo_point` field,
      # and therefore can't support a `latitude` without a `longitude` or vice-versa.
      latitude = geo_location_type.graphql_fields_by_name.fetch(names.latitude) # : ElasticGraph::SchemaDefinition::SchemaElements::Field & SchemaElements::FieldExtension
      longitude = geo_location_type.graphql_fields_by_name.fetch(names.longitude) # : ElasticGraph::SchemaDefinition::SchemaElements::Field & SchemaElements::FieldExtension
      latitude.json_schema minimum: -90, maximum: 90, nullable: false
      longitude.json_schema minimum: -180, maximum: 180, nullable: false
    end
  end
end

Instance Method Details

#enforce_json_schema_version(value) ⇒ void

Note:

Generally speaking, you will want this to be true for any ElasticGraph application that is in production as the versioning of JSON schemas is what supports safe schema evolution as it allows ElasticGraph to identify which version of the JSON schema the publishing system was operating on when it published an event.

It can be useful to set it to false before your application is in production, as you do not want to be forced to bump the version after every single schema change while you are building an initial prototype.

This method returns an undefined value.

Configures whether JSON schema artifact dumping enforces the requirement that the JSON schema version is incremented every time dumping the JSON schemas results in a changed artifact. Defaults to true.

Examples:

Disable enforcement during initial prototyping

ElasticGraph.define_schema do |schema|
  # TODO: remove this once we're past the prototyping stage
  schema.enforce_json_schema_version false
end

Parameters:

  • value (Boolean)

    whether to require json_schema_version to be incremented on changes that impact json_schemas.yaml

See Also:



102
103
104
105
106
107
108
109
# File 'elasticgraph-json_ingestion/lib/elastic_graph/json_ingestion/schema_definition/api_extension.rb', line 102

def enforce_json_schema_version(value)
  unless value == true || value == false
    raise Errors::SchemaError, "`enforce_json_schema_version` must be a boolean. Specified value: #{value.inspect}"
  end

  json_ingestion_state.enforce_json_schema_version = value
  nil
end

#json_schema_strictness(allow_omitted_fields: false, allow_extra_fields: true) ⇒ void

Note:

If you allow both omitted fields and extra fields, ElasticGraph's JSON schema validation will allow (and ignore) misspelled field names in indexing events. For example, if the ElasticGraph schema has a nullable field named parentId but the publisher accidentally provides it as parent_id, ElasticGraph would happily ignore the parent_id field entirely, because parentId is allowed to be omitted and parent_id would be treated as an extra field. Therefore, we recommend that you only set one of these to true (or none).

This method returns an undefined value.

Defines strictness of the JSON schema validation. By default, the JSON schema will require all fields to be provided by the publisher (but they can be nullable) and will ignore extra fields that are not defined in the schema. Use this method to configure this behavior.

Examples:

Allow omitted fields and disallow extra fields

ElasticGraph.define_schema do |schema|
  schema.json_schema_strictness allow_omitted_fields: true, allow_extra_fields: false
end

Parameters:

  • allow_omitted_fields (bool) (defaults to: false)

    Whether nullable fields can be omitted from indexing events.

  • allow_extra_fields (bool) (defaults to: true)

    Whether extra fields (e.g. beyond fields defined in the schema) can be included in indexing events.



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'elasticgraph-json_ingestion/lib/elastic_graph/json_ingestion/schema_definition/api_extension.rb', line 129

def json_schema_strictness(allow_omitted_fields: false, allow_extra_fields: true)
  state = json_ingestion_state

  unless [true, false].include?(allow_omitted_fields)
    raise Errors::SchemaError, "`allow_omitted_fields` must be true or false"
  end

  unless [true, false].include?(allow_extra_fields)
    raise Errors::SchemaError, "`allow_extra_fields` must be true or false"
  end

  state.allow_omitted_json_schema_fields = allow_omitted_fields
  state.allow_extra_json_schema_fields = allow_extra_fields
  nil
end

#json_schema_version(version) ⇒ void

Note:

While this is an important part of how ElasticGraph is designed to support schema evolution, it can be annoying constantly have to increment this while rapidly changing the schema during prototyping. You can disable the requirement to increment this on every JSON schema change with #enforce_json_schema_version.

This method returns an undefined value.

Defines the version number of the current JSON schema. Importantly, every time a change is made that impacts the JSON schema artifact, the version number must be incremented to ensure that each different version of the JSON schema is identified by a unique version number. The publisher will then include this version number in published events to identify the version of the schema it was using. This avoids the need to deploy the publisher and ElasticGraph indexer at the same time to keep them in sync.

Examples:

Set the JSON schema version to 1

ElasticGraph.define_schema do |schema|
  schema.json_schema_version 1
end

Parameters:

  • version (Integer)

    current version number of the JSON schema artifact

See Also:



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'elasticgraph-json_ingestion/lib/elastic_graph/json_ingestion/schema_definition/api_extension.rb', line 65

def json_schema_version(version)
  state = json_ingestion_state

  if !version.is_a?(Integer) || version < 1
    raise Errors::SchemaError, "`json_schema_version` must be a positive integer. Specified version: #{version}"
  end

  if state.json_schema_version
    raise Errors::SchemaError, "`json_schema_version` can only be set once on a schema. Previously-set version: #{state.json_schema_version}"
  end

  state.json_schema_version = version
  state.json_schema_version_setter_location = caller_locations(1, 1).to_a.first
  nil
end