Class: ElasticGraph::SchemaArtifacts::FromDisk

Inherits:
Object
  • Object
show all
Includes:
ArtifactsHelperMethods
Defined in:
elasticgraph-schema_artifacts/lib/elastic_graph/schema_artifacts/from_disk.rb

Overview

Responsible for loading schema artifacts from disk and providing access to each artifact.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ArtifactsHelperMethods

#datastore_scripts, #index_mappings_by_index_def_name, #index_templates, #indices

Constructor Details

#initialize(artifacts_dir) ⇒ void

Builds an instance using the given artifacts directory.

Parameters:

  • artifacts_dir (String)

    directory from which the schema artifacts are loaded



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'elasticgraph-schema_artifacts/lib/elastic_graph/schema_artifacts/from_disk.rb', line 51

class FromDisk < Support::MemoizableData.define(:artifacts_dir)
  include ArtifactsHelperMethods

  # Provides the GraphQL SDL schema string. This defines the contract between an ElasticGraph project and its GraphQL clients,
  # and can be freely given to GraphQL clients for code generation or query validation purposes.
  #
  # In addition, it is used by `elasticgraph-graphql` to power an ElasticGraph GraphQL endpoint.
  #
  # @return [String]
  # @raise [Errors::MissingSchemaArtifactError] when the `graphql.schema` file does not exist in the `artifacts_dir`.
  #
  # @example Print the GraphQL schema string
  #   artifacts = ElasticGraph::SchemaArtifacts::FromDisk.new(schema_artifacts_dir)
  #   puts artifacts.graphql_schema_string
  #
  def graphql_schema_string
    @graphql_schema_string ||= read_artifact(GRAPHQL_SCHEMA_FILE)
  end

  # Provides the JSON schemas of all types at a specific version. The JSON schemas define the contract between
  # data publishers and an ElasticGraph project, and can be freely given to data publishers for code generation
  # or query validation purposes.
  #
  # In addition, they are used by `elasticgraph-indexer` to validate data before indexing it.
  #
  # @note ElasticGraph supports multiple JSON schema versions in order to support safe, seamless schema evolution.
  #   Each event will be validated using the version specified in the event itself, allowing data publishers to be
  #   updated to the latest JSON schema at a later time after `elasticgraph-indexer` is deployed with a new JSON
  #   schema version.
  #
  # @param version [Integer] the desired JSON schema version
  # @return [Hash<String, Object>]
  # @raise [Errors::MissingSchemaArtifactError] when the provided version does not exist within the `artifacts_dir`.
  # @see #available_json_schema_versions
  # @see #latest_json_schema_version
  #
  # @example Get the JSON schema for a `Widget` type at version 1
  #   artifacts = ElasticGraph::SchemaArtifacts::FromDisk.new(schema_artifacts_dir)
  #   widget_v1_json_schema = artifacts.json_schemas_for(1).fetch("$defs").fetch("Widget")
  def json_schemas_for(version)
    unless available_json_schema_versions.include?(version)
      raise Errors::MissingSchemaArtifactError, "The requested json schema version (#{version}) is not available. " \
        "Available versions: #{available_json_schema_versions.sort.join(", ")}."
    end

    json_schemas_by_version[version] # : ::Hash[::String, untyped]
  end

  # Provides the set of available JSON schema versions.
  #
  # @return [Set<Integer>]
  # @see #json_schemas_for
  # @see #latest_json_schema_version
  #
  # @example Print the list of available JSON schema versions
  #   artifacts = ElasticGraph::SchemaArtifacts::FromDisk.new(schema_artifacts_dir)
  #   puts artifacts.available_json_schema_versions.sort.join(", ")
  def available_json_schema_versions
    @available_json_schema_versions ||= begin
      versioned_json_schemas_dir = ::File.join(artifacts_dir, JSON_SCHEMAS_BY_VERSION_DIRECTORY)
      if ::Dir.exist?(versioned_json_schemas_dir)
        ::Dir.entries(versioned_json_schemas_dir).filter_map { |it| it[/v(\d+)\.yaml/, 1]&.to_i }.to_set
      else
        ::Set.new
      end
    end
  end

  # Provides the latest JSON schema version.
  #
  # @return [Integer]
  # @raise [Errors::MissingSchemaArtifactError] when no JSON schemas files exist within the `artifacts_dir`.
  # @see #available_json_schema_versions
  # @see #json_schemas_for
  #
  # @example Print the latest JSON schema version
  #   artifacts = ElasticGraph::SchemaArtifacts::FromDisk.new(schema_artifacts_dir)
  #   puts artifacts.latest_json_schema_version
  def latest_json_schema_version
    @latest_json_schema_version ||= available_json_schema_versions.max || raise(
      Errors::MissingSchemaArtifactError,
      "The directory for versioned JSON schemas (#{::File.join(artifacts_dir, JSON_SCHEMAS_BY_VERSION_DIRECTORY)}) could not be found. " \
      "Either the schema artifacts haven't been dumped yet or the schema artifacts directory (#{artifacts_dir}) is misconfigured."
    )
  end

  # Provides the datastore configuration. The datastore configuration defines the full configuration--including indices, templates,
  # and scripts--required in the datastore (Elasticsearch or OpenSearch) by ElasticGraph for the current schema.
  #
  # `elasticgraph-admin` uses this artifact to administer the datastore.
  #
  # @return [Hash<String, Object>]
  # @raise [Errors::MissingSchemaArtifactError] when `datastore_config.yaml` does not exist within the `artifacts_dir`.
  #
  # @example Print the current list of indices
  #   artifacts = ElasticGraph::SchemaArtifacts::FromDisk.new(schema_artifacts_dir)
  #   puts artifacts.datastore_config.fetch("indices").keys.sort.join(", ")
  def datastore_config
    @datastore_config ||= _ = parsed_yaml_from(DATASTORE_CONFIG_FILE)
  end

  # Provides the runtime metadata. This runtime metadata is used at runtime by `elasticgraph-graphql` and `elasticgraph-indexer`.
  #
  # @return [RuntimeMetadata::Schema]
  def 
    @runtime_metadata ||= RuntimeMetadata::Schema.from_hash(parsed_yaml_from(RUNTIME_METADATA_FILE))
  end

  private

  def read_artifact(artifact_name)
    file_name = ::File.join(artifacts_dir, artifact_name)

    if ::File.exist?(file_name)
      ::File.read(file_name)
    else
      raise Errors::MissingSchemaArtifactError, "Schema artifact `#{artifact_name}` could not be found. " \
        "Either the schema artifacts haven't been dumped yet or the schema artifacts directory (#{artifacts_dir}) is misconfigured."
    end
  end

  def parsed_yaml_from(artifact_name)
    ::YAML.safe_load(read_artifact(artifact_name))
  end

  def json_schemas_by_version
    @json_schemas_by_version ||= ::Hash.new do |hash, json_schema_version|
      hash[json_schema_version] = load_json_schema(json_schema_version)
    end
  end

  # Loads the given JSON schema version from disk.
  def load_json_schema(json_schema_version)
    parsed_yaml_from(::File.join(JSON_SCHEMAS_BY_VERSION_DIRECTORY, "v#{json_schema_version}.yaml"))
  end
