elasticgraph 0.19.0.0 → 0.19.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +8 -0
- data/exe/elasticgraph +11 -0
- data/lib/elastic_graph/cli.rb +106 -0
- data/lib/elastic_graph/project_template/.gitignore +5 -0
- data/lib/elastic_graph/project_template/.standard.yml.tt +8 -0
- data/lib/elastic_graph/project_template/Gemfile.tt +17 -0
- data/lib/elastic_graph/project_template/README.md.tt +176 -0
- data/lib/elastic_graph/project_template/Rakefile.tt +64 -0
- data/lib/elastic_graph/project_template/config/queries/example_client/FindArtist.graphql +24 -0
- data/lib/elastic_graph/project_template/config/queries/example_client/ListArtistAlbums.graphql +16 -0
- data/lib/elastic_graph/project_template/config/schema/artists.rb.tt +65 -0
- data/lib/elastic_graph/project_template/config/schema.rb.tt +21 -0
- data/lib/elastic_graph/project_template/config/settings/local.yaml.tt +36 -0
- data/lib/elastic_graph/project_template/lib/app_name/factories.rb +107 -0
- data/lib/elastic_graph/project_template/lib/app_name/fake_data_batch_generator.rb.tt +14 -0
- data/lib/elastic_graph/project_template/lib/app_name/shared_factories.rb +29 -0
- data/lib/elastic_graph/project_template/spec/project_spec.rb.tt +19 -0
- metadata +35 -100
- data/elasticgraph.gemspec +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2bc0f43e12d65d88384972b991179c77c5ec7856c86c85f151138e0af2d99f2f
|
4
|
+
data.tar.gz: f12ed7e628eba142a6299f5878a97d8d80de3068fbff13606fe6ffbc7e181acd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 276bb3d1e4e9aa8180c01031468d60115ec05567bfbc02d39fbd65e8777dec65f874a19f6e46a5bbeb20aca56d0855c66ba0dd1a989462804ba01cddf6ba81e5
|
7
|
+
data.tar.gz: c191d95111cf81157ef2777bea143d12a0f71aa095b9df0da9bccf27ede6b3f53f250e01bc1bf0d20ab911840dbe33534c9c5fb7557cc521f08496eb8bc2a49f
|
data/README.md
CHANGED
@@ -2,3 +2,11 @@
|
|
2
2
|
|
3
3
|
ElasticGraph meta-gem that pulls in all the core ElasticGraph gems. Intended for use when all
|
4
4
|
parts of ElasticGraph are used from the same deployed app.
|
5
|
+
|
6
|
+
## Getting Started
|
7
|
+
|
8
|
+
Run this command to bootstrap a new local project:
|
9
|
+
|
10
|
+
```bash
|
11
|
+
elasticgraph new my_app
|
12
|
+
```
|
data/exe/elasticgraph
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Copyright 2024 Block, Inc.
|
3
|
+
#
|
4
|
+
# Use of this source code is governed by an MIT-style
|
5
|
+
# license that can be found in the LICENSE file or at
|
6
|
+
# https://opensource.org/licenses/MIT.
|
7
|
+
#
|
8
|
+
# frozen_string_literal: true
|
9
|
+
|
10
|
+
require "elastic_graph/cli"
|
11
|
+
ElasticGraph::CLI.start(ARGV)
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# Copyright 2024 Block, Inc.
|
2
|
+
#
|
3
|
+
# Use of this source code is governed by an MIT-style
|
4
|
+
# license that can be found in the LICENSE file or at
|
5
|
+
# https://opensource.org/licenses/MIT.
|
6
|
+
#
|
7
|
+
# frozen_string_literal: true
|
8
|
+
|
9
|
+
require "bundler"
|
10
|
+
require "elastic_graph/version"
|
11
|
+
require "thor"
|
12
|
+
|
13
|
+
module ElasticGraph
|
14
|
+
class CLI < ::Thor
|
15
|
+
include ::Thor::Actions
|
16
|
+
|
17
|
+
# Tell Thor where our template files live
|
18
|
+
def self.source_root
|
19
|
+
::File.expand_path("project_template", __dir__)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.exit_on_failure?
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
VALID_DATASTORES = %w[elasticsearch opensearch]
|
27
|
+
|
28
|
+
option :datastore, desc: "elasticsearch or opensearch", type: :string, default: "opensearch"
|
29
|
+
desc "new APP_NAME", "Generate a new ElasticGraph project in APP_NAME."
|
30
|
+
def new(app_path)
|
31
|
+
new_app_path = ::File.join(::Dir.pwd, app_path)
|
32
|
+
app_name = ::File.basename(new_app_path)
|
33
|
+
|
34
|
+
unless app_name.match?(/\A[a-z_]+\z/)
|
35
|
+
raise ::Thor::Error, "App name must be in `snake_case` form but was not: `#{app_name}`."
|
36
|
+
end
|
37
|
+
|
38
|
+
unless VALID_DATASTORES.include?(options[:datastore])
|
39
|
+
raise ::Thor::Error, "Invalid datastore option: #{options[:datastore]}. Must be #{VALID_DATASTORES.join(" or ")}."
|
40
|
+
end
|
41
|
+
|
42
|
+
setup_env = SetupEnv.new(
|
43
|
+
app_name: app_name,
|
44
|
+
app_module: app_name.split("_").map(&:capitalize).join,
|
45
|
+
datastore: options.fetch(:datastore),
|
46
|
+
gemfile_elasticgraph_details_code_snippet: %(["#{VERSION}"])
|
47
|
+
)
|
48
|
+
|
49
|
+
say "Creating a new #{setup_env.datastore_name} ElasticGraph project called '#{app_name}' at: #{new_app_path}", :green
|
50
|
+
|
51
|
+
ElasticGraph.with_setup_env(setup_env) do
|
52
|
+
# Recursively copy all files from project_template into the new_app_path
|
53
|
+
directory ".", new_app_path, exclude_pattern: %r{/lib/app_name/}
|
54
|
+
directory "lib/app_name", ::File.join(new_app_path, "lib", app_name)
|
55
|
+
end
|
56
|
+
|
57
|
+
inside new_app_path do
|
58
|
+
::Bundler.with_unbundled_env do
|
59
|
+
run "bundle install"
|
60
|
+
run "bundle exec rake schema_artifacts:dump query_registry:dump_variables:all build"
|
61
|
+
end
|
62
|
+
|
63
|
+
run "git init"
|
64
|
+
run "git add ."
|
65
|
+
run "git commit -m 'Bootstrapped ElasticGraph with `elasticgraph new`.'"
|
66
|
+
end
|
67
|
+
|
68
|
+
say "Successfully bootstrapped '#{app_name}' as a new #{setup_env.datastore_name} ElasticGraph project.", :green
|
69
|
+
|
70
|
+
say <<~INSTRUCTIONS, :yellow
|
71
|
+
Next steps:
|
72
|
+
1. cd #{app_path}
|
73
|
+
2. Run `bundle exec rake boot_locally` to try it out in your browser.
|
74
|
+
3. Run `bundle exec rake -T` to view other available tasks.
|
75
|
+
4. Customize your new project as needed. (Search for `TODO` to find things that need updating.)
|
76
|
+
INSTRUCTIONS
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class SetupEnv < ::Data.define(:app_name, :app_module, :datastore, :gemfile_elasticgraph_details_code_snippet)
|
81
|
+
DATASTORE_NAMES = {"elasticsearch" => "Elasticsearch", "opensearch" => "OpenSearch"}
|
82
|
+
DATASTORE_UI_NAMES = {"elasticsearch" => "Kibana", "opensearch" => "OpenSearch Dashboards"}
|
83
|
+
|
84
|
+
def datastore_name
|
85
|
+
DATASTORE_NAMES.fetch(datastore)
|
86
|
+
end
|
87
|
+
|
88
|
+
def datastore_ui_name
|
89
|
+
DATASTORE_UI_NAMES.fetch(datastore)
|
90
|
+
end
|
91
|
+
|
92
|
+
def ruby_major_minor
|
93
|
+
"3.4"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
singleton_class.attr_reader :setup_env
|
98
|
+
|
99
|
+
def self.with_setup_env(setup_env)
|
100
|
+
original_setup_env = self.setup_env
|
101
|
+
@setup_env = setup_env
|
102
|
+
yield
|
103
|
+
ensure
|
104
|
+
@setup_env = original_setup_env
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
# Gem details for the elasticgraph gems.
|
4
|
+
elasticgraph_details = <%= ElasticGraph.setup_env.gemfile_elasticgraph_details_code_snippet %>
|
5
|
+
|
6
|
+
gem "elasticgraph-local", *elasticgraph_details
|
7
|
+
gem "elasticgraph-<%= ElasticGraph.setup_env.datastore %>", *elasticgraph_details
|
8
|
+
gem "elasticgraph-query_registry", *elasticgraph_details
|
9
|
+
|
10
|
+
gem "httpx", "~> 1.3"
|
11
|
+
|
12
|
+
group :development do
|
13
|
+
gem "factory_bot"
|
14
|
+
gem "faker"
|
15
|
+
gem "rspec"
|
16
|
+
gem "standard"
|
17
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
# <%= ElasticGraph.setup_env.app_module %> ElasticGraph Project
|
2
|
+
|
3
|
+
This repository contains the files for creating and maintaining the <%= ElasticGraph.setup_env.app_module %> ElasticGraph Project.
|
4
|
+
|
5
|
+
## Development Environment
|
6
|
+
|
7
|
+
Here's what you need:
|
8
|
+
|
9
|
+
| Requirement | Version | Installation Instructions |
|
10
|
+
|----------------|---------|---------------------------------------------------------------------------|
|
11
|
+
| Ruby | <%= ElasticGraph.setup_env.ruby_major_minor %>.x | [ruby-lang.org](https://www.ruby-lang.org/en/documentation/installation/) |
|
12
|
+
| Docker Engine | 27.x | [docker.com](https://docs.docker.com/engine/install/) |
|
13
|
+
| Docker Compose | 2.29.x | [docker.com](https://docs.docker.com/compose/install/) |
|
14
|
+
|
15
|
+
### Ruby
|
16
|
+
|
17
|
+
This project is written in Ruby, a dynamic, open source programming language with a focus on simplicity and productivity.
|
18
|
+
|
19
|
+
You may verify your `ruby` installation via the terminal:
|
20
|
+
|
21
|
+
```bash
|
22
|
+
$ ruby -v
|
23
|
+
ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [arm64-darwin24]
|
24
|
+
```
|
25
|
+
|
26
|
+
If you do not have Ruby, we recommend installing it using one of the following:
|
27
|
+
|
28
|
+
* [RVM](https://rvm.io/)
|
29
|
+
* [asdf](https://asdf-vm.com/)
|
30
|
+
* [rbenv](https://rbenv.org/)
|
31
|
+
* [ruby-install](https://github.com/postmodern/ruby-install)
|
32
|
+
|
33
|
+
### Ruby Dependencies
|
34
|
+
|
35
|
+
Ruby dependencies are managed using [bundler](https://bundler.io/), which comes installed with Ruby.
|
36
|
+
To install Ruby dependencies, run:
|
37
|
+
|
38
|
+
```bash
|
39
|
+
$ bundle install
|
40
|
+
```
|
41
|
+
|
42
|
+
Once that is done, prefix Ruby commands with `bundle exec` in order to run them in the context of the project bundle.
|
43
|
+
|
44
|
+
### Docker and Docker Compose
|
45
|
+
|
46
|
+
This project uses Docker Engine and Docker Compose to run <%= ElasticGraph.setup_env.datastore_name %> locally. We recommend installing
|
47
|
+
[Docker Desktop](https://docs.docker.com/desktop/) to get both Docker dependencies.
|
48
|
+
|
49
|
+
## Local Development
|
50
|
+
|
51
|
+
Some useful commands to try:
|
52
|
+
|
53
|
+
```bash
|
54
|
+
# The build rake task can be used after making changes to rebuild everything
|
55
|
+
bundle exec rake build
|
56
|
+
|
57
|
+
# See all tasks available for managing your project and schemas
|
58
|
+
bundle exec rake -T
|
59
|
+
|
60
|
+
# Boot a local instance prepopulated with fake data, useful for experimenting
|
61
|
+
bundle exec rake boot_locally
|
62
|
+
|
63
|
+
# The GraphiQL UI should open automatically
|
64
|
+
open http://localhost:9393/
|
65
|
+
|
66
|
+
# You can also visit <%= ElasticGraph.setup_env.datastore_ui_name %> via:
|
67
|
+
open http://localhost:19293/
|
68
|
+
```
|
69
|
+
|
70
|
+
### Run Build Tasks
|
71
|
+
|
72
|
+
Run a complete suite of build tasks with the build `rake` task:
|
73
|
+
|
74
|
+
```bash
|
75
|
+
bundle exec rake build
|
76
|
+
```
|
77
|
+
|
78
|
+
This will:
|
79
|
+
1. (Re)generate your schema artifacts
|
80
|
+
2. Validate all registered queries against the latest schema
|
81
|
+
3. Lint everything (use `bundle exec standardrb --fix` to fix most issues)
|
82
|
+
4. Run tests (including the common shared ElasticGraph tests)
|
83
|
+
|
84
|
+
Note: on CI, you'll want to use `bundle exec rake check` instead of `bundle exec rake build`,
|
85
|
+
so that it verifies that schema artifacts are up-to-date (rather than dumping them).
|
86
|
+
|
87
|
+
### Upgrading ElasticGraph
|
88
|
+
|
89
|
+
Upgrades to the ElasticGraph gems will come with [release notes](https://github.com/block/elasticgraph/releases/tag/v0.19.0.0) that include upgrade instructions, if necessary.
|
90
|
+
|
91
|
+
Here's the bare minimum upgrade process:
|
92
|
+
|
93
|
+
1. Modify `elasticgraph_details` in the root `Gemfile` and run `bundle install`.
|
94
|
+
2. Run `bundle exec rake`.
|
95
|
+
3. Commit the results.
|
96
|
+
|
97
|
+
### Managing <%= ElasticGraph.setup_env.datastore_name %>
|
98
|
+
|
99
|
+
The `<%= ElasticGraph.setup_env.datastore %>:` tasks will boot the desired <%= ElasticGraph.setup_env.datastore_name %> version using docker. You can
|
100
|
+
use either the `:boot` or `:daemon` tasks:
|
101
|
+
|
102
|
+
* The `:boot` task will keep <%= ElasticGraph.setup_env.datastore_name %> in the foreground, allowing you to see the logs.
|
103
|
+
* The `:daemon` task runs <%= ElasticGraph.setup_env.datastore_name %> as a background daemon task. Notably, it waits to return
|
104
|
+
until <%= ElasticGraph.setup_env.datastore_name %> is ready to receive traffic.
|
105
|
+
|
106
|
+
If you use a `:daemon` task, you can later use the corresponding `:halt` task to stop the daemon.
|
107
|
+
|
108
|
+
### Using the GraphiQL interactive GraphQL query editor
|
109
|
+
|
110
|
+
When running `bundle exec rake boot_locally` the GraphiQL editor should open automatically
|
111
|
+
(`open http://localhost:9393/`). Using it you can query your ElasticGraph cluster using GraphQL.
|
112
|
+
|
113
|
+
### Seeding Fake Data
|
114
|
+
|
115
|
+
The `bundle exec rake index_fake_data:<type_name>` tasks generate and index a batch of fake data.
|
116
|
+
You can pass an arg (note quotes) to seed more batches of data:
|
117
|
+
`bundle exec rake "index_fake_data:<type_name>[10]"`.
|
118
|
+
|
119
|
+
### Using <%= ElasticGraph.setup_env.datastore_ui_name %>
|
120
|
+
|
121
|
+
After running `bundle exec rake boot_locally` and opening <%= ElasticGraph.setup_env.datastore_ui_name %>
|
122
|
+
`open http://localhost:19293/` click "Dev Tools" to open the <%= ElasticGraph.setup_env.datastore_name %> console.
|
123
|
+
|
124
|
+
Here are some queries to get you started:
|
125
|
+
|
126
|
+
```
|
127
|
+
# Cluster info
|
128
|
+
GET /_cat/indices?v
|
129
|
+
GET /_cat/shards?v
|
130
|
+
GET /_cat/templates?v
|
131
|
+
GET /_cat/nodes?v
|
132
|
+
GET /_cat/allocation?v
|
133
|
+
|
134
|
+
# Or with a pattern
|
135
|
+
GET /_cat/shards/*_rollover__202*?v
|
136
|
+
|
137
|
+
# More cluster info
|
138
|
+
GET /_cluster/health
|
139
|
+
GET /_cluster/settings
|
140
|
+
|
141
|
+
# Test queries (change from `artists` to your index name)
|
142
|
+
GET /artists/_search
|
143
|
+
{
|
144
|
+
"from": 0,
|
145
|
+
"size": 1
|
146
|
+
}
|
147
|
+
|
148
|
+
GET /artists/_search
|
149
|
+
{
|
150
|
+
"from": 0,
|
151
|
+
"size": 1,
|
152
|
+
"query": {
|
153
|
+
"bool": {
|
154
|
+
"must": [
|
155
|
+
{
|
156
|
+
"match": {
|
157
|
+
"bio": "accordion"
|
158
|
+
}
|
159
|
+
}
|
160
|
+
]
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}
|
164
|
+
```
|
165
|
+
|
166
|
+
### Query Registry
|
167
|
+
|
168
|
+
This project uses the ElasticGraph query registry extension. This is an optional piece you can choose to remove,
|
169
|
+
but provides many benefits--see the [elasticgraph-query_registry
|
170
|
+
README](https://github.com/block/elasticgraph/tree/main/elasticgraph-query_registry#elasticgraphqueryregistry)
|
171
|
+
for details.
|
172
|
+
|
173
|
+
With the registry in place, clients must register their queries in a directory under
|
174
|
+
[config/queries](config/queries) that matches their resolved application name.
|
175
|
+
The CI build will validate that all schema changes are compatible with all registered queries, and
|
176
|
+
your deployed GraphQL endpoints will reject any unregistered queries.
|
@@ -0,0 +1,64 @@
|
|
1
|
+
project_root = File.expand_path(__dir__)
|
2
|
+
|
3
|
+
require "elastic_graph/local/rake_tasks"
|
4
|
+
require "elastic_graph/query_registry/rake_tasks"
|
5
|
+
require "rspec/core/rake_task"
|
6
|
+
require "standard/rake"
|
7
|
+
require_relative "lib/<%= ElasticGraph.setup_env.app_name %>/fake_data_batch_generator"
|
8
|
+
|
9
|
+
settings_file = "#{project_root}/config/settings/local.yaml"
|
10
|
+
|
11
|
+
ElasticGraph::Local::RakeTasks.new(
|
12
|
+
local_config_yaml: settings_file,
|
13
|
+
path_to_schema: "#{project_root}/config/schema.rb"
|
14
|
+
) do |tasks|
|
15
|
+
# Set this to true once you're beyond the prototyping stage.
|
16
|
+
tasks.enforce_json_schema_version = false
|
17
|
+
|
18
|
+
# Determines casing of field names. Can be either `:camelCase` or `:snake_case`.
|
19
|
+
tasks.schema_element_name_form = :camelCase
|
20
|
+
|
21
|
+
# Customizes the names of fields generated by ElasticGraph.
|
22
|
+
tasks.schema_element_name_overrides = {
|
23
|
+
# Example: force inequality operators to be spelled out.
|
24
|
+
# gt: "greaterThan",
|
25
|
+
# gte: "greaterThanOrEqualTo",
|
26
|
+
# lt: "lessThan",
|
27
|
+
# lte: "lessThanOrEqualTo"
|
28
|
+
}
|
29
|
+
|
30
|
+
# Customizes the naming format used by derived types.
|
31
|
+
tasks.derived_type_name_formats = {
|
32
|
+
# Example: change suffix used for filter inputs from `FilterInput` to just `Filter`.
|
33
|
+
# FilterInput: "%{base}Filter",
|
34
|
+
}
|
35
|
+
|
36
|
+
# Use this to override type names generated by ElasticGraph. We generally recommend sticking
|
37
|
+
# with the defaults, but to align with conventions in your organization you may need to override
|
38
|
+
# some type names.
|
39
|
+
tasks.type_name_overrides = {
|
40
|
+
# Example: this would make your ElasticGraph schema use `IDFilter` in place of the standard `IDFilterInput`.
|
41
|
+
# IDFilterInput: "IDFilter"
|
42
|
+
}
|
43
|
+
|
44
|
+
# TODO: replace this with a fake data generator for your own dataset.
|
45
|
+
tasks.define_fake_data_batch_for :artists do
|
46
|
+
<%= ElasticGraph.setup_env.app_module %>::FakeDataBatchGenerator.generate(artists: 100, venues: 10)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
ElasticGraph::QueryRegistry::RakeTasks.from_yaml_file(
|
51
|
+
settings_file,
|
52
|
+
"config/queries",
|
53
|
+
require_eg_latency_slo_directive: false
|
54
|
+
)
|
55
|
+
|
56
|
+
::RSpec::Core::RakeTask.new
|
57
|
+
|
58
|
+
standard_checks = ["standard", "query_registry:validate_queries", "spec"]
|
59
|
+
|
60
|
+
desc "Rebuild everything. Intended to be run locally as you iterate on the schema"
|
61
|
+
task build: ["schema_artifacts:dump", *standard_checks]
|
62
|
+
|
63
|
+
desc "Check everything. Intended to be run on CI to check your project."
|
64
|
+
task check: ["schema_artifacts:check", *standard_checks]
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# TODO: remove or replace this query when you replace the artist schema.
|
2
|
+
query FindArtist {
|
3
|
+
byName: artists(filter: {
|
4
|
+
name: {equalToAnyOf: ["U2"]}
|
5
|
+
}) {
|
6
|
+
nodes {
|
7
|
+
name
|
8
|
+
bio {
|
9
|
+
yearFormed
|
10
|
+
}
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
byBioYearFounded: artists(filter: {
|
15
|
+
bio: {yearFormed: {gt: 2000}}
|
16
|
+
}) {
|
17
|
+
nodes {
|
18
|
+
name
|
19
|
+
bio {
|
20
|
+
yearFormed
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# TODO: replace this file with one that defines the schema for your own dataset.
|
2
|
+
ElasticGraph.define_schema do |schema|
|
3
|
+
schema.object_type "Artist" do |t|
|
4
|
+
t.field "id", "ID"
|
5
|
+
t.field "name", "String"
|
6
|
+
t.field "lifetimeSales", "JsonSafeLong"
|
7
|
+
t.field "bio", "ArtistBio"
|
8
|
+
|
9
|
+
t.field "albums", "[Album!]!" do |f|
|
10
|
+
f.mapping type: "nested"
|
11
|
+
end
|
12
|
+
|
13
|
+
t.field "tours", "[Tour!]!" do |f|
|
14
|
+
f.mapping type: "nested"
|
15
|
+
end
|
16
|
+
|
17
|
+
t.index "artists"
|
18
|
+
end
|
19
|
+
|
20
|
+
schema.object_type "ArtistBio" do |t|
|
21
|
+
t.field "yearFormed", "Int"
|
22
|
+
t.field "homeCountry", "String"
|
23
|
+
t.field "description", "String" do |f|
|
24
|
+
f.mapping type: "text"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
schema.object_type "Album" do |t|
|
29
|
+
t.field "name", "String"
|
30
|
+
t.field "releasedOn", "Date"
|
31
|
+
t.field "soldUnits", "Int"
|
32
|
+
t.field "tracks", "[AlbumTrack!]!" do |f|
|
33
|
+
f.mapping type: "nested"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
schema.object_type "AlbumTrack" do |t|
|
38
|
+
t.field "name", "String"
|
39
|
+
t.field "trackNumber", "Int"
|
40
|
+
t.field "lengthInSeconds", "Int"
|
41
|
+
end
|
42
|
+
|
43
|
+
schema.object_type "Tour" do |t|
|
44
|
+
t.field "name", "String"
|
45
|
+
t.field "shows", "[Show!]!" do |f|
|
46
|
+
f.mapping type: "nested"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
schema.object_type "Show" do |t|
|
51
|
+
t.relates_to_one "venue", "Venue", via: "venueId", dir: :out
|
52
|
+
t.field "attendance", "Int"
|
53
|
+
t.field "startedAt", "DateTime"
|
54
|
+
end
|
55
|
+
|
56
|
+
schema.object_type "Venue" do |t|
|
57
|
+
t.field "id", "ID"
|
58
|
+
t.field "name", "String"
|
59
|
+
t.field "location", "GeoLocation"
|
60
|
+
t.field "capacity", "Int"
|
61
|
+
t.relates_to_many "featuredArtists", "Artist", via: "tours.shows.venueId", dir: :in, singular: "featuredArtist"
|
62
|
+
|
63
|
+
t.index "venues"
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
3
|
+
ElasticGraph.define_schema do |schema|
|
4
|
+
# ElasticGraph will tell you when you need to bump this.
|
5
|
+
schema.json_schema_version 1
|
6
|
+
|
7
|
+
# This registers the elasticgraph-query_registry extension, which can be used to reject queries that
|
8
|
+
# clients have not registered (and to reject queries that differ from what a client has registered).
|
9
|
+
# In addition, every registered query is validated against the schema in the CI build, giving you
|
10
|
+
# confidence as you evolve your schema that you're not breaking client queries.
|
11
|
+
#
|
12
|
+
# If you don't want to use this extension, you can remove these lines.
|
13
|
+
require(query_registry_path = "elastic_graph/query_registry/graphql_extension")
|
14
|
+
schema.register_graphql_extension ElasticGraph::QueryRegistry::GraphQLExtension, defined_at: query_registry_path
|
15
|
+
end
|
16
|
+
|
17
|
+
# Load the rest of the schema from files at config/schema/**/*.rb.
|
18
|
+
Dir["#{__dir__}/schema/**/*.rb"].each do |schema_def_file|
|
19
|
+
# Must use `load`, not `require` so that if the schema is evaluated multiple times it works.
|
20
|
+
load Pathname(schema_def_file).expand_path
|
21
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
datastore:
|
2
|
+
client_faraday_adapter:
|
3
|
+
name: httpx
|
4
|
+
require: httpx/adapters/faraday
|
5
|
+
clusters:
|
6
|
+
main:
|
7
|
+
backend: <%= ElasticGraph.setup_env.datastore %>
|
8
|
+
url: http://localhost:9293
|
9
|
+
settings: {}
|
10
|
+
index_definitions:
|
11
|
+
# TODO: replace the `artists:` and `venues:` keys with the indices from your dataset
|
12
|
+
artists: &main_index_settings
|
13
|
+
# elasticgraph-local relies on the cluster being named "main".
|
14
|
+
query_cluster: "main"
|
15
|
+
index_into_clusters: ["main"]
|
16
|
+
ignore_routing_values: []
|
17
|
+
custom_timestamp_ranges: []
|
18
|
+
setting_overrides:
|
19
|
+
number_of_shards: 10
|
20
|
+
setting_overrides_by_timestamp: {}
|
21
|
+
venues: *main_index_settings
|
22
|
+
max_client_retries: 3
|
23
|
+
graphql:
|
24
|
+
default_page_size: 50
|
25
|
+
max_page_size: 500
|
26
|
+
logger:
|
27
|
+
device: stderr
|
28
|
+
indexer:
|
29
|
+
latency_slo_thresholds_by_timestamp_in_ms: {}
|
30
|
+
schema_artifacts:
|
31
|
+
directory: config/schema/artifacts
|
32
|
+
query_registry:
|
33
|
+
# Allow any query by any client since this is for local use.
|
34
|
+
allow_unregistered_clients: true
|
35
|
+
allow_any_query_for_clients: []
|
36
|
+
path_to_registry: config/queries
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require "factory_bot"
|
2
|
+
require "faker"
|
3
|
+
require_relative "shared_factories"
|
4
|
+
|
5
|
+
# TODO: replace the artist/album/tour/venue factories with your own.
|
6
|
+
FactoryBot.define do
|
7
|
+
factory :artist, parent: :indexed_type_base do
|
8
|
+
__typename { "Artist" }
|
9
|
+
name { Faker::Music.band }
|
10
|
+
|
11
|
+
lifetimeSales do
|
12
|
+
albums.map { |a| a.fetch(:soldUnits) }.sum
|
13
|
+
end
|
14
|
+
|
15
|
+
bio { build(:artist_bio) }
|
16
|
+
|
17
|
+
albums do
|
18
|
+
Faker::Number.between(from: 1, to: 10).times.map { build(:album) }
|
19
|
+
end
|
20
|
+
|
21
|
+
tours do
|
22
|
+
Faker::Number.between(from: 0, to: 8).times.map { build(:tour, venueIds: venueIds) }
|
23
|
+
end
|
24
|
+
|
25
|
+
transient do
|
26
|
+
venueIds { [] }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
factory :artist_bio, parent: :hash_base do
|
31
|
+
__typename { "ArtistBio" }
|
32
|
+
yearFormed { Faker::Number.between(from: 1900, to: 2025) }
|
33
|
+
homeCountry { Faker::Address.country }
|
34
|
+
description { Faker::Lorem.paragraphs(number: 3).join("\n\n") }
|
35
|
+
end
|
36
|
+
|
37
|
+
factory :album, parent: :hash_base do
|
38
|
+
__typename { "Album" }
|
39
|
+
name { Faker::Music.album }
|
40
|
+
releasedOn { Faker::Date.between(from: "1900-01-01", to: "2025-12-31").iso8601 }
|
41
|
+
soldUnits { Faker::Number.between(from: 10000, to: 100_000_000) }
|
42
|
+
tracks do
|
43
|
+
Faker::Number.between(from: 1, to: 20).times.map do |index|
|
44
|
+
build(:album_track, trackNumber: index + 1)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
factory :album_track, parent: :hash_base do
|
50
|
+
__typename { "AlbumTrack" }
|
51
|
+
name { Faker::Music::RockBand.song }
|
52
|
+
trackNumber { Faker::Number.between(from: 1, to: 20) }
|
53
|
+
lengthInSeconds { Faker::Number.between(from: 30, to: 1200) }
|
54
|
+
end
|
55
|
+
|
56
|
+
factory :tour, parent: :hash_base do
|
57
|
+
__typename { "Tour" }
|
58
|
+
name { "#{Faker::Music::RockBand.song} Tour" }
|
59
|
+
shows do
|
60
|
+
start_date = Faker::Date.between(from: "1900-01-01", to: "2025-12-31")
|
61
|
+
|
62
|
+
Faker::Number.between(from: 3, to: 200).times.map do |index|
|
63
|
+
venue_id = Faker::Base.sample(venueIds)
|
64
|
+
build(:show, date: start_date + index, venueId: venue_id)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
transient do
|
69
|
+
venueIds { [] }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
factory :show, parent: :hash_base do
|
74
|
+
__typename { "Show" }
|
75
|
+
attendance { Faker::Number.between(from: 200, to: 100_000) }
|
76
|
+
startedAt { "#{date.iso8601}T#{startTime}" }
|
77
|
+
venueId { nil }
|
78
|
+
|
79
|
+
transient do
|
80
|
+
date { Faker::Date.between(from: "1900-01-01", to: "2025-12-31") }
|
81
|
+
startTime { Faker::Base.sample(%w[19:00:00Z 19:30:00Z 20:00:00Z 20:30:00Z]) }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
factory :venue, parent: :indexed_type_base do
|
86
|
+
__typename { "Venue" }
|
87
|
+
|
88
|
+
name do
|
89
|
+
# Some common music venue types
|
90
|
+
venue_types = ["Theater", "Arena", "Music Hall", "Stadium", "Opera House", "Amphitheater"]
|
91
|
+
|
92
|
+
city_name = Faker::Address.city
|
93
|
+
venue_type = Faker::Base.sample(venue_types)
|
94
|
+
|
95
|
+
"#{city_name} #{venue_type}"
|
96
|
+
end
|
97
|
+
|
98
|
+
location { build(:geo_location) }
|
99
|
+
capacity { Faker::Number.between(from: 200, to: 100_000) }
|
100
|
+
end
|
101
|
+
|
102
|
+
factory :geo_location, parent: :hash_base do
|
103
|
+
__typename { "GeoLocation" }
|
104
|
+
latitude { Faker::Number.between(from: -90.0, to: 90.0) }
|
105
|
+
longitude { Faker::Number.between(from: -180.0, to: 180.0) }
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative "factories"
|
2
|
+
|
3
|
+
module <%= ElasticGraph.setup_env.app_module %>
|
4
|
+
module FakeDataBatchGenerator
|
5
|
+
def self.generate(artists:, venues:)
|
6
|
+
venue_list = FactoryBot.build_list(:venue, venues)
|
7
|
+
venue_ids = venue_list.map { |v| v.fetch(:id) }
|
8
|
+
|
9
|
+
artist_list = FactoryBot.build_list(:artist, artists, venueIds: venue_ids)
|
10
|
+
|
11
|
+
venue_list + artist_list
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "date"
|
2
|
+
require "factory_bot"
|
3
|
+
require "faker"
|
4
|
+
|
5
|
+
FactoryBot.define do
|
6
|
+
factory :hash_base, class: Hash do
|
7
|
+
initialize_with { attributes }
|
8
|
+
end
|
9
|
+
|
10
|
+
trait :uuid_id do
|
11
|
+
id { Faker::Internet.uuid }
|
12
|
+
end
|
13
|
+
|
14
|
+
trait :versioned do
|
15
|
+
__version { Faker::Number.between(from: 1, to: 10) }
|
16
|
+
end
|
17
|
+
|
18
|
+
current_json_schema_version = nil
|
19
|
+
|
20
|
+
factory :indexed_type_base, parent: :hash_base, traits: [:uuid_id, :versioned] do
|
21
|
+
__typename { raise NotImplementedError, "You must supply __typename" }
|
22
|
+
__json_schema_version do
|
23
|
+
current_json_schema_version ||= begin
|
24
|
+
json_schema_file = File.expand_path("../../config/schema/artifacts/json_schemas.yaml", __dir__)
|
25
|
+
YAML.safe_load_file(json_schema_file).fetch("json_schema_version")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "elastic_graph/local/spec_support/common_project_specs"
|
2
|
+
require "<%= ElasticGraph.setup_env.app_name %>/factories"
|
3
|
+
require "<%= ElasticGraph.setup_env.app_name %>/fake_data_batch_generator"
|
4
|
+
|
5
|
+
RSpec.describe "ElasticGraph project" do
|
6
|
+
ignored_factories = [
|
7
|
+
# List any factories to ignore
|
8
|
+
]
|
9
|
+
|
10
|
+
include_examples "an ElasticGraph project",
|
11
|
+
use_settings_yaml: "local.yaml",
|
12
|
+
ignored_factories: ignored_factories
|
13
|
+
|
14
|
+
# TODO: update this spec as needed to generate example fake data for your dataset.
|
15
|
+
it "generates a batch of valid records from `FakeDataBatchGenerator`" do
|
16
|
+
batch = <%= ElasticGraph.setup_env.app_module %>::FakeDataBatchGenerator.generate(artists: 20, venues: 5)
|
17
|
+
expect(batch.size).to eq(25)
|
18
|
+
end
|
19
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elasticgraph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.19.
|
4
|
+
version: 0.19.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Myron Marston
|
@@ -10,139 +10,71 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2025-02-06 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
17
|
-
requirement: !ruby/object:Gem::Requirement
|
18
|
-
requirements:
|
19
|
-
- - "~>"
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: '2.26'
|
22
|
-
type: :development
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
requirements:
|
26
|
-
- - "~>"
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
version: '2.26'
|
29
|
-
- !ruby/object:Gem::Dependency
|
30
|
-
name: rubocop-rake
|
31
|
-
requirement: !ruby/object:Gem::Requirement
|
32
|
-
requirements:
|
33
|
-
- - "~>"
|
34
|
-
- !ruby/object:Gem::Version
|
35
|
-
version: '0.6'
|
36
|
-
type: :development
|
37
|
-
prerelease: false
|
38
|
-
version_requirements: !ruby/object:Gem::Requirement
|
39
|
-
requirements:
|
40
|
-
- - "~>"
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
version: '0.6'
|
43
|
-
- !ruby/object:Gem::Dependency
|
44
|
-
name: rubocop-rspec
|
45
|
-
requirement: !ruby/object:Gem::Requirement
|
46
|
-
requirements:
|
47
|
-
- - "~>"
|
48
|
-
- !ruby/object:Gem::Version
|
49
|
-
version: '3.1'
|
50
|
-
type: :development
|
51
|
-
prerelease: false
|
52
|
-
version_requirements: !ruby/object:Gem::Requirement
|
53
|
-
requirements:
|
54
|
-
- - "~>"
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
version: '3.1'
|
57
|
-
- !ruby/object:Gem::Dependency
|
58
|
-
name: standard
|
59
|
-
requirement: !ruby/object:Gem::Requirement
|
60
|
-
requirements:
|
61
|
-
- - "~>"
|
62
|
-
- !ruby/object:Gem::Version
|
63
|
-
version: 1.41.0
|
64
|
-
type: :development
|
65
|
-
prerelease: false
|
66
|
-
version_requirements: !ruby/object:Gem::Requirement
|
67
|
-
requirements:
|
68
|
-
- - "~>"
|
69
|
-
- !ruby/object:Gem::Version
|
70
|
-
version: 1.41.0
|
71
|
-
- !ruby/object:Gem::Dependency
|
72
|
-
name: elasticgraph-admin
|
73
|
-
requirement: !ruby/object:Gem::Requirement
|
74
|
-
requirements:
|
75
|
-
- - '='
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: 0.19.0.0
|
78
|
-
type: :runtime
|
79
|
-
prerelease: false
|
80
|
-
version_requirements: !ruby/object:Gem::Requirement
|
81
|
-
requirements:
|
82
|
-
- - '='
|
83
|
-
- !ruby/object:Gem::Version
|
84
|
-
version: 0.19.0.0
|
85
|
-
- !ruby/object:Gem::Dependency
|
86
|
-
name: elasticgraph-graphql
|
16
|
+
name: elasticgraph-support
|
87
17
|
requirement: !ruby/object:Gem::Requirement
|
88
18
|
requirements:
|
89
19
|
- - '='
|
90
20
|
- !ruby/object:Gem::Version
|
91
|
-
version: 0.19.
|
21
|
+
version: 0.19.1.0
|
92
22
|
type: :runtime
|
93
23
|
prerelease: false
|
94
24
|
version_requirements: !ruby/object:Gem::Requirement
|
95
25
|
requirements:
|
96
26
|
- - '='
|
97
27
|
- !ruby/object:Gem::Version
|
98
|
-
version: 0.19.
|
28
|
+
version: 0.19.1.0
|
99
29
|
- !ruby/object:Gem::Dependency
|
100
|
-
name:
|
30
|
+
name: thor
|
101
31
|
requirement: !ruby/object:Gem::Requirement
|
102
32
|
requirements:
|
103
|
-
- -
|
104
|
-
- !ruby/object:Gem::Version
|
105
|
-
version: 0.19.0.0
|
106
|
-
type: :runtime
|
107
|
-
prerelease: false
|
108
|
-
version_requirements: !ruby/object:Gem::Requirement
|
109
|
-
requirements:
|
110
|
-
- - '='
|
111
|
-
- !ruby/object:Gem::Version
|
112
|
-
version: 0.19.0.0
|
113
|
-
- !ruby/object:Gem::Dependency
|
114
|
-
name: elasticgraph-local
|
115
|
-
requirement: !ruby/object:Gem::Requirement
|
116
|
-
requirements:
|
117
|
-
- - '='
|
33
|
+
- - "~>"
|
118
34
|
- !ruby/object:Gem::Version
|
119
|
-
version:
|
35
|
+
version: '1.3'
|
120
36
|
type: :runtime
|
121
37
|
prerelease: false
|
122
38
|
version_requirements: !ruby/object:Gem::Requirement
|
123
39
|
requirements:
|
124
|
-
- -
|
40
|
+
- - "~>"
|
125
41
|
- !ruby/object:Gem::Version
|
126
|
-
version:
|
42
|
+
version: '1.3'
|
127
43
|
description:
|
128
44
|
email:
|
129
45
|
- myron@squareup.com
|
130
|
-
executables:
|
46
|
+
executables:
|
47
|
+
- elasticgraph
|
131
48
|
extensions: []
|
132
49
|
extra_rdoc_files: []
|
133
50
|
files:
|
134
51
|
- LICENSE.txt
|
135
52
|
- README.md
|
136
|
-
- elasticgraph
|
53
|
+
- exe/elasticgraph
|
54
|
+
- lib/elastic_graph/cli.rb
|
55
|
+
- lib/elastic_graph/project_template/.gitignore
|
56
|
+
- lib/elastic_graph/project_template/.standard.yml.tt
|
57
|
+
- lib/elastic_graph/project_template/Gemfile.tt
|
58
|
+
- lib/elastic_graph/project_template/README.md.tt
|
59
|
+
- lib/elastic_graph/project_template/Rakefile.tt
|
60
|
+
- lib/elastic_graph/project_template/config/queries/example_client/FindArtist.graphql
|
61
|
+
- lib/elastic_graph/project_template/config/queries/example_client/ListArtistAlbums.graphql
|
62
|
+
- lib/elastic_graph/project_template/config/schema.rb.tt
|
63
|
+
- lib/elastic_graph/project_template/config/schema/artists.rb.tt
|
64
|
+
- lib/elastic_graph/project_template/config/settings/local.yaml.tt
|
65
|
+
- lib/elastic_graph/project_template/lib/app_name/factories.rb
|
66
|
+
- lib/elastic_graph/project_template/lib/app_name/fake_data_batch_generator.rb.tt
|
67
|
+
- lib/elastic_graph/project_template/lib/app_name/shared_factories.rb
|
68
|
+
- lib/elastic_graph/project_template/spec/project_spec.rb.tt
|
137
69
|
homepage: https://block.github.io/elasticgraph/
|
138
70
|
licenses:
|
139
71
|
- MIT
|
140
72
|
metadata:
|
141
73
|
bug_tracker_uri: https://github.com/block/elasticgraph/issues
|
142
|
-
changelog_uri: https://github.com/block/elasticgraph/releases/tag/v0.19.
|
74
|
+
changelog_uri: https://github.com/block/elasticgraph/releases/tag/v0.19.1.0
|
143
75
|
documentation_uri: https://block.github.io/elasticgraph/docs/main/
|
144
76
|
homepage_uri: https://block.github.io/elasticgraph/
|
145
|
-
source_code_uri: https://github.com/block/elasticgraph/tree/v0.19.
|
77
|
+
source_code_uri: https://github.com/block/elasticgraph/tree/v0.19.1.0/elasticgraph
|
146
78
|
gem_category: core
|
147
79
|
post_install_message:
|
148
80
|
rdoc_options: []
|
@@ -150,9 +82,12 @@ require_paths:
|
|
150
82
|
- lib
|
151
83
|
required_ruby_version: !ruby/object:Gem::Requirement
|
152
84
|
requirements:
|
153
|
-
- - "
|
85
|
+
- - ">="
|
154
86
|
- !ruby/object:Gem::Version
|
155
87
|
version: '3.2'
|
88
|
+
- - "<"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '3.5'
|
156
91
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
157
92
|
requirements:
|
158
93
|
- - ">="
|
@@ -162,5 +97,5 @@ requirements: []
|
|
162
97
|
rubygems_version: 3.5.22
|
163
98
|
signing_key:
|
164
99
|
specification_version: 4
|
165
|
-
summary:
|
100
|
+
summary: Bootstraps ElasticGraph projects.
|
166
101
|
test_files: []
|
data/elasticgraph.gemspec
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
# Copyright 2024 Block, Inc.
|
2
|
-
#
|
3
|
-
# Use of this source code is governed by an MIT-style
|
4
|
-
# license that can be found in the LICENSE file or at
|
5
|
-
# https://opensource.org/licenses/MIT.
|
6
|
-
#
|
7
|
-
# frozen_string_literal: true
|
8
|
-
|
9
|
-
require_relative "../gemspec_helper"
|
10
|
-
|
11
|
-
ElasticGraphGemspecHelper.define_elasticgraph_gem(gemspec_file: __FILE__, category: :core) do |spec, eg_version|
|
12
|
-
spec.summary = "ElasticGraph meta-gem that pulls in all the core ElasticGraph gems."
|
13
|
-
|
14
|
-
spec.add_dependency "elasticgraph-admin", eg_version
|
15
|
-
spec.add_dependency "elasticgraph-graphql", eg_version
|
16
|
-
spec.add_dependency "elasticgraph-indexer", eg_version
|
17
|
-
spec.add_dependency "elasticgraph-local", eg_version
|
18
|
-
end
|