protocol-grpc 0.11.0 → 0.12.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
- checksums.yaml.gz.sig +0 -0
- data/context/index.yaml +2 -0
- data/lib/protocol/grpc/body/readable.rb +29 -24
- data/lib/protocol/grpc/body/writable.rb +15 -14
- data/lib/protocol/grpc/call.rb +19 -0
- data/lib/protocol/grpc/header/timeout.rb +40 -6
- data/lib/protocol/grpc/interface.rb +6 -0
- data/lib/protocol/grpc/metadata.rb +3 -32
- data/lib/protocol/grpc/methods.rb +12 -25
- data/lib/protocol/grpc/middleware.rb +1 -1
- data/lib/protocol/grpc/version.rb +1 -1
- data/readme.md +24 -3
- data/releases.md +5 -0
- data.tar.gz.sig +0 -0
- metadata +5 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 82a5d69076bd57b3e2fe9c3e8d46f2caf79874136d4577664240179aa39f0966
|
|
4
|
+
data.tar.gz: 1b46c0bde1016ebc61998c76592f64b97714b9b701d264c5a2dd4c64433b1745
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c7aa9a55156f31361fe0c8afc57f74b3c69760e39c14985ec999250c507b8f9cad650ac70435dda2b7620eb3557d6105126a6a5fb2ad045b5fb0f306f1aa572d
|
|
7
|
+
data.tar.gz: efe791eece6660faced232e8d1d9fc0a207ee5866b9905fa93cc6b78c1781c4d9f7c804d5083df76dffcc65b6798cd7e4f3fb07d185987ef8a99a7247f688b5f
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/context/index.yaml
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
---
|
|
4
4
|
description: Protocol abstractions for gRPC, built on top of protocol-http.
|
|
5
5
|
metadata:
|
|
6
|
+
bug_tracker_uri: https://github.com/socketry/protocol-grpc/issues
|
|
7
|
+
changelog_uri: https://github.com/socketry/protocol-grpc/blob/main/releases.md
|
|
6
8
|
documentation_uri: https://socketry.github.io/protocol-grpc/
|
|
7
9
|
source_code_uri: https://github.com/socketry/protocol-grpc.git
|
|
8
10
|
files:
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2025, by Samuel Williams.
|
|
4
|
+
# Copyright, 2025-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
6
|
require "protocol/http"
|
|
7
7
|
require "protocol/http/body/wrapper"
|
|
8
8
|
require "zlib"
|
|
9
9
|
|
|
10
|
+
require_relative "../error"
|
|
11
|
+
require_relative "../status"
|
|
12
|
+
|
|
10
13
|
module Protocol
|
|
11
14
|
module GRPC
|
|
12
15
|
# @namespace
|
|
@@ -47,8 +50,6 @@ module Protocol
|
|
|
47
50
|
# Overrides Wrapper#read to transform raw HTTP body chunks into decoded gRPC messages.
|
|
48
51
|
# @returns [Object | String | Nil] Decoded message, raw binary, or `Nil` if stream ended
|
|
49
52
|
def read
|
|
50
|
-
return nil if @body.nil? || @body.empty?
|
|
51
|
-
|
|
52
53
|
# Read 5-byte prefix: 1 byte compression flag + 4 bytes length
|
|
53
54
|
prefix = read_exactly(5)
|
|
54
55
|
return nil unless prefix
|
|
@@ -58,7 +59,9 @@ module Protocol
|
|
|
58
59
|
|
|
59
60
|
# Read the message body:
|
|
60
61
|
data = read_exactly(length)
|
|
61
|
-
|
|
62
|
+
unless data
|
|
63
|
+
raise Error.new(Status::INTERNAL, "Truncated gRPC frame: expected #{length} bytes, received 0")
|
|
64
|
+
end
|
|
62
65
|
|
|
63
66
|
# Decompress if needed:
|
|
64
67
|
data = decompress(data) if compressed
|
|
@@ -76,19 +79,25 @@ module Protocol
|
|
|
76
79
|
private
|
|
77
80
|
|
|
78
81
|
# Read exactly n bytes from the underlying body.
|
|
79
|
-
# @parameter n [Integer] The number of bytes to read
|
|
80
|
-
# @returns [String | Nil] The data read, or `Nil` if the stream ended
|
|
82
|
+
# @parameter n [Integer] The number of bytes to read.
|
|
83
|
+
# @returns [String | Nil] The data read, or `Nil` if the stream ended before reading any bytes.
|
|
84
|
+
# @raises [Error] If the stream ends after reading a partial value.
|
|
81
85
|
def read_exactly(n)
|
|
82
86
|
# Fill buffer until we have enough data:
|
|
83
87
|
while @buffer.bytesize < n
|
|
84
|
-
|
|
88
|
+
if @body.nil? || @body.empty?
|
|
89
|
+
return nil if @buffer.empty?
|
|
90
|
+
|
|
91
|
+
raise Error.new(Status::INTERNAL, "Truncated gRPC frame: expected #{n} bytes, received #{@buffer.bytesize}")
|
|
92
|
+
end
|
|
85
93
|
|
|
86
94
|
# Read chunk from underlying body:
|
|
87
95
|
chunk = @body.read
|
|
88
96
|
|
|
89
97
|
if chunk.nil?
|
|
90
|
-
|
|
91
|
-
|
|
98
|
+
return nil if @buffer.empty?
|
|
99
|
+
|
|
100
|
+
raise Error.new(Status::INTERNAL, "Truncated gRPC frame: expected #{n} bytes, received #{@buffer.bytesize}")
|
|
92
101
|
end
|
|
93
102
|
|
|
94
103
|
# Append to buffer:
|
|
@@ -108,24 +117,20 @@ module Protocol
|
|
|
108
117
|
def decompress(data)
|
|
109
118
|
case @encoding
|
|
110
119
|
when "gzip"
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
result
|
|
120
|
+
begin
|
|
121
|
+
Zlib.gunzip(data)
|
|
122
|
+
rescue => error
|
|
123
|
+
raise Error.new(Status::INTERNAL, "Failed to decompress message: #{error.message}")
|
|
124
|
+
end
|
|
117
125
|
when "deflate"
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
result
|
|
126
|
+
begin
|
|
127
|
+
Zlib::Inflate.inflate(data)
|
|
128
|
+
rescue => error
|
|
129
|
+
raise Error.new(Status::INTERNAL, "Failed to decompress message: #{error.message}")
|
|
130
|
+
end
|
|
124
131
|
else
|
|
125
|
-
|
|
132
|
+
raise Error.new(Status::UNIMPLEMENTED, "Unsupported compression encoding: #{@encoding.inspect}")
|
|
126
133
|
end
|
|
127
|
-
rescue StandardError => error
|
|
128
|
-
raise Error.new(Status::INTERNAL, "Failed to decompress message: #{error.message}")
|
|
129
134
|
end
|
|
130
135
|
end
|
|
131
136
|
end
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2025, by Samuel Williams.
|
|
4
|
+
# Copyright, 2025-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
6
|
require "protocol/http"
|
|
7
7
|
require "protocol/http/body/writable"
|
|
8
8
|
require "zlib"
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
require_relative "../error"
|
|
11
|
+
require_relative "../status"
|
|
10
12
|
|
|
11
13
|
module Protocol
|
|
12
14
|
module GRPC
|
|
@@ -86,21 +88,20 @@ module Protocol
|
|
|
86
88
|
def compress(data)
|
|
87
89
|
case @encoding
|
|
88
90
|
when "gzip"
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
io.string
|
|
91
|
+
begin
|
|
92
|
+
Zlib.gzip(data, level: @level)
|
|
93
|
+
rescue => error
|
|
94
|
+
raise Error.new(Status::INTERNAL, "Failed to compress message: #{error.message}")
|
|
95
|
+
end
|
|
95
96
|
when "deflate"
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
begin
|
|
98
|
+
Zlib::Deflate.deflate(data, @level)
|
|
99
|
+
rescue => error
|
|
100
|
+
raise Error.new(Status::INTERNAL, "Failed to compress message: #{error.message}")
|
|
101
|
+
end
|
|
99
102
|
else
|
|
100
|
-
|
|
103
|
+
raise Error.new(Status::INTERNAL, "Unsupported compression encoding: #{@encoding.inspect}")
|
|
101
104
|
end
|
|
102
|
-
rescue StandardError => error
|
|
103
|
-
raise Error.new(Status::INTERNAL, "Failed to compress message: #{error.message}")
|
|
104
105
|
end
|
|
105
106
|
end
|
|
106
107
|
end
|
data/lib/protocol/grpc/call.rb
CHANGED
|
@@ -10,6 +10,19 @@ module Protocol
|
|
|
10
10
|
module GRPC
|
|
11
11
|
# Represents context for a single RPC call.
|
|
12
12
|
class Call
|
|
13
|
+
# Create a new RPC call context for the given request and response.
|
|
14
|
+
# Automatically computes a deadline from the `grpc-timeout` request header, if present.
|
|
15
|
+
# @parameter request [Protocol::HTTP::Request] The HTTP request
|
|
16
|
+
# @parameter response [Protocol::HTTP::Response | Nil] The HTTP response
|
|
17
|
+
# @returns [Call] The new call context.
|
|
18
|
+
def self.for(request, response = nil)
|
|
19
|
+
if timeout = request.headers["grpc-timeout"]
|
|
20
|
+
deadline = Async::Deadline.start(timeout.to_seconds)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
return new(request, response, deadline: deadline)
|
|
24
|
+
end
|
|
25
|
+
|
|
13
26
|
# Initialize a new RPC call context.
|
|
14
27
|
# @parameter request [Protocol::HTTP::Request] The HTTP request
|
|
15
28
|
# @parameter response [Protocol::HTTP::Response | Nil] The HTTP response (for setting metadata and trailers)
|
|
@@ -36,6 +49,12 @@ module Protocol
|
|
|
36
49
|
@metadata ||= Methods.extract_metadata(@request.headers)
|
|
37
50
|
end
|
|
38
51
|
|
|
52
|
+
# Get the timeout requested by the client.
|
|
53
|
+
# @returns [Numeric | Nil] The original timeout in seconds, or `nil` if no timeout was specified.
|
|
54
|
+
def timeout
|
|
55
|
+
@request.headers["grpc-timeout"]&.to_seconds
|
|
56
|
+
end
|
|
57
|
+
|
|
39
58
|
# Check if the deadline has expired.
|
|
40
59
|
# @returns [Boolean] `true` if the deadline has expired, `false` otherwise
|
|
41
60
|
def deadline_exceeded?
|
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
4
|
# Copyright, 2026, by Samuel Williams.
|
|
5
5
|
|
|
6
|
-
require_relative "../methods"
|
|
7
|
-
|
|
8
6
|
module Protocol
|
|
9
7
|
module GRPC
|
|
10
8
|
module Header
|
|
@@ -14,6 +12,28 @@ module Protocol
|
|
|
14
12
|
# The format is: value + unit (H=hours, M=minutes, S=seconds, m=milliseconds, u=microseconds, n=nanoseconds).
|
|
15
13
|
# This header appears only in request headers, not in trailers.
|
|
16
14
|
class Timeout < String
|
|
15
|
+
# The wire format for a gRPC timeout value.
|
|
16
|
+
FORMAT = /\A(?<amount>[1-9]\d{0,7})(?<unit>[HMSmun])\z/
|
|
17
|
+
|
|
18
|
+
# Format a timeout duration for the `grpc-timeout` header.
|
|
19
|
+
# @parameter timeout [Numeric] The timeout duration in seconds.
|
|
20
|
+
# @returns [String] The formatted timeout.
|
|
21
|
+
def self.format(timeout)
|
|
22
|
+
if timeout >= 3600
|
|
23
|
+
"#{(timeout / 3600).to_i}H"
|
|
24
|
+
elsif timeout >= 60
|
|
25
|
+
"#{(timeout / 60).to_i}M"
|
|
26
|
+
elsif timeout >= 1
|
|
27
|
+
"#{timeout.to_i}S"
|
|
28
|
+
elsif timeout >= 0.001
|
|
29
|
+
"#{(timeout * 1000).to_i}m"
|
|
30
|
+
elsif timeout >= 0.000001
|
|
31
|
+
"#{(timeout * 1_000_000).to_i}u"
|
|
32
|
+
else
|
|
33
|
+
"#{(timeout * 1_000_000_000).to_i}n"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
17
37
|
# Parse a timeout from a header value.
|
|
18
38
|
#
|
|
19
39
|
# @parameter value [String] The header value to parse (e.g., "5S", "1000m").
|
|
@@ -24,13 +44,13 @@ module Protocol
|
|
|
24
44
|
|
|
25
45
|
# Coerce a value to a Timeout instance.
|
|
26
46
|
#
|
|
27
|
-
# If a Numeric is provided, it will be formatted as a gRPC timeout string using {
|
|
47
|
+
# If a Numeric is provided, it will be formatted as a gRPC timeout string using {format}.
|
|
28
48
|
#
|
|
29
49
|
# @parameter value [String | Numeric] The value to coerce.
|
|
30
50
|
# @returns [Timeout] A new Timeout instance.
|
|
31
51
|
def self.coerce(value)
|
|
32
52
|
if value.is_a?(Numeric)
|
|
33
|
-
return new(
|
|
53
|
+
return new(format(value))
|
|
34
54
|
else
|
|
35
55
|
return new(value.to_s)
|
|
36
56
|
end
|
|
@@ -45,9 +65,23 @@ module Protocol
|
|
|
45
65
|
|
|
46
66
|
# Parse the timeout value to seconds.
|
|
47
67
|
#
|
|
48
|
-
# @returns [Numeric
|
|
68
|
+
# @returns [Numeric] Timeout in seconds.
|
|
69
|
+
# @raises [ArgumentError] If the timeout value is invalid.
|
|
49
70
|
def to_seconds
|
|
50
|
-
|
|
71
|
+
unless match = FORMAT.match(self)
|
|
72
|
+
raise ArgumentError, "Invalid grpc-timeout: #{self.inspect}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
amount = match[:amount].to_i
|
|
76
|
+
|
|
77
|
+
case match[:unit]
|
|
78
|
+
when "H" then amount * 3600
|
|
79
|
+
when "M" then amount * 60
|
|
80
|
+
when "S" then amount
|
|
81
|
+
when "m" then amount / 1000.0
|
|
82
|
+
when "u" then amount / 1_000_000.0
|
|
83
|
+
when "n" then amount / 1_000_000_000.0
|
|
84
|
+
end
|
|
51
85
|
end
|
|
52
86
|
|
|
53
87
|
# Merge another timeout value (takes the new value, as timeout should only appear once)
|
|
@@ -25,6 +25,12 @@ module Protocol
|
|
|
25
25
|
class Interface
|
|
26
26
|
# RPC method definition
|
|
27
27
|
RPC = Struct.new(:name, :request_class, :response_class, :streaming, :method, keyword_init: true) do
|
|
28
|
+
# Initialize a new RPC method definition.
|
|
29
|
+
# @parameter name [Symbol] The RPC method name.
|
|
30
|
+
# @parameter request_class [Class | Streaming | Nil] The request message class.
|
|
31
|
+
# @parameter response_class [Class | Streaming | Nil] The response message class.
|
|
32
|
+
# @parameter streaming [Symbol] The streaming mode.
|
|
33
|
+
# @parameter method [Symbol | Nil] The Ruby method name.
|
|
28
34
|
def initialize(name:, request_class:, response_class:, streaming: :unary, method: nil)
|
|
29
35
|
super
|
|
30
36
|
end
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2025, by Samuel Williams.
|
|
4
|
+
# Copyright, 2025-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
|
-
require "uri"
|
|
7
6
|
require_relative "header"
|
|
8
7
|
require_relative "status"
|
|
9
8
|
|
|
@@ -12,7 +11,6 @@ module Protocol
|
|
|
12
11
|
# @namespace
|
|
13
12
|
module Metadata
|
|
14
13
|
# Extract gRPC status from headers.
|
|
15
|
-
# Convenience method that handles both Header::Status instances and raw values.
|
|
16
14
|
# Returns Status::UNKNOWN if status is not present.
|
|
17
15
|
#
|
|
18
16
|
# Note: In Protocol::HTTP::Headers, trailers are merged into the headers
|
|
@@ -29,31 +27,10 @@ module Protocol
|
|
|
29
27
|
status = headers["grpc-status"]
|
|
30
28
|
return Status::UNKNOWN unless status
|
|
31
29
|
|
|
32
|
-
|
|
33
|
-
status.to_i
|
|
34
|
-
else
|
|
35
|
-
# Fallback for when header policy isn't used
|
|
36
|
-
# Handle Array case (may occur with external clients)
|
|
37
|
-
status_value = if status.is_a?(Array)
|
|
38
|
-
# Flatten and take first non-nil value, recursively handle nested arrays
|
|
39
|
-
flattened = status.flatten.compact.first
|
|
40
|
-
# If still an array, take first element
|
|
41
|
-
flattened.is_a?(Array) ? flattened.first : flattened
|
|
42
|
-
else
|
|
43
|
-
status
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# Convert to string then integer to handle various types
|
|
47
|
-
# Handle case where status_value might still be an array somehow
|
|
48
|
-
if status_value.is_a?(Array)
|
|
49
|
-
status_value = status_value.first
|
|
50
|
-
end
|
|
51
|
-
status_value.to_s.to_i
|
|
52
|
-
end
|
|
30
|
+
return status.to_i
|
|
53
31
|
end
|
|
54
32
|
|
|
55
33
|
# Extract gRPC status message from headers.
|
|
56
|
-
# Convenience method that handles both Header::Message instances and raw values.
|
|
57
34
|
# Returns `Nil` if message is not present.
|
|
58
35
|
#
|
|
59
36
|
# @parameter headers [Protocol::HTTP::Headers]
|
|
@@ -66,13 +43,7 @@ module Protocol
|
|
|
66
43
|
message = headers["grpc-message"]
|
|
67
44
|
return nil unless message
|
|
68
45
|
|
|
69
|
-
|
|
70
|
-
message.decode
|
|
71
|
-
else
|
|
72
|
-
# Fallback for when header policy isn't used
|
|
73
|
-
message_value = message.is_a?(Array) ? message.first : message.to_s
|
|
74
|
-
URI.decode_www_form_component(message_value)
|
|
75
|
-
end
|
|
46
|
+
return message.decode
|
|
76
47
|
end
|
|
77
48
|
|
|
78
49
|
# Assign gRPC status, message, and optional backtrace to headers.
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
require "base64"
|
|
7
7
|
require "protocol/http"
|
|
8
8
|
|
|
9
|
+
require_relative "header/timeout"
|
|
10
|
+
|
|
9
11
|
module Protocol
|
|
10
12
|
module GRPC
|
|
11
13
|
# Provides utility methods for building and parsing gRPC-compatible HTTP requests.
|
|
@@ -83,40 +85,25 @@ module Protocol
|
|
|
83
85
|
# Format timeout for grpc-timeout header.
|
|
84
86
|
# @parameter timeout [Numeric] Timeout in seconds
|
|
85
87
|
# @returns [String] e.g., "1000m" for 1 second
|
|
88
|
+
# @deprecated Use {Protocol::GRPC::Header::Timeout.format} instead.
|
|
86
89
|
def self.format_timeout(timeout)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
elsif timeout >= 60
|
|
91
|
-
"#{(timeout / 60).to_i}M"
|
|
92
|
-
elsif timeout >= 1
|
|
93
|
-
"#{timeout.to_i}S"
|
|
94
|
-
elsif timeout >= 0.001
|
|
95
|
-
"#{(timeout * 1000).to_i}m"
|
|
96
|
-
elsif timeout >= 0.000001
|
|
97
|
-
"#{(timeout * 1_000_000).to_i}u"
|
|
98
|
-
else
|
|
99
|
-
"#{(timeout * 1_000_000_000).to_i}n"
|
|
100
|
-
end
|
|
90
|
+
Kernel.warn("`Protocol::GRPC::Methods.format_timeout` is deprecated; use `Protocol::GRPC::Header::Timeout.format` instead.", uplevel: 1, category: :deprecated) if $VERBOSE
|
|
91
|
+
|
|
92
|
+
Header::Timeout.format(timeout)
|
|
101
93
|
end
|
|
102
94
|
|
|
103
95
|
# Parse grpc-timeout header value.
|
|
104
96
|
# @parameter value [String] e.g., "1000m"
|
|
105
97
|
# @returns [Numeric | Nil] Timeout in seconds, or `Nil` if value is invalid
|
|
98
|
+
# @deprecated Use {Protocol::GRPC::Header::Timeout#to_seconds} instead.
|
|
106
99
|
def self.parse_timeout(value)
|
|
107
|
-
|
|
100
|
+
Kernel.warn("`Protocol::GRPC::Methods.parse_timeout` is deprecated; use `Protocol::GRPC::Header::Timeout#to_seconds` instead.", uplevel: 1, category: :deprecated) if $VERBOSE
|
|
108
101
|
|
|
109
|
-
|
|
110
|
-
unit = value[-1]
|
|
102
|
+
return nil unless value
|
|
111
103
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
when "S" then amount
|
|
116
|
-
when "m" then amount / 1000.0
|
|
117
|
-
when "u" then amount / 1_000_000.0
|
|
118
|
-
when "n" then amount / 1_000_000_000.0
|
|
119
|
-
end
|
|
104
|
+
Header::Timeout.parse(value).to_seconds
|
|
105
|
+
rescue ArgumentError
|
|
106
|
+
return nil
|
|
120
107
|
end
|
|
121
108
|
end
|
|
122
109
|
end
|
data/readme.md
CHANGED
|
@@ -28,6 +28,11 @@ Please see the [project documentation](https://socketry.github.io/protocol-grpc/
|
|
|
28
28
|
|
|
29
29
|
Please see the [project releases](https://socketry.github.io/protocol-grpc/releases/index) for all releases.
|
|
30
30
|
|
|
31
|
+
### v0.12.0
|
|
32
|
+
|
|
33
|
+
- Added `Protocol::GRPC::Call#timeout` to expose the client-supplied gRPC timeout in seconds.
|
|
34
|
+
- Added `Protocol::GRPC::Header::Timeout.format` and deprecated `Protocol::GRPC::Methods.format_timeout` and `Protocol::GRPC::Methods.parse_timeout`.
|
|
35
|
+
|
|
31
36
|
### v0.11.0
|
|
32
37
|
|
|
33
38
|
- Rename `add_status!` to `assign_status!` to better reflect its purpose of assigning status information to headers or trailers.
|
|
@@ -66,11 +71,27 @@ Please see the [project releases](https://socketry.github.io/protocol-grpc/relea
|
|
|
66
71
|
|
|
67
72
|
We welcome contributions to this project.
|
|
68
73
|
|
|
69
|
-
1. Fork
|
|
74
|
+
1. Fork the repository.
|
|
70
75
|
2. Create your feature branch (`git checkout -b my-new-feature`).
|
|
71
|
-
3. Commit your changes (`git commit -am 'Add some feature'`).
|
|
76
|
+
3. Commit your changes (`git commit -am 'Add some feature.'`).
|
|
72
77
|
4. Push to the branch (`git push origin my-new-feature`).
|
|
73
|
-
5. Create new
|
|
78
|
+
5. Create a new pull request.
|
|
79
|
+
|
|
80
|
+
### Running Tests
|
|
81
|
+
|
|
82
|
+
To run the test suite:
|
|
83
|
+
|
|
84
|
+
``` shell
|
|
85
|
+
bundle exec sus
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Making Releases
|
|
89
|
+
|
|
90
|
+
To make a new release:
|
|
91
|
+
|
|
92
|
+
``` shell
|
|
93
|
+
bundle exec bake gem:release:patch # or minor or major
|
|
94
|
+
```
|
|
74
95
|
|
|
75
96
|
### Developer Certificate of Origin
|
|
76
97
|
|
data/releases.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Releases
|
|
2
2
|
|
|
3
|
+
## v0.12.0
|
|
4
|
+
|
|
5
|
+
- Added `Protocol::GRPC::Call#timeout` to expose the client-supplied gRPC timeout in seconds.
|
|
6
|
+
- Added `Protocol::GRPC::Header::Timeout.format` and deprecated `Protocol::GRPC::Methods.format_timeout` and `Protocol::GRPC::Methods.parse_timeout`.
|
|
7
|
+
|
|
3
8
|
## v0.11.0
|
|
4
9
|
|
|
5
10
|
- Rename `add_status!` to `assign_status!` to better reflect its purpose of assigning status information to headers or trailers.
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: protocol-grpc
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.12.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samuel Williams
|
|
@@ -127,6 +127,8 @@ homepage: https://github.com/socketry/protocol-grpc
|
|
|
127
127
|
licenses:
|
|
128
128
|
- MIT
|
|
129
129
|
metadata:
|
|
130
|
+
bug_tracker_uri: https://github.com/socketry/protocol-grpc/issues
|
|
131
|
+
changelog_uri: https://github.com/socketry/protocol-grpc/blob/main/releases.md
|
|
130
132
|
documentation_uri: https://socketry.github.io/protocol-grpc/
|
|
131
133
|
source_code_uri: https://github.com/socketry/protocol-grpc.git
|
|
132
134
|
rdoc_options: []
|
|
@@ -136,14 +138,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
136
138
|
requirements:
|
|
137
139
|
- - ">="
|
|
138
140
|
- !ruby/object:Gem::Version
|
|
139
|
-
version: '3.
|
|
141
|
+
version: '3.3'
|
|
140
142
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
143
|
requirements:
|
|
142
144
|
- - ">="
|
|
143
145
|
- !ruby/object:Gem::Version
|
|
144
146
|
version: '0'
|
|
145
147
|
requirements: []
|
|
146
|
-
rubygems_version: 4.0.
|
|
148
|
+
rubygems_version: 4.0.10
|
|
147
149
|
specification_version: 4
|
|
148
150
|
summary: Protocol abstractions for gRPC, built on top of protocol-http.
|
|
149
151
|
test_files: []
|
metadata.gz.sig
CHANGED
|
Binary file
|