Class: ElasticGraph::SchemaDefinition::SchemaArtifactManager

Inherits:
Object
  • Object
show all
Defined in:
lib/elastic_graph/schema_definition/schema_artifact_manager.rb

Overview

Manages schema artifacts. Note: not tested directly. Instead, the ‘RakeTasks` tests drive this class.

Note that we use ‘abort` instead of `raise` here for exceptions that require the user to perform an action to resolve. The output from `abort` is cleaner (no stack trace, etc) which improves the signal-to-noise ratio for the user to (hopefully) make it easier to understand what to do, without needing to wade through extra output.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(schema_definition_results:, schema_artifacts_directory:, enforce_json_schema_version:, output:, max_diff_lines: 50) ⇒ SchemaArtifactManager

Returns a new instance of SchemaArtifactManager.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/elastic_graph/schema_definition/schema_artifact_manager.rb', line 33

def initialize(schema_definition_results:, schema_artifacts_directory:, enforce_json_schema_version:, output:, max_diff_lines: 50)
  @schema_definition_results = schema_definition_results
  @schema_artifacts_directory = schema_artifacts_directory
  @enforce_json_schema_version = enforce_json_schema_version
  @output = output
  @max_diff_lines = max_diff_lines

  @json_schemas_artifact = new_yaml_artifact(
    JSON_SCHEMAS_FILE,
    JSONSchemaPruner.prune(schema_definition_results.current_public_json_schema),
    extra_comment_lines: [
      "This is the \"public\" JSON schema file and is intended to be provided to publishers so that",
      "they can perform code generation and event validation."
    ]
  )

  # Here we round-trip the SDL string through the GraphQL gem's formatting logic. This provides
  # nice, consistent formatting (alphabetical order, consistent spacing, etc) and also prunes out
  # any "orphaned" schema types (that is, types that are defined but never referenced).
  # We also prepend a line break so there's a blank line between the comment block and the
  # schema elements.
  graphql_schema = ::GraphQL::Schema.from_definition(schema_definition_results.graphql_schema_string).to_definition.chomp

  unversioned_artifacts = [
    new_yaml_artifact(DATASTORE_CONFIG_FILE, schema_definition_results.datastore_config),
    new_yaml_artifact(RUNTIME_METADATA_FILE, (graphql_schema).to_dumpable_hash),
    @json_schemas_artifact,
    new_raw_artifact(GRAPHQL_SCHEMA_FILE, "\n" + graphql_schema)
  ]

  versioned_artifacts = build_desired_versioned_json_schemas(@json_schemas_artifact.desired_contents).values.map do |versioned_schema|
    new_versioned_json_schema_artifact(versioned_schema)
  end

  @artifacts = (unversioned_artifacts + versioned_artifacts).sort_by(&:file_name)
  notify_about_unused_type_name_overrides
  notify_about_unused_enum_value_overrides
end

Instance Attribute Details

#schema_definition_resultsObject (readonly)

Returns the value of attribute schema_definition_results.



31
32
33
# File 'lib/elastic_graph/schema_definition/schema_artifact_manager.rb', line 31

def schema_definition_results
  @schema_definition_results
end

Instance Method Details

#check_artifactsObject

Checks that all schema artifacts are up-to-date, raising an exception if not.



101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/elastic_graph/schema_definition/schema_artifact_manager.rb', line 101

def check_artifacts
  out_of_date_artifacts = @artifacts.select(&:out_of_date?)

  if out_of_date_artifacts.empty?
    descriptions = @artifacts.map.with_index(1) { |art, i| "#{i}. #{art.file_name}" }
    @output.puts <<~EOS
      Your schema artifacts are all up to date:
      #{descriptions.join("\n")}

    EOS
  else
    abort artifacts_out_of_date_error(out_of_date_artifacts)
  end
end

#dump_artifactsObject

Dumps all the schema artifacts to disk.



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
# File 'lib/elastic_graph/schema_definition/schema_artifact_manager.rb', line 73

def dump_artifacts
  check_if_needs_json_schema_version_bump do |recommended_json_schema_version|
    if @enforce_json_schema_version
      # @type var setter_location: ::Thread::Backtrace::Location
      # We use `_ =` because while `json_schema_version_setter_location` can be nil,
      # it'll never be nil if we get here and we want the type to be non-nilable.
      setter_location = _ = schema_definition_results.json_schema_version_setter_location
      setter_location_path = ::Pathname.new(setter_location.absolute_path.to_s).relative_path_from(::Dir.pwd)

      abort "A change has been attempted to `json_schemas.yaml`, but the `json_schema_version` has not been correspondingly incremented. Please " \
        "increase the schema's version, and then run the `schema_artifacts:dump` command again.\n\n" \
        "To update the schema version to the expected version, change line #{setter_location.lineno} at `#{setter_location_path}` to:\n" \
        "  `schema.json_schema_version #{recommended_json_schema_version}`\n\n" \
        "Alternately, pass `enforce_json_schema_version: false` to `ElasticGraph::SchemaDefinition::RakeTasks.new` to allow the JSON schemas " \
        "file to change without requiring a version bump, but that is only recommended for non-production applications during initial schema prototyping."
    else
      @output.puts <<~EOS
        WARNING: the `json_schemas.yaml` artifact is being updated without the `json_schema_version` being correspondingly incremented.
        This is not recommended for production applications, but is currently allowed because you have set `enforce_json_schema_version: false`.
      EOS
    end
  end

  ::FileUtils.mkdir_p(@schema_artifacts_directory)
  @artifacts.each { |artifact| artifact.dump(@output) }
end