proto_turf 0.0.1
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +48 -0
- data/lib/proto_turf/cached_confluent_schema_registry.rb +51 -0
- data/lib/proto_turf/confluent_schema_registry.rb +118 -0
- data/lib/proto_turf/version.rb +3 -0
- data/lib/proto_turf.rb +229 -0
- data/proto_turf.gemspec +27 -0
- metadata +107 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 748636abfd68b4fbf48cb1786c3d2617ae0b48400c23e14c9ff03786601a4dd8
|
4
|
+
data.tar.gz: 9b3e76306ecefa2cfe6ca7b097b366d8145ec4c3a2c1dbe59b05625b1d1b37e7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 58e153ed45709e81d7b1d6d2b35523282d866a20f925e549ace5930daf29d1f2afafadcdd48b383bc7f27e662e401aa72cabc7cbd9e4a3d5bc3abad3f121f0d2
|
7
|
+
data.tar.gz: 5715d4b57c35db06292f30ec6228a19d4e089e65558cf0e2c0c698ec930fc471541a1b92d9743344a173a6b7b67ba2c8593bbe198bca5eb58841112d8f5339ce
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Flipp
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# proto_turf
|
2
|
+
|
3
|
+
`proto_turf` is a library to interact with the Confluent Schema Registry using Google Protobuf. It is inspired by and based off of [avro_turf](https://github.com/dasch/avro_turf).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'proto_turf'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install proto_turf
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
ProtoTurf interacts with the Confluent Schema Registry, and caches all results. When you first encode a message, it will register the message and all dependencies with the Schema Registry. When decoding, it will look up the schema in the Schema Registry and use the associated local generated code to decode the message.
|
24
|
+
|
25
|
+
Example usage:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
require 'proto_turf'
|
29
|
+
|
30
|
+
proto_turf = ProtoTurf.new(registry_url: 'http://localhost:8081')
|
31
|
+
message = MyProto::MyMessage.new(field1: 'value1', field2: 42)
|
32
|
+
encoded = proto_turf.encode(message, subject: 'my-subject')
|
33
|
+
|
34
|
+
# Decoding
|
35
|
+
|
36
|
+
decoded_proto_message = proto_turf.decode(encoded_string)
|
37
|
+
```
|
38
|
+
|
39
|
+
If you're using [buf](https://buf.build/) to manage your Protobuf definitions, you should run `buf export` before using `proto_turf` to ensure that all the dependencies are available as `.proto` files in your project. The actual proto text is needed when registering the schema with the Schema Registry.
|
40
|
+
|
41
|
+
## Notes about usage
|
42
|
+
|
43
|
+
* For now, this library only supports a single message per `.proto` file that is registered with the Schema Registry. You can reference as many other files and messages as you like from that message, but keeping it to one message per file simplifies the workflow significantly.
|
44
|
+
* When decoding, this library does *not* attempt to fully parse the Proto definition stored on the schema registry and generate dynamic classes. Instead, it simply parses out the package and message and assumes that the reader has the message available in the descriptor pool. Any compatibility issues should be detected through normal means, i.e. just by instantiating the message and seeing if any errors are raised.
|
45
|
+
|
46
|
+
## TODO
|
47
|
+
|
48
|
+
* Support multi-message proto files
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class ProtoTurf::CachedConfluentSchemaRegistry
|
2
|
+
|
3
|
+
# @param upstream [ProtoTurf::ConfluentSchemaRegistry]
|
4
|
+
def initialize(upstream)
|
5
|
+
@upstream = upstream
|
6
|
+
@schemas_by_id = {}
|
7
|
+
@ids_by_schema = {}
|
8
|
+
@versions_by_subject_and_id = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
# Delegate the following methods to the upstream
|
12
|
+
%i(subject_versions schema_subject_versions).each do |name|
|
13
|
+
define_method(name) do |*args|
|
14
|
+
instance_variable_get(:@upstream).send(name, *args)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param id [Integer] the schema ID to fetch
|
19
|
+
# @return [String] the schema string stored in the registry for the given id
|
20
|
+
def fetch(id)
|
21
|
+
@schemas_by_id[id] ||= @upstream.fetch(id)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param id [Integer] the schema ID to fetch
|
25
|
+
# @param subject [String] the subject to fetch the version for
|
26
|
+
# @return [Integer, nil] the version of the schema for the given subject and id, or nil if not found
|
27
|
+
def fetch_version(id, subject)
|
28
|
+
key = [subject, id]
|
29
|
+
return @versions_by_subject_and_id[key] if @versions_by_subject_and_id[key]
|
30
|
+
|
31
|
+
results = @upstream.schema_subject_versions(id)
|
32
|
+
@versions_by_subject_and_id[key] = results&.find { |r| r['subject'] == subject }&.dig('version')
|
33
|
+
end
|
34
|
+
|
35
|
+
# @param subject [String] the subject to check
|
36
|
+
# @param schema [String] the schema text to check
|
37
|
+
# @return [Boolean] true if we know the schema has been registered for that subject.
|
38
|
+
def registered?(subject, schema)
|
39
|
+
@ids_by_schema[[subject, schema]].present?
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param subject [String] the subject to register the schema under
|
43
|
+
# @param schema [String] the schema text to register
|
44
|
+
# @param references [Array<Hash>] optional references to other schemas
|
45
|
+
def register(subject, schema, references: [])
|
46
|
+
key = [subject, schema]
|
47
|
+
|
48
|
+
@ids_by_schema[key] ||= @upstream.register(subject, schema, references: references)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'excon'
|
2
|
+
|
3
|
+
class ProtoTurf
|
4
|
+
class ConfluentSchemaRegistry
|
5
|
+
|
6
|
+
CONTENT_TYPE = "application/vnd.schemaregistry.v1+json".freeze
|
7
|
+
|
8
|
+
def initialize(
|
9
|
+
url,
|
10
|
+
schema_context: nil,
|
11
|
+
logger: Logger.new($stdout),
|
12
|
+
proxy: nil,
|
13
|
+
user: nil,
|
14
|
+
password: nil,
|
15
|
+
ssl_ca_file: nil,
|
16
|
+
client_cert: nil,
|
17
|
+
client_key: nil,
|
18
|
+
client_key_pass: nil,
|
19
|
+
client_cert_data: nil,
|
20
|
+
client_key_data: nil,
|
21
|
+
path_prefix: nil,
|
22
|
+
connect_timeout: nil,
|
23
|
+
resolv_resolver: nil,
|
24
|
+
retry_limit: nil
|
25
|
+
)
|
26
|
+
@path_prefix = path_prefix
|
27
|
+
@schema_context_prefix = schema_context.nil? ? '' : ":.#{schema_context}:"
|
28
|
+
@schema_context_options = schema_context.nil? ? {} : {query: {subject: @schema_context_prefix}}
|
29
|
+
@logger = logger
|
30
|
+
headers = Excon.defaults[:headers].merge(
|
31
|
+
"Content-Type" => CONTENT_TYPE
|
32
|
+
)
|
33
|
+
params = {
|
34
|
+
headers: headers,
|
35
|
+
user: user,
|
36
|
+
password: password,
|
37
|
+
proxy: proxy,
|
38
|
+
ssl_ca_file: ssl_ca_file,
|
39
|
+
client_cert: client_cert,
|
40
|
+
client_key: client_key,
|
41
|
+
client_key_pass: client_key_pass,
|
42
|
+
client_cert_data: client_cert_data,
|
43
|
+
client_key_data: client_key_data,
|
44
|
+
resolv_resolver: resolv_resolver,
|
45
|
+
connect_timeout: connect_timeout,
|
46
|
+
retry_limit: retry_limit
|
47
|
+
}
|
48
|
+
# Remove nil params to allow Excon to use its default values
|
49
|
+
params.reject! { |_, v| v.nil? }
|
50
|
+
@connection = Excon.new(
|
51
|
+
url,
|
52
|
+
params
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
# @param id [Integer] the schema ID to fetch
|
57
|
+
# @return [String] the schema string stored in the registry for the given id
|
58
|
+
def fetch(id)
|
59
|
+
@logger.info "Fetching schema with id #{id}"
|
60
|
+
data = get("/schemas/ids/#{id}", idempotent: true, **@schema_context_options, )
|
61
|
+
data.fetch("schema")
|
62
|
+
end
|
63
|
+
|
64
|
+
# @param schema_id [Integer] the schema ID to fetch versions for
|
65
|
+
# @return [Array<Hash>] an array of versions for the given schema ID
|
66
|
+
def schema_subject_versions(schema_id)
|
67
|
+
get("/schemas/ids/#{schema_id}/versions", idempotent: true, **@schema_context_options)
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param subject [String] the subject to check
|
71
|
+
# @param schema [String] the schema text to check
|
72
|
+
# @param references [Array<Hash>] optional references to other schemas
|
73
|
+
# @return [Integer] the ID of the registered schema
|
74
|
+
def register(subject, schema, references: [])
|
75
|
+
data = post("/subjects/#{@schema_context_prefix}#{CGI.escapeURIComponent(subject)}/versions",
|
76
|
+
body: { schemaType: 'PROTOBUF',
|
77
|
+
references: references,
|
78
|
+
schema: schema.to_s }.to_json)
|
79
|
+
|
80
|
+
id = data.fetch("id")
|
81
|
+
|
82
|
+
@logger.info "Registered schema for subject `#{@schema_context_prefix}#{subject}`; id = #{id}"
|
83
|
+
|
84
|
+
id
|
85
|
+
end
|
86
|
+
|
87
|
+
# @param subject [String]
|
88
|
+
# @return [Array<Hash>] an array of versions for the given subject
|
89
|
+
def subject_versions(subject)
|
90
|
+
get("/subjects/#{@schema_context_prefix}#{CGI.escapeURIComponent(subject)}/versions", idempotent: true)
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def get(path, **options)
|
96
|
+
request(path, method: :get, **options)
|
97
|
+
end
|
98
|
+
|
99
|
+
def put(path, **options)
|
100
|
+
request(path, method: :put, **options)
|
101
|
+
end
|
102
|
+
|
103
|
+
def post(path, **options)
|
104
|
+
request(path, method: :post, **options)
|
105
|
+
end
|
106
|
+
|
107
|
+
def request(path, **options)
|
108
|
+
options = { expects: 200 }.merge!(options)
|
109
|
+
path = File.join(@path_prefix, path) unless @path_prefix.nil?
|
110
|
+
response = @connection.request(path: path, **options)
|
111
|
+
JSON.parse(response.body)
|
112
|
+
rescue Excon::Error => e
|
113
|
+
@logger.error("Error while requesting #{path}: #{e.response.body}")
|
114
|
+
raise
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
data/lib/proto_turf.rb
ADDED
@@ -0,0 +1,229 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'proto_turf/confluent_schema_registry'
|
3
|
+
require 'proto_turf/cached_confluent_schema_registry'
|
4
|
+
|
5
|
+
class ProtoTurf
|
6
|
+
# Provides a way to encode and decode messages without having to embed schemas
|
7
|
+
# in the encoded data. Confluent's Schema Registry[1] is used to register
|
8
|
+
# a schema when encoding a message -- the registry will issue a schema id that
|
9
|
+
# will be included in the encoded data alongside the actual message. When
|
10
|
+
# decoding the data, the schema id will be used to look up the writer's schema
|
11
|
+
# from the registry.
|
12
|
+
#
|
13
|
+
# 1: https://github.com/confluentinc/schema-registry
|
14
|
+
# https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/serdes-protobuf.html
|
15
|
+
# https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#wire-format
|
16
|
+
MAGIC_BYTE = [0].pack("C").freeze
|
17
|
+
|
18
|
+
|
19
|
+
# Instantiate a new ProtoTurf instance with the given configuration.
|
20
|
+
#
|
21
|
+
# registry - A schema registry object that responds to all methods in the
|
22
|
+
# ProtoTurf::ConfluentSchemaRegistry interface.
|
23
|
+
# registry_url - The String URL of the schema registry that should be used.
|
24
|
+
# schema_context - Schema registry context name (optional)
|
25
|
+
# schemas_path - The String file system path where local schemas are stored.
|
26
|
+
# registry_path_prefix - The String URL path prefix used to namespace schema registry requests (optional).
|
27
|
+
# logger - The Logger that should be used to log information (optional).
|
28
|
+
# proxy - Forward the request via proxy (optional).
|
29
|
+
# user - User for basic auth (optional).
|
30
|
+
# password - Password for basic auth (optional).
|
31
|
+
# ssl_ca_file - Name of file containing CA certificate (optional).
|
32
|
+
# client_cert - Name of file containing client certificate (optional).
|
33
|
+
# client_key - Name of file containing client private key to go with client_cert (optional).
|
34
|
+
# client_key_pass - Password to go with client_key (optional).
|
35
|
+
# client_cert_data - In-memory client certificate (optional).
|
36
|
+
# client_key_data - In-memory client private key to go with client_cert_data (optional).
|
37
|
+
# connect_timeout - Timeout to use in the connection with the schema registry (optional).
|
38
|
+
# resolv_resolver - Custom domain name resolver (optional).
|
39
|
+
def initialize(
|
40
|
+
registry: nil,
|
41
|
+
registry_url: nil,
|
42
|
+
schema_context: nil,
|
43
|
+
schemas_path: nil,
|
44
|
+
registry_path_prefix: nil,
|
45
|
+
logger: nil,
|
46
|
+
proxy: nil,
|
47
|
+
user: nil,
|
48
|
+
password: nil,
|
49
|
+
ssl_ca_file: nil,
|
50
|
+
client_cert: nil,
|
51
|
+
client_key: nil,
|
52
|
+
client_key_pass: nil,
|
53
|
+
client_cert_data: nil,
|
54
|
+
client_key_data: nil,
|
55
|
+
connect_timeout: nil,
|
56
|
+
resolv_resolver: nil,
|
57
|
+
retry_limit: nil
|
58
|
+
)
|
59
|
+
@logger = logger || Logger.new($stderr)
|
60
|
+
@path = schemas_path
|
61
|
+
@registry = registry || ProtoTurf::CachedConfluentSchemaRegistry.new(
|
62
|
+
ProtoTurf::ConfluentSchemaRegistry.new(
|
63
|
+
registry_url,
|
64
|
+
schema_context: schema_context,
|
65
|
+
logger: @logger,
|
66
|
+
proxy: proxy,
|
67
|
+
user: user,
|
68
|
+
password: password,
|
69
|
+
ssl_ca_file: ssl_ca_file,
|
70
|
+
client_cert: client_cert,
|
71
|
+
client_key: client_key,
|
72
|
+
client_key_pass: client_key_pass,
|
73
|
+
client_cert_data: client_cert_data,
|
74
|
+
client_key_data: client_key_data,
|
75
|
+
path_prefix: registry_path_prefix,
|
76
|
+
connect_timeout: connect_timeout,
|
77
|
+
resolv_resolver: resolv_resolver
|
78
|
+
)
|
79
|
+
)
|
80
|
+
@all_schemas = {}
|
81
|
+
end
|
82
|
+
|
83
|
+
# Encodes a message using the specified schema.
|
84
|
+
#
|
85
|
+
# message - The message that should be encoded. Must be compatible with
|
86
|
+
# the schema.
|
87
|
+
# subject - The subject name the schema should be registered under in
|
88
|
+
# the schema registry (optional).
|
89
|
+
# Returns the encoded data as a String.
|
90
|
+
def encode(message, subject: nil)
|
91
|
+
load_schemas! if @all_schemas.empty?
|
92
|
+
|
93
|
+
id = register_schema(message.class.descriptor.file_descriptor, subject: subject)
|
94
|
+
|
95
|
+
stream = StringIO.new
|
96
|
+
# Always start with the magic byte.
|
97
|
+
stream.write(MAGIC_BYTE)
|
98
|
+
|
99
|
+
# The schema id is encoded as a 4-byte big-endian integer.
|
100
|
+
stream.write([id].pack("N"))
|
101
|
+
|
102
|
+
# For now, we're only going to support a single message per schema. See
|
103
|
+
# https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#wire-format
|
104
|
+
write_int(stream, 0)
|
105
|
+
|
106
|
+
# Now we write the actual message.
|
107
|
+
stream.write(message.to_proto)
|
108
|
+
|
109
|
+
stream.string
|
110
|
+
rescue Excon::Error::NotFound
|
111
|
+
if schema_id
|
112
|
+
raise SchemaNotFoundError.new("Schema with id: #{schema_id} is not found on registry")
|
113
|
+
else
|
114
|
+
raise SchemaNotFoundError.new("Schema with subject: `#{subject}` version: `#{version}` is not found on registry")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Decodes data into the original message.
|
119
|
+
#
|
120
|
+
# data - A String containing encoded data.
|
121
|
+
#
|
122
|
+
# Returns a Protobuf AbstractMessage object instantiated with the decoded data.
|
123
|
+
def decode(data)
|
124
|
+
stream = StringIO.new(data)
|
125
|
+
|
126
|
+
# The first byte is MAGIC!!!
|
127
|
+
magic_byte = stream.read(1)
|
128
|
+
|
129
|
+
if magic_byte != MAGIC_BYTE
|
130
|
+
raise "Expected data to begin with a magic byte, got `#{magic_byte.inspect}`"
|
131
|
+
end
|
132
|
+
|
133
|
+
# The schema id is a 4-byte big-endian integer.
|
134
|
+
schema_id = stream.read(4).unpack("N").first
|
135
|
+
|
136
|
+
# For now, we're only going to support a single message per schema. See
|
137
|
+
# https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#wire-format
|
138
|
+
read_int(stream)
|
139
|
+
|
140
|
+
schema = @registry.fetch(schema_id)
|
141
|
+
encoded = stream.read
|
142
|
+
decode_protobuf(schema, encoded)
|
143
|
+
rescue Excon::Error::NotFound
|
144
|
+
raise SchemaNotFoundError.new("Schema with id: #{schema_id} is not found on registry")
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
# Write an int with zig-zag encoding. Copied from Avro.
|
150
|
+
def write_int(stream, n)
|
151
|
+
n = (n << 1) ^ (n >> 63)
|
152
|
+
while (n & ~0x7F) != 0
|
153
|
+
stream.write(((n & 0x7f) | 0x80).chr)
|
154
|
+
n >>= 7
|
155
|
+
end
|
156
|
+
stream.write(n.chr)
|
157
|
+
end
|
158
|
+
|
159
|
+
# Read an int with zig-zag encoding. Copied from Avro.
|
160
|
+
def read_int(stream)
|
161
|
+
b = stream.readbyte
|
162
|
+
n = b & 0x7F
|
163
|
+
shift = 7
|
164
|
+
while (b & 0x80) != 0
|
165
|
+
b = stream.readbyte
|
166
|
+
n |= (b & 0x7F) << shift
|
167
|
+
shift += 7
|
168
|
+
end
|
169
|
+
(n >> 1) ^ -(n & 1)
|
170
|
+
end
|
171
|
+
|
172
|
+
def decode_protobuf(schema, encoded)
|
173
|
+
# get the package
|
174
|
+
package = schema.match(/package (\S+);/)[1]
|
175
|
+
# get the first message in the protobuf text
|
176
|
+
# TODO - get the correct message based on schema index
|
177
|
+
message_name = schema.match(/message (\w+) {/)[1]
|
178
|
+
# look up the descriptor
|
179
|
+
full_name = "#{package}.#{message_name}"
|
180
|
+
descriptor = Google::Protobuf::DescriptorPool.generated_pool.lookup(full_name)
|
181
|
+
unless descriptor
|
182
|
+
raise "Could not find schema for #{full_name}. Make sure the corresponding .proto file has been compiled and loaded."
|
183
|
+
end
|
184
|
+
descriptor.msgclass.decode(encoded)
|
185
|
+
end
|
186
|
+
|
187
|
+
def register_schema(file_descriptor, subject: nil)
|
188
|
+
subject ||= file_descriptor.name
|
189
|
+
return if @registry.registered?(file_descriptor.name, subject)
|
190
|
+
|
191
|
+
# register dependencies first
|
192
|
+
dependencies = file_descriptor.to_proto.dependency.to_a.reject { |d| d.start_with?('google/protobuf/') }
|
193
|
+
versions = dependencies.map do |dependency|
|
194
|
+
dependency_descriptor = @all_schemas[dependency]
|
195
|
+
result = register_schema(dependency_descriptor, subject: dependency_descriptor.name)
|
196
|
+
@registry.fetch_version(result, dependency_descriptor.name)
|
197
|
+
end
|
198
|
+
|
199
|
+
@registry.register(subject,
|
200
|
+
schema_text(file_descriptor),
|
201
|
+
references: dependencies.map.with_index do |dependency, i|
|
202
|
+
{
|
203
|
+
name: dependency,
|
204
|
+
subject: dependency,
|
205
|
+
version: versions[i]
|
206
|
+
}
|
207
|
+
end
|
208
|
+
)
|
209
|
+
end
|
210
|
+
|
211
|
+
def schema_text(file_descriptor)
|
212
|
+
filename = "#{@path}/#{file_descriptor.name}"
|
213
|
+
File.exist?(filename) ? File.read(filename) : ""
|
214
|
+
end
|
215
|
+
|
216
|
+
def load_schemas!
|
217
|
+
all_messages = ObjectSpace.each_object(Class).select do |o|
|
218
|
+
o < Google::Protobuf.const_get(:AbstractMessage)
|
219
|
+
end.to_a
|
220
|
+
all_messages.each do |m|
|
221
|
+
file_desc = m.descriptor.file_descriptor
|
222
|
+
file_path = file_desc.name
|
223
|
+
next if file_path.start_with?('google/protobuf/') # skip built-in protos
|
224
|
+
|
225
|
+
@all_schemas[file_path] = file_desc
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
data/proto_turf.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'proto_turf/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "proto_turf"
|
8
|
+
spec.version = ProtoTurf::VERSION
|
9
|
+
spec.authors = ["Daniel Orner"]
|
10
|
+
spec.email = ["daniel.orner@flipp.com"]
|
11
|
+
spec.summary = "Support for Protobuf files in Confluent Schema Registry"
|
12
|
+
spec.homepage = "https://github.com/flipp-oss/proto_turf"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency "google-protobuf"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
25
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
26
|
+
spec.add_development_dependency "rspec", "~> 3.2"
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: proto_turf
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Daniel Orner
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-08-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: google-protobuf
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '13.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '13.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.2'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.2'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- daniel.orner@flipp.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- LICENSE
|
77
|
+
- README.md
|
78
|
+
- lib/proto_turf.rb
|
79
|
+
- lib/proto_turf/cached_confluent_schema_registry.rb
|
80
|
+
- lib/proto_turf/confluent_schema_registry.rb
|
81
|
+
- lib/proto_turf/version.rb
|
82
|
+
- proto_turf.gemspec
|
83
|
+
homepage: https://github.com/flipp-oss/proto_turf
|
84
|
+
licenses:
|
85
|
+
- MIT
|
86
|
+
metadata:
|
87
|
+
rubygems_mfa_required: 'true'
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
requirements: []
|
103
|
+
rubygems_version: 3.4.10
|
104
|
+
signing_key:
|
105
|
+
specification_version: 4
|
106
|
+
summary: Support for Protobuf files in Confluent Schema Registry
|
107
|
+
test_files: []
|