-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/schema registry in geronimo #2278
Open
retgoat
wants to merge
15
commits into
master
Choose a base branch
from
feature/schema-registry-in-geronimo
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
101e7a7
Finish schema registry client
retgoat 4448002
Add avro schema for key
retgoat fe0c6ef
Add tests for schema registry client rework push to kafka
retgoat a85bb98
Rework tests
retgoat 6ce407e
Add part of a model spec
retgoat 8748f3e
Push only encoded values
retgoat 14414df
Add push to kafka on update
retgoat 77ca38c
Add storefront and validation tests
retgoat 1ef1b88
Update readme
retgoat b180f13
Add CMS api docs
retgoat 4ca64ff
Update readme
retgoat 5c064e4
Fix seed task
retgoat 6e9a1b3
Update readme
retgoat e61d574
Update readme
retgoat 03543b1
Add geronimo workers
retgoat File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Data Structures | ||
|
||
## ContentTypeBase | ||
+ schema: `{ "title": {"type": ["string"], "required": true }}` (required, string) - JSON schema of a content_type | ||
+ name: `BlogPost` (required, string) - Name of a content_type | ||
|
||
## ContentTypePayload | ||
- Include ContentTypeBase | ||
|
||
## ContentTypeUpdatePayload | ||
+ schema: `{ "another_title": {"type": ["string"], "required": true }}` (optional, string) - JSON schema of a content_type | ||
+ name: `BlogPost` (optional, string) - Name of a content_type | ||
|
||
## ContentTypeResponse | ||
- Include ContentTypeBase | ||
+ scope: `1` (required, string) - Scope of an admin who created a given ContentType | ||
+ id: `1` (required, number) - ID of a created ContentType | ||
+ created_by: `4` (required, number) - ID of a user who created a given ContentType | ||
+ versions: `["2017-06-12T03:13:46Z", "2017-06-13T03:12:46Z"]` (optional, string) - Previous versions of ContentType | ||
|
||
## EntityBase | ||
+ content_type_id: 1 (required, number) - id of a corresponding content_type | ||
+ storefront: `theperfectgourmet.com` (required, string) - Name of a store on which given Entity has been created | ||
+ content: ` { "title": "foo" } ` (required, string) - JSON content of a Entity | ||
|
||
## EntityPayload | ||
- Include EntityBase | ||
|
||
## EntityUpdatePayload | ||
+ content_type_id: 1 (optional, number) - id of a corresponding content_type | ||
+ content: ` { "title": "bar" } ` (optional, string) - JSON content of a Entity | ||
|
||
## EntityAdminResponse | ||
- Include EntityBase | ||
+ schema_version: `2017-06-12T03:13:46Z` (required, string) - Version of schema Entity was validated against | ||
+ storefront: `theperfectgourmet.com` (required, string) - Name of a store on which given Entity has been created | ||
+ kind: `BlogPost` (required, string) - Type of a created Entity | ||
+ id: `3` (required, number) - ID of a created Entity | ||
+ created_by: `4` (required, number) - ID of a user who created a given Entity | ||
+ versions: `["2017-06-12T03:13:46Z", "2017-06-13T03:12:46Z"]` (optional, string) - Previous versions of Entity | ||
|
105 changes: 105 additions & 0 deletions
105
developer-portal/content/reference/resources/admin_cms.apib
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
## ContentType [/v1/admin/content_types{id}] | ||
|
||
This object represents ContentTypes in CMS. | ||
Each ContentType describes specific Entity. | ||
|
||
+ Parameters | ||
+ id: `1` (required, number) - ContentType ID. | ||
|
||
+ Model (application/json) | ||
+ Attributes (ContentTypeResponse) | ||
|
||
|
||
### Retrieve ContentType [GET] | ||
|
||
Allows an administrator to retrieve a content_type record, which includes all | ||
information about the content_type. | ||
|
||
+ Response 200 (application/json) | ||
+ Attributes (ContentTypeResponse) | ||
|
||
### Create New ContentType [POST /v1/admin/content_types] | ||
|
||
Allows an administrator to create a new content_types. | ||
|
||
+ Request (application/json) | ||
+ Attributes (ContentTypePayload) | ||
+ Response 200 (application/json) | ||
+ Attributes (ContentTypeResponse) | ||
|
||
### Update Existing ContentType [PUT] | ||
|
||
+ Request (application/json) | ||
+ Attributes(ContentTypeUpdatePayload) | ||
+ Response 200 (application/json) | ||
+ Attributes (ContentTypeResponse) | ||
|
||
### Get specific version of ContentType [GET /v1/admin/content_types/{id}/versions?ver={version}] | ||
|
||
+ Parameters | ||
+ id: `1` (required, number) - ContentType ID. | ||
+ ver: `2017-06-13T16:14:51.974673Z` (required, string) - Version of a ContentType | ||
|
||
+ Response 200 (application/json) | ||
+ Attributes (ContentTypeResponse) | ||
|
||
### Restore specific version of ContentType [PUT /v1/admin/content_types/{id}/restore?ver={version}] | ||
|
||
+ Parameters | ||
+ id: `1` (required, number) - ContentType ID. | ||
+ ver: `2017-06-13T16:14:51.974673Z` (required, string) - Version of a ContentType | ||
|
||
+ Response 200 (application/json) | ||
+ Attributes (ContentTypeResponse) | ||
|
||
## Entity [/v1/admin/entities{id}] | ||
|
||
This object describes an actual entity of CMS: Blog posts, testimonials, etc. | ||
Each Entity validates against corresponding ContentType's schema before creation. | ||
|
||
+ Parameters | ||
+ id: `1` (required, number) - Entity ID. | ||
|
||
+ Model (application/json) | ||
+ Attributes (EntityAdminResponse) | ||
|
||
### Retrieve Entity [GET] | ||
|
||
Allows an administrator to retrieve a single Entity record. | ||
|
||
+ Response 200 (application/json) | ||
+ Attributes (EntityAdminResponse) | ||
|
||
### Create New Entity [POST /v1/admin/entities] | ||
|
||
Allows an administrator to create a new Entity. | ||
|
||
+ Request (application/json) | ||
+ Attributes (EntityPayload) | ||
+ Response 200 (application/json) | ||
+ Attributes (EntityAdminResponse) | ||
|
||
### Update Existing Entity [PUT] | ||
|
||
+ Request (application/json) | ||
+ Attributes(EntityUpdatePayload) | ||
+ Response 200 (application/json) | ||
+ Attributes (EntityAdminResponse) | ||
|
||
### Get specific version of Entity [GET /v1/admin/entities/{id}/versions?ver={version}] | ||
|
||
+ Parameters | ||
+ id: `1` (required, number) - Entity ID. | ||
+ ver: `2017-06-13T16:14:51.974673Z` (required, string) - Version of a Entity | ||
|
||
+ Response 200 (application/json) | ||
+ Attributes (EntityAdminResponse) | ||
|
||
### Restore specific version of Entity [PUT /v1/admin/entities/{id}/restore?ver={version}] | ||
|
||
+ Parameters | ||
+ id: `1` (required, number) - Entity ID. | ||
+ ver: `2017-06-13T16:14:51.974673Z` (required, string) - Version of a Entity | ||
|
||
+ Response 200 (application/json) | ||
+ Attributes (EntityAdminResponse) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
defmodule Geronimo.Kafka.Pusher do | ||
@moduledoc """ | ||
Implements sync and async pushes to Kafka | ||
""" | ||
require Logger | ||
|
||
def push(module, obj) do | ||
kind = apply(module, :table, []) | ||
data = apply(module, :avro_encode!, [obj]) | ||
res = KafkaEx.produce("geronimo_#{kind}", 0, data, | ||
key: "#{kind}_#{obj.id}", | ||
worker_name: :geronimo_worker) | ||
Logger.debug "#{Inflex.singularize(kind)} with id #{obj.id} pushed to kafka #{inspect(res)}" | ||
end | ||
|
||
def push_async(kind, obj) do | ||
unless Mix.env == :test do | ||
Task.async(fn -> | ||
push(kind, obj) | ||
end) | ||
end | ||
end | ||
|
||
def push_async_await(kind, obj) do | ||
push_async(kind, obj) |> Task.await | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,38 @@ | ||
defmodule Geronimo.Kafka.SchemaRegistryClient do | ||
@moduledoc """ | ||
Provides a easy and conveniens functions to get/store schemas in schema registry | ||
""" | ||
use HTTPoison.Base | ||
|
||
def get_schema(object, id) do | ||
case get("/subjects/#{object}/versions/#{id}") do | ||
{:ok, %HTTPoison.Response{body: body, headers: _, status_code: 200}} -> | ||
body[:schema] | ||
|> Poison.decode! | ||
|> Utils.atomize | ||
{:ok, %HTTPoison.Response{body: body, headers: _, status_code: _}} -> body | ||
{:error, err} -> err | ||
end | ||
end | ||
|
||
def store_schema(schema) do | ||
schema | ||
get("/subjects/#{object}/versions/#{id}") | ||
|> response_body() | ||
end | ||
|
||
def process_url(url) do | ||
"http://#{schema_registry_url()}/#{url}" | ||
def store_schema(object, schema) do | ||
post("/subjects/#{object}/versions", Poison.encode!(%{schema: schema})) | ||
|> response_body() | ||
end | ||
|
||
def process_response_body(body) do | ||
body | ||
|> Poison.decode! | ||
|> Enum.map(fn({k, v}) -> {String.to_atom(k), v} end) | ||
defp response_body(response) do | ||
case response do | ||
{:ok, %HTTPoison.Response{body: body, headers: _, status_code: 200}} -> {:ok, body} | ||
{:ok, %HTTPoison.Response{body: body, headers: _, status_code: _}} -> {:error, body} | ||
{:error, err} -> {:fail, err.reason} | ||
end | ||
end | ||
|
||
def schema_registry_url do | ||
url = Application.fetch_env!(:geronimo, :schema_registry_ip) | ||
def process_url(path) do | ||
ip = Application.fetch_env!(:geronimo, :schema_registry_ip) | ||
port = Application.fetch_env!(:geronimo, :schema_registry_port) | ||
"http://#{url}:#{port}" | ||
"http://#{ip}:#{port}" <> path | ||
end | ||
|
||
def process_request_headers(), do: ["Content-Type", "application/vnd.schemaregistry.v1+json"] | ||
|
||
def process_response_body(body) do | ||
body | ||
|> Poison.decode! | ||
|> Utils.atomize | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,32 @@ | ||
defmodule Geronimo.Kafka.Worker do | ||
@moduledoc """ | ||
Starts KafkaEs worker on app start and registers all needed schemas | ||
NB: Add new modules to register_schemas() if needed. | ||
""" | ||
|
||
require Logger | ||
alias Geronimo.Kafka.SchemaRegistryClient | ||
|
||
def start do | ||
kafka_url = [{Application.fetch_env!(:geronimo, :kafka_host), | ||
Application.fetch_env!(:geronimo, :kafka_port) |> String.to_integer }] | ||
KafkaEx.create_worker(:geronimo_worker, [uris: kafka_url, | ||
consumer_group: Application.fetch_env!(:geronimo, :consumer_group)]) | ||
register_schemas() | ||
end | ||
|
||
def push(kind, obj) do | ||
KafkaEx.produce("geronimo_#{kind}", 0, Poison.encode!(obj), | ||
key: "#{kind}_#{obj.id}", worker_name: :geronimo_worker) | ||
end | ||
def register_schemas do | ||
Task.async(fn-> | ||
modules = [Geronimo.ContentType, Geronimo.Entity] | ||
|
||
def push_async(kind, obj) do | ||
unless Mix.env == :test do | ||
Task.async(fn -> | ||
push(kind, obj) | ||
Enum.each(modules, fn(module) -> | ||
key_schema = apply(module, :avro_schema_key, []) | ||
value_schema = apply(module, :avro_schema_value, []) | ||
object = apply(module, :table, []) | ||
{:ok, k_res} = SchemaRegistryClient.store_schema("#{object}-key", key_schema) | ||
{:ok, v_ver} = SchemaRegistryClient.store_schema("#{object}-value", value_schema) | ||
Logger.info "Schemas for #{object} registered. Key: #{inspect(k_res)}, value: #{inspect(v_ver)}" | ||
end) | ||
end | ||
end | ||
|
||
def push_async_await(kind, obj) do | ||
push_async(kind, obj) |> Task.await | ||
end) |> Task.await | ||
end | ||
end |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that we have
drop-db
, shall we createdrop-test-db
too?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually no. We dropping test DB here because in other case we can not drop development DB cause it belongs to
geronimo
DB user as well.We creating test DB in
reset-test
task.