end

Instance Attribute Details

#artifacts_dirString (readonly)

Returns directory from which the schema artifacts are loaded.

Returns:

  • (String)

    directory from which the schema artifacts are loaded



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'elasticgraph-schema_artifacts/lib/elastic_graph/schema_artifacts/from_disk.rb', line 51

class FromDisk < Support::MemoizableData.define(:artifacts_dir)
  include ArtifactsHelperMethods

  # Provides the GraphQL SDL schema string. This defines the contract between an ElasticGraph project and its GraphQL clients,
  # and can be freely given to GraphQL clients for code generation or query validation purposes.
  #
  # In addition, it is used by `elasticgraph-graphql` to power an ElasticGraph GraphQL endpoint.
  #
  # @return [String]
  # @raise [Errors::MissingSchemaArtifactError] when the `graphql.schema` file does not exist in the `artifacts_dir`.
  #
  # @example Print the GraphQL schema string
  #   artifacts = ElasticGraph::SchemaArtifacts::FromDisk.new(schema_artifacts_dir)
  #   puts artifacts.graphql_schema_string
  #
  def graphql_schema_string
    @graphql_schema_string ||= read_artifact(GRAPHQL_SCHEMA_FILE)
  end

  # Provides the JSON schemas of all types at a specific version. The JSON schemas define the contract between
  # data publishers and an ElasticGraph project, and can be freely given to data publishers for code generation
  # or query validation purposes.
  #
  # In addition, they are used by `elasticgraph-indexer` to validate data before indexing it.
  #
  # @note ElasticGraph supports multiple JSON schema versions in order to support safe, seamless schema evolution.
  #   Each event will be validated using the version specified in the event itself, allowing data publishers to be
  #   updated to the latest JSON schema at a later time after `elasticgraph-indexer` is deployed with a new JSON
  #   schema version.
  #
  # @param version [Integer] the desired JSON schema version
  # @return [Hash<String, Object>]
  # @raise [Errors::MissingSchemaArtifactError] when the provided version does not exist within the `artifacts_dir`.
  # @see #available_json_schema_versions
  # @see #latest_json_schema_version
  #
  # @example Get the JSON schema for a `Widget` type at version 1
  #   artifacts = ElasticGraph::SchemaArtifacts::FromDisk.new(schema_artifacts_dir)
  #   widget_v1_json_schema = artifacts.json_schemas_for(1).fetch("$defs").fetch("Widget")
  def json_schemas_for(version)
    unless available_json_schema_versions.include?(version)
      raise Errors::MissingSchemaArtifactError, "The requested json schema version (#{version}) is not available. " \
        "Available versions: #{available_json_schema_versions.sort.join(", ")}."
    end

    json_schemas_by_version[version] # : ::Hash[::String, untyped]
  end

  # Provides the set of available JSON schema versions.
  #
  # @return [Set<Integer>]
  # @see #json_schemas_for
  # @see #latest_json_schema_version
  #
  # @example Print the list of available JSON schema versions
  #   artifacts = ElasticGraph::SchemaArtifacts::FromDisk.new(schema_artifacts_dir)
  #   puts artifacts.available_json_schema_versions.sort.join(", ")
  def available_json_schema_versions
    @available_json_schema_versions ||= begin
      versioned_json_schemas_dir = ::File.join(artifacts_dir, JSON_SCHEMAS_BY_VERSION_DIRECTORY)
      if ::Dir.exist?(versioned_json_schemas_dir)
        ::Dir.entries(versioned_json_schemas_dir).filter_map { |it| it[/v(\d+)\.yaml/, 1]&.to_i }.to_set
      else
        ::Set.new
      end
    end
  end

  # Provides the latest JSON schema version.
  #
  # @return [Integer]
  # @raise [Errors::MissingSchemaArtifactError] when no JSON schemas files exist within the `artifacts_dir`.
  # @see #available_json_schema_versions
  # @see #json_schemas_for
  #
  # @example Print the latest JSON schema version
  #   artifacts = ElasticGraph::SchemaArtifacts::FromDisk.new(schema_artifacts_dir)
  #   puts artifacts.latest_json_schema_version
  def latest_json_schema_version
    @latest_json_schema_version ||= available_json_schema_versions.max || raise(
      Errors::MissingSchemaArtifactError,
      "The directory for versioned JSON schemas (#{::File.join(artifacts_dir, JSON_SCHEMAS_BY_VERSION_DIRECTORY)}) could not be found. " \
      "Either the schema artifacts haven't been dumped yet or the schema artifacts directory (#{artifacts_dir}) is misconfigured."
    )
  end

  # Provides the datastore configuration. The datastore configuration defines the full configuration--including indices, templates,
  # and scripts--required in the datastore (Elasticsearch or OpenSearch) by ElasticGraph for the current schema.
  #
  # `elasticgraph-admin` uses this artifact to administer the datastore.
  #
  # @return [Hash<String, Object>]
  # @raise [Errors::MissingSchemaArtifactError] when `datastore_config.yaml` does not exist within the `artifacts_dir`.
  #
  # @example Print the current list of indices
  #   artifacts = ElasticGraph::SchemaArtifacts::FromDisk.new(schema_artifacts_dir)
  #   puts artifacts.datastore_config.fetch("indices").keys.sort.join(", ")
  def datastore_config
    @datastore_config ||= _ = parsed_yaml_from(DATASTORE_CONFIG_FILE)
  end

  # Provides the runtime metadata. This runtime metadata is used at runtime by `elasticgraph-graphql` and `elasticgraph-indexer`.
  #
  # @return [RuntimeMetadata::Schema]
  def 
    @runtime_metadata ||= RuntimeMetadata::Schema.from_hash(parsed_yaml_from(RUNTIME_METADATA_FILE))
  end

  private

  def read_artifact(artifact_name)
    file_name = ::File.join(artifacts_dir, artifact_name)

    if ::File.exist?(file_name)
      ::File.read(file_name)
    else
      raise Errors::MissingSchemaArtifactError, "Schema artifact `#{artifact_name}` could not be found. " \
        "Either the schema artifacts haven't been dumped yet or the schema artifacts directory (#{artifacts_dir}) is misconfigured."
    end
  end

  def parsed_yaml_from(artifact_name)
    ::YAML.safe_load(read_artifact(artifact_name))
  end

  def json_schemas_by_version
    @json_schemas_by_version ||= ::Hash.new do |hash, json_schema_version|
      hash[json_schema_version] = load_json_schema(json_schema_version)
    end
  end

  # Loads the given JSON schema version from disk.
  def load_json_schema(json_schema_version)
    parsed_yaml_from(::File.join(JSON_SCHEMAS_BY_VERSION_DIRECTORY, "v#{json_schema_version}.yaml"))
  end
end

Instance Method Details

#available_json_schema_versionsSet<Integer>

Provides the set of available JSON schema versions.

Examples:

Print the list of available JSON schema versions

artifacts = ElasticGraph::SchemaArtifacts::FromDisk.new(schema_artifacts_dir)
puts artifacts.available_json_schema_versions.sort.join(", ")

Returns:

  • (Set<Integer>)

See Also:



108
109
110
111
112
113
114
115
116
117
# File 'elasticgraph-schema_artifacts/lib/elastic_graph/schema_artifacts/from_disk.rb', line 108

def available_json_schema_versions
  @available_json_schema_versions ||= begin
    versioned_json_schemas_dir = ::File.join(artifacts_dir, JSON_SCHEMAS_BY_VERSION_DIRECTORY)
    if ::Dir.exist?(versioned_json_schemas_dir)
      ::Dir.entries(versioned_json_schemas_dir).filter_map { |it| it[/v(\d+)\.yaml/, 1]&.to_i }.to_set
    else
      ::Set.new
    end
  end
end

#datastore_configHash<String, Object>

Provides the datastore configuration. The datastore configuration defines the full configuration–including indices, templates, and scripts–required in the datastore (Elasticsearch or OpenSearch) by ElasticGraph for the current schema.

elasticgraph-admin uses this artifact to administer the datastore.

Examples:

Print the current list of indices

artifacts = ElasticGraph::SchemaArtifacts::FromDisk.new(schema_artifacts_dir)
puts artifacts.datastore_config.fetch("indices").keys.sort.join(", ")

Returns:

  • (Hash<String, Object>)

Raises:

  • (Errors::MissingSchemaArtifactError)

    when datastore_config.yaml does not exist within the artifacts_dir.



148
149
150
# File 'elasticgraph-schema_artifacts/lib/elastic_graph/schema_artifacts/from_disk.rb', line 148

def datastore_config
  @datastore_config ||= _ = parsed_yaml_from(DATASTORE_CONFIG_FILE)
end

#graphql_schema_stringString

Provides the GraphQL SDL schema string. This defines the contract between an ElasticGraph project and its GraphQL clients, and can be freely given to GraphQL clients for code generation or query validation purposes.

In addition, it is used by elasticgraph-graphql to power an ElasticGraph GraphQL endpoint.

Examples:

Print the GraphQL schema string

artifacts = ElasticGraph::SchemaArtifacts::FromDisk.new(schema_artifacts_dir)
puts artifacts.graphql_schema_string

Returns:

  • (String)

Raises:

  • (Errors::MissingSchemaArtifactError)

    when the graphql.schema file does not exist in the artifacts_dir.



66
67
68
# File 'elasticgraph-schema_artifacts/lib/elastic_graph/schema_artifacts/from_disk.rb', line 66

def graphql_schema_string
  @graphql_schema_string ||= read_artifact(GRAPHQL_SCHEMA_FILE)
end

#json_schemas_for(version) ⇒ Hash<String, Object>

Note:

ElasticGraph supports multiple JSON schema versions in order to support safe, seamless schema evolution. Each event will be validated using the version specified in the event itself, allowing data publishers to be updated to the latest JSON schema at a later time after elasticgraph-indexer is deployed with a new JSON schema version.

Provides the JSON schemas of all types at a specific version. The JSON schemas define the contract between data publishers and an ElasticGraph project, and can be freely given to data publishers for code generation or query validation purposes.

In addition, they are used by elasticgraph-indexer to validate data before indexing it.

Examples:

Get the JSON schema for a Widget type at version 1

artifacts = ElasticGraph::SchemaArtifacts::FromDisk.new(schema_artifacts_dir)
widget_v1_json_schema = artifacts.json_schemas_for(1).fetch("$defs").fetch("Widget")

Parameters:

  • version (Integer)

    the desired JSON schema version

Returns:

  • (Hash<String, Object>)

Raises:

  • (Errors::MissingSchemaArtifactError)

    when the provided version does not exist within the artifacts_dir.

See Also:



90
91
92
93
94
95
96
97
# File 'elasticgraph-schema_artifacts/lib/elastic_graph/schema_artifacts/from_disk.rb', line 90

def json_schemas_for(version)
  unless available_json_schema_versions.include?(version)
    raise Errors::MissingSchemaArtifactError, "The requested json schema version (#{version}) is not available. " \
      "Available versions: #{available_json_schema_versions.sort.join(", ")}."
  end

  json_schemas_by_version[version] # : ::Hash[::String, untyped]
end

#latest_json_schema_versionInteger

Provides the latest JSON schema version.

Examples:

Print the latest JSON schema version

artifacts = ElasticGraph::SchemaArtifacts::FromDisk.new(schema_artifacts_dir)
puts artifacts.latest_json_schema_version

Returns:

  • (Integer)

Raises:

  • (Errors::MissingSchemaArtifactError)

    when no JSON schemas files exist within the artifacts_dir.

See Also:



129
130
131
132
133
134
135
# File 'elasticgraph-schema_artifacts/lib/elastic_graph/schema_artifacts/from_disk.rb', line 129

def latest_json_schema_version
  @latest_json_schema_version ||= available_json_schema_versions.max || raise(
    Errors::MissingSchemaArtifactError,
    "The directory for versioned JSON schemas (#{::File.join(artifacts_dir, JSON_SCHEMAS_BY_VERSION_DIRECTORY)}) could not be found. " \
    "Either the schema artifacts haven't been dumped yet or the schema artifacts directory (#{artifacts_dir}) is misconfigured."
  )
end

#runtime_metadataRuntimeMetadata::Schema

Provides the runtime metadata. This runtime metadata is used at runtime by elasticgraph-graphql and elasticgraph-indexer.



155
156
157
# File 'elasticgraph-schema_artifacts/lib/elastic_graph/schema_artifacts/from_disk.rb', line 155

def 
  @runtime_metadata ||= RuntimeMetadata::Schema.from_hash(parsed_yaml_from(RUNTIME_METADATA_FILE))
end