spikard 0.12.0 → 0.15.2
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/Steepfile +6 -0
- data/ext/spikard_rb/extconf.rb +1 -2
- data/ext/spikard_rb/{Cargo.lock → native/Cargo.lock} +897 -451
- data/ext/spikard_rb/native/Cargo.toml +24 -0
- data/ext/spikard_rb/src/lib.rs +5366 -3
- data/lib/spikard/native.rb +86 -0
- data/lib/spikard/version.rb +6 -1
- data/lib/spikard.rb +8 -45
- data/lib/spikard_rb.so +0 -0
- data/sig/types.rbs +427 -0
- metadata +14 -242
- data/LICENSE +0 -1
- data/README.md +0 -267
- data/ext/spikard_rb/Cargo.toml +0 -17
- data/lib/spikard/app.rb +0 -428
- data/lib/spikard/background.rb +0 -58
- data/lib/spikard/config.rb +0 -506
- data/lib/spikard/converters.rb +0 -13
- data/lib/spikard/grpc.rb +0 -182
- data/lib/spikard/handler_wrapper.rb +0 -113
- data/lib/spikard/provide.rb +0 -214
- data/lib/spikard/response.rb +0 -173
- data/lib/spikard/schema.rb +0 -243
- data/lib/spikard/sse.rb +0 -111
- data/lib/spikard/streaming_response.rb +0 -44
- data/lib/spikard/testing.rb +0 -432
- data/lib/spikard/upload_file.rb +0 -131
- data/lib/spikard/websocket.rb +0 -59
- data/sig/spikard.rbs +0 -719
- data/vendor/crates/spikard-bindings-shared/Cargo.toml +0 -80
- data/vendor/crates/spikard-bindings-shared/examples/config_extraction.rs +0 -132
- data/vendor/crates/spikard-bindings-shared/src/config_extractor.rs +0 -905
- data/vendor/crates/spikard-bindings-shared/src/conversion_traits.rs +0 -210
- data/vendor/crates/spikard-bindings-shared/src/di_traits.rs +0 -252
- data/vendor/crates/spikard-bindings-shared/src/error_response.rs +0 -404
- data/vendor/crates/spikard-bindings-shared/src/grpc_metadata.rs +0 -199
- data/vendor/crates/spikard-bindings-shared/src/handler_base.rs +0 -252
- data/vendor/crates/spikard-bindings-shared/src/json_conversion.rs +0 -829
- data/vendor/crates/spikard-bindings-shared/src/lazy_cache.rs +0 -587
- data/vendor/crates/spikard-bindings-shared/src/lib.rs +0 -33
- data/vendor/crates/spikard-bindings-shared/src/lifecycle_base.rs +0 -298
- data/vendor/crates/spikard-bindings-shared/src/lifecycle_executor.rs +0 -594
- data/vendor/crates/spikard-bindings-shared/src/response_builder.rs +0 -743
- data/vendor/crates/spikard-bindings-shared/src/response_interpreter.rs +0 -944
- data/vendor/crates/spikard-bindings-shared/src/test_client_base.rs +0 -260
- data/vendor/crates/spikard-bindings-shared/src/validation_helpers.rs +0 -369
- data/vendor/crates/spikard-bindings-shared/tests/config_extractor_behavior.rs +0 -192
- data/vendor/crates/spikard-bindings-shared/tests/error_response_edge_cases.rs +0 -383
- data/vendor/crates/spikard-bindings-shared/tests/full_coverage.rs +0 -459
- data/vendor/crates/spikard-bindings-shared/tests/handler_base_integration.rs +0 -280
- data/vendor/crates/spikard-bindings-shared/tests/integration_tests.rs +0 -669
- data/vendor/crates/spikard-core/Cargo.toml +0 -60
- data/vendor/crates/spikard-core/src/bindings/mod.rs +0 -3
- data/vendor/crates/spikard-core/src/bindings/response.rs +0 -130
- data/vendor/crates/spikard-core/src/debug.rs +0 -127
- data/vendor/crates/spikard-core/src/di/container.rs +0 -702
- data/vendor/crates/spikard-core/src/di/dependency.rs +0 -273
- data/vendor/crates/spikard-core/src/di/error.rs +0 -118
- data/vendor/crates/spikard-core/src/di/factory.rs +0 -538
- data/vendor/crates/spikard-core/src/di/graph.rs +0 -507
- data/vendor/crates/spikard-core/src/di/mod.rs +0 -192
- data/vendor/crates/spikard-core/src/di/resolved.rs +0 -428
- data/vendor/crates/spikard-core/src/di/value.rs +0 -282
- data/vendor/crates/spikard-core/src/errors.rs +0 -72
- data/vendor/crates/spikard-core/src/http.rs +0 -492
- data/vendor/crates/spikard-core/src/lib.rs +0 -29
- data/vendor/crates/spikard-core/src/lifecycle.rs +0 -1273
- data/vendor/crates/spikard-core/src/metadata.rs +0 -378
- data/vendor/crates/spikard-core/src/parameters.rs +0 -2546
- data/vendor/crates/spikard-core/src/problem.rs +0 -358
- data/vendor/crates/spikard-core/src/request_data.rs +0 -1146
- data/vendor/crates/spikard-core/src/router.rs +0 -530
- data/vendor/crates/spikard-core/src/schema_registry.rs +0 -197
- data/vendor/crates/spikard-core/src/type_hints.rs +0 -311
- data/vendor/crates/spikard-core/src/validation/error_mapper.rs +0 -710
- data/vendor/crates/spikard-core/src/validation/mod.rs +0 -470
- data/vendor/crates/spikard-core/tests/bindings_response_tests.rs +0 -136
- data/vendor/crates/spikard-core/tests/di_dependency_defaults.rs +0 -37
- data/vendor/crates/spikard-core/tests/error_mapper.rs +0 -761
- data/vendor/crates/spikard-core/tests/parameters_edge_cases.rs +0 -106
- data/vendor/crates/spikard-core/tests/parameters_full.rs +0 -701
- data/vendor/crates/spikard-core/tests/parameters_schema_and_formats.rs +0 -301
- data/vendor/crates/spikard-core/tests/request_data_roundtrip.rs +0 -67
- data/vendor/crates/spikard-core/tests/validation_coverage.rs +0 -250
- data/vendor/crates/spikard-core/tests/validation_error_paths.rs +0 -45
- data/vendor/crates/spikard-http/Cargo.toml +0 -87
- data/vendor/crates/spikard-http/examples/sse-notifications.rs +0 -148
- data/vendor/crates/spikard-http/examples/websocket-chat.rs +0 -92
- data/vendor/crates/spikard-http/src/auth.rs +0 -301
- data/vendor/crates/spikard-http/src/background.rs +0 -1860
- data/vendor/crates/spikard-http/src/bindings/mod.rs +0 -3
- data/vendor/crates/spikard-http/src/bindings/response.rs +0 -1
- data/vendor/crates/spikard-http/src/body_metadata.rs +0 -8
- data/vendor/crates/spikard-http/src/cors.rs +0 -1026
- data/vendor/crates/spikard-http/src/debug.rs +0 -128
- data/vendor/crates/spikard-http/src/di_handler.rs +0 -1672
- data/vendor/crates/spikard-http/src/grpc/framing.rs +0 -469
- data/vendor/crates/spikard-http/src/grpc/handler.rs +0 -1122
- data/vendor/crates/spikard-http/src/grpc/mod.rs +0 -434
- data/vendor/crates/spikard-http/src/grpc/service.rs +0 -622
- data/vendor/crates/spikard-http/src/grpc/streaming.rs +0 -319
- data/vendor/crates/spikard-http/src/handler_response.rs +0 -901
- data/vendor/crates/spikard-http/src/handler_trait.rs +0 -1015
- data/vendor/crates/spikard-http/src/handler_trait_tests.rs +0 -290
- data/vendor/crates/spikard-http/src/jsonrpc/http_handler.rs +0 -502
- data/vendor/crates/spikard-http/src/jsonrpc/method_registry.rs +0 -648
- data/vendor/crates/spikard-http/src/jsonrpc/mod.rs +0 -58
- data/vendor/crates/spikard-http/src/jsonrpc/protocol.rs +0 -1207
- data/vendor/crates/spikard-http/src/jsonrpc/router.rs +0 -2262
- data/vendor/crates/spikard-http/src/lib.rs +0 -548
- data/vendor/crates/spikard-http/src/lifecycle/adapter.rs +0 -230
- data/vendor/crates/spikard-http/src/lifecycle.rs +0 -1193
- data/vendor/crates/spikard-http/src/middleware/mod.rs +0 -560
- data/vendor/crates/spikard-http/src/middleware/multipart.rs +0 -912
- data/vendor/crates/spikard-http/src/middleware/urlencoded.rs +0 -513
- data/vendor/crates/spikard-http/src/middleware/validation.rs +0 -768
- data/vendor/crates/spikard-http/src/openapi/mod.rs +0 -309
- data/vendor/crates/spikard-http/src/openapi/parameter_extraction.rs +0 -535
- data/vendor/crates/spikard-http/src/openapi/schema_conversion.rs +0 -1363
- data/vendor/crates/spikard-http/src/openapi/spec_generation.rs +0 -667
- data/vendor/crates/spikard-http/src/query_parser.rs +0 -793
- data/vendor/crates/spikard-http/src/response.rs +0 -720
- data/vendor/crates/spikard-http/src/server/fast_router.rs +0 -186
- data/vendor/crates/spikard-http/src/server/grpc_routing.rs +0 -858
- data/vendor/crates/spikard-http/src/server/handler.rs +0 -1661
- data/vendor/crates/spikard-http/src/server/lifecycle_execution.rs +0 -253
- data/vendor/crates/spikard-http/src/server/mod.rs +0 -1649
- data/vendor/crates/spikard-http/src/server/request_extraction.rs +0 -871
- data/vendor/crates/spikard-http/src/server/routing_factory.rs +0 -618
- data/vendor/crates/spikard-http/src/sse.rs +0 -1409
- data/vendor/crates/spikard-http/src/testing/form.rs +0 -52
- data/vendor/crates/spikard-http/src/testing/multipart.rs +0 -64
- data/vendor/crates/spikard-http/src/testing/test_client.rs +0 -787
- data/vendor/crates/spikard-http/src/testing.rs +0 -617
- data/vendor/crates/spikard-http/src/websocket.rs +0 -1477
- data/vendor/crates/spikard-http/tests/auth_integration.rs +0 -645
- data/vendor/crates/spikard-http/tests/background_behavior.rs +0 -832
- data/vendor/crates/spikard-http/tests/common/grpc_helpers.rs +0 -1012
- data/vendor/crates/spikard-http/tests/common/handlers.rs +0 -309
- data/vendor/crates/spikard-http/tests/common/mod.rs +0 -33
- data/vendor/crates/spikard-http/tests/common/test_builders.rs +0 -628
- data/vendor/crates/spikard-http/tests/di_handler_error_responses.rs +0 -162
- data/vendor/crates/spikard-http/tests/di_integration.rs +0 -192
- data/vendor/crates/spikard-http/tests/doc_snippets.rs +0 -5
- data/vendor/crates/spikard-http/tests/grpc_bidirectional_streaming.rs +0 -430
- data/vendor/crates/spikard-http/tests/grpc_client_streaming.rs +0 -738
- data/vendor/crates/spikard-http/tests/grpc_error_handling_test.rs +0 -652
- data/vendor/crates/spikard-http/tests/grpc_integration_test.rs +0 -334
- data/vendor/crates/spikard-http/tests/grpc_metadata_test.rs +0 -532
- data/vendor/crates/spikard-http/tests/grpc_server_integration.rs +0 -495
- data/vendor/crates/spikard-http/tests/grpc_server_streaming.rs +0 -974
- data/vendor/crates/spikard-http/tests/lifecycle_execution.rs +0 -1093
- data/vendor/crates/spikard-http/tests/middleware_stack_integration.rs +0 -389
- data/vendor/crates/spikard-http/tests/multipart_behavior.rs +0 -656
- data/vendor/crates/spikard-http/tests/request_extraction_full.rs +0 -513
- data/vendor/crates/spikard-http/tests/server_auth_middleware_behavior.rs +0 -328
- data/vendor/crates/spikard-http/tests/server_config_builder.rs +0 -314
- data/vendor/crates/spikard-http/tests/server_configured_router_behavior.rs +0 -200
- data/vendor/crates/spikard-http/tests/server_cors_preflight.rs +0 -83
- data/vendor/crates/spikard-http/tests/server_handler_wrappers.rs +0 -464
- data/vendor/crates/spikard-http/tests/server_method_router_additional_behavior.rs +0 -286
- data/vendor/crates/spikard-http/tests/server_method_router_coverage.rs +0 -118
- data/vendor/crates/spikard-http/tests/server_middleware_behavior.rs +0 -99
- data/vendor/crates/spikard-http/tests/server_middleware_branches.rs +0 -204
- data/vendor/crates/spikard-http/tests/server_openapi_jsonrpc_static.rs +0 -421
- data/vendor/crates/spikard-http/tests/server_router_behavior.rs +0 -121
- data/vendor/crates/spikard-http/tests/sse_behavior.rs +0 -620
- data/vendor/crates/spikard-http/tests/sse_full_behavior.rs +0 -584
- data/vendor/crates/spikard-http/tests/sse_handler_behavior.rs +0 -130
- data/vendor/crates/spikard-http/tests/test_client_requests.rs +0 -167
- data/vendor/crates/spikard-http/tests/testing_helpers.rs +0 -87
- data/vendor/crates/spikard-http/tests/testing_module_coverage.rs +0 -155
- data/vendor/crates/spikard-http/tests/urlencoded_content_type.rs +0 -82
- data/vendor/crates/spikard-http/tests/websocket_behavior.rs +0 -663
- data/vendor/crates/spikard-http/tests/websocket_full_behavior.rs +0 -440
- data/vendor/crates/spikard-http/tests/websocket_integration.rs +0 -150
- data/vendor/crates/spikard-rb/Cargo.toml +0 -68
- data/vendor/crates/spikard-rb/build.rs +0 -200
- data/vendor/crates/spikard-rb/src/background.rs +0 -63
- data/vendor/crates/spikard-rb/src/config/mod.rs +0 -5
- data/vendor/crates/spikard-rb/src/config/server_config.rs +0 -401
- data/vendor/crates/spikard-rb/src/conversion.rs +0 -688
- data/vendor/crates/spikard-rb/src/di/builder.rs +0 -100
- data/vendor/crates/spikard-rb/src/di/mod.rs +0 -375
- data/vendor/crates/spikard-rb/src/grpc/handler.rs +0 -834
- data/vendor/crates/spikard-rb/src/grpc/mod.rs +0 -13
- data/vendor/crates/spikard-rb/src/gvl.rs +0 -80
- data/vendor/crates/spikard-rb/src/handler.rs +0 -699
- data/vendor/crates/spikard-rb/src/integration/mod.rs +0 -3
- data/vendor/crates/spikard-rb/src/lib.rs +0 -2264
- data/vendor/crates/spikard-rb/src/lifecycle.rs +0 -303
- data/vendor/crates/spikard-rb/src/metadata/mod.rs +0 -5
- data/vendor/crates/spikard-rb/src/metadata/route_extraction.rs +0 -507
- data/vendor/crates/spikard-rb/src/request.rs +0 -439
- data/vendor/crates/spikard-rb/src/runtime/mod.rs +0 -5
- data/vendor/crates/spikard-rb/src/runtime/server_runner.rs +0 -344
- data/vendor/crates/spikard-rb/src/server.rs +0 -307
- data/vendor/crates/spikard-rb/src/sse.rs +0 -231
- data/vendor/crates/spikard-rb/src/testing/client.rs +0 -698
- data/vendor/crates/spikard-rb/src/testing/mod.rs +0 -7
- data/vendor/crates/spikard-rb/src/testing/sse.rs +0 -108
- data/vendor/crates/spikard-rb/src/testing/websocket.rs +0 -573
- data/vendor/crates/spikard-rb/src/websocket.rs +0 -475
- data/vendor/crates/spikard-rb-macros/Cargo.toml +0 -25
- data/vendor/crates/spikard-rb-macros/src/lib.rs +0 -51
|
@@ -1,319 +0,0 @@
|
|
|
1
|
-
//! Streaming support utilities for gRPC
|
|
2
|
-
//!
|
|
3
|
-
//! This module provides utilities for handling streaming RPCs:
|
|
4
|
-
//! - Client streaming (receiving stream of messages)
|
|
5
|
-
//! - Server streaming (sending stream of messages)
|
|
6
|
-
//! - Bidirectional streaming (both directions)
|
|
7
|
-
|
|
8
|
-
use bytes::Bytes;
|
|
9
|
-
use futures_util::Stream;
|
|
10
|
-
use std::pin::Pin;
|
|
11
|
-
use tonic::Status;
|
|
12
|
-
|
|
13
|
-
/// Type alias for a stream of protobuf message bytes
|
|
14
|
-
///
|
|
15
|
-
/// Used for both client streaming (incoming) and server streaming (outgoing).
|
|
16
|
-
/// Each item in the stream is either:
|
|
17
|
-
/// - Ok(Bytes): A serialized protobuf message
|
|
18
|
-
/// - Err(Status): A gRPC error
|
|
19
|
-
///
|
|
20
|
-
/// # Backpressure Considerations
|
|
21
|
-
///
|
|
22
|
-
/// Streaming responses should implement backpressure handling to avoid memory buildup with slow clients:
|
|
23
|
-
///
|
|
24
|
-
/// - **Problem**: If a client reads slowly but the handler produces messages quickly, messages will
|
|
25
|
-
/// queue in memory, potentially causing high memory usage or OOM errors.
|
|
26
|
-
/// - **Solution**: The gRPC layer (Tonic) handles backpressure automatically via the underlying TCP/HTTP/2
|
|
27
|
-
/// connection. However, handlers should be aware of this behavior.
|
|
28
|
-
/// - **Best Practice**: For long-running or high-volume streams, implement rate limiting or flow control
|
|
29
|
-
/// in the handler to avoid overwhelming the network buffer.
|
|
30
|
-
///
|
|
31
|
-
/// # Example: Rate-limited streaming
|
|
32
|
-
///
|
|
33
|
-
/// ```ignore
|
|
34
|
-
/// use spikard_http::grpc::streaming::MessageStream;
|
|
35
|
-
/// use bytes::Bytes;
|
|
36
|
-
/// use std::pin::Pin;
|
|
37
|
-
/// use std::time::Duration;
|
|
38
|
-
/// use tokio::time::sleep;
|
|
39
|
-
/// use futures_util::stream::{self, StreamExt};
|
|
40
|
-
///
|
|
41
|
-
/// // Handler that sends 1000 messages with rate limiting
|
|
42
|
-
/// fn create_rate_limited_stream() -> MessageStream {
|
|
43
|
-
/// let messages = (0..1000).map(|i| {
|
|
44
|
-
/// Ok(Bytes::from(format!("message_{}", i)))
|
|
45
|
-
/// });
|
|
46
|
-
///
|
|
47
|
-
/// // Stream with delay between messages to avoid overwhelming the client
|
|
48
|
-
/// let stream = stream::iter(messages)
|
|
49
|
-
/// .then(|msg| async {
|
|
50
|
-
/// sleep(Duration::from_millis(1)).await; // 1ms between messages
|
|
51
|
-
/// msg
|
|
52
|
-
/// });
|
|
53
|
-
///
|
|
54
|
-
/// Box::pin(stream)
|
|
55
|
-
/// }
|
|
56
|
-
/// ```
|
|
57
|
-
///
|
|
58
|
-
/// # Memory Management
|
|
59
|
-
///
|
|
60
|
-
/// Keep the following in mind when implementing large streams:
|
|
61
|
-
///
|
|
62
|
-
/// - Messages are buffered in the gRPC transport layer's internal queue
|
|
63
|
-
/// - Slow clients will cause the queue to grow, increasing memory usage
|
|
64
|
-
/// - Very large individual messages may cause buffer allocation spikes
|
|
65
|
-
/// - Consider implementing stream chunking for very large responses (split one large message into many small ones)
|
|
66
|
-
pub type MessageStream = Pin<Box<dyn Stream<Item = Result<Bytes, Status>> + Send>>;
|
|
67
|
-
|
|
68
|
-
/// Request for client streaming RPC
|
|
69
|
-
///
|
|
70
|
-
/// Contains metadata and a stream of incoming messages from the client.
|
|
71
|
-
pub struct StreamingRequest {
|
|
72
|
-
/// Service name
|
|
73
|
-
pub service_name: String,
|
|
74
|
-
/// Method name
|
|
75
|
-
pub method_name: String,
|
|
76
|
-
/// Stream of incoming protobuf messages
|
|
77
|
-
pub message_stream: MessageStream,
|
|
78
|
-
/// Request metadata
|
|
79
|
-
pub metadata: tonic::metadata::MetadataMap,
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/// Response for server streaming RPC
|
|
83
|
-
///
|
|
84
|
-
/// Contains metadata, a stream of outgoing messages, and optional trailers.
|
|
85
|
-
/// Trailers are metadata sent after the stream completes (after all messages).
|
|
86
|
-
pub struct StreamingResponse {
|
|
87
|
-
/// Stream of outgoing protobuf messages
|
|
88
|
-
pub message_stream: MessageStream,
|
|
89
|
-
/// Response metadata (sent before messages)
|
|
90
|
-
pub metadata: tonic::metadata::MetadataMap,
|
|
91
|
-
/// Optional trailers (sent after stream completes)
|
|
92
|
-
///
|
|
93
|
-
/// Trailers are useful for sending status information or metrics
|
|
94
|
-
/// after all messages have been sent.
|
|
95
|
-
pub trailers: Option<tonic::metadata::MetadataMap>,
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/// Helper to create a message stream from a vector of bytes
|
|
99
|
-
///
|
|
100
|
-
/// Useful for testing and for handlers that want to create a stream
|
|
101
|
-
/// from a fixed set of messages.
|
|
102
|
-
///
|
|
103
|
-
/// # Example
|
|
104
|
-
///
|
|
105
|
-
/// ```ignore
|
|
106
|
-
/// use spikard_http::grpc::streaming::message_stream_from_vec;
|
|
107
|
-
/// use bytes::Bytes;
|
|
108
|
-
///
|
|
109
|
-
/// let messages = vec![
|
|
110
|
-
/// Bytes::from("message1"),
|
|
111
|
-
/// Bytes::from("message2"),
|
|
112
|
-
/// ];
|
|
113
|
-
///
|
|
114
|
-
/// let stream = message_stream_from_vec(messages);
|
|
115
|
-
/// ```
|
|
116
|
-
pub fn message_stream_from_vec(messages: Vec<Bytes>) -> MessageStream {
|
|
117
|
-
Box::pin(futures_util::stream::iter(messages.into_iter().map(Ok)))
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/// Helper to create an empty message stream
|
|
121
|
-
///
|
|
122
|
-
/// Useful for testing or for handlers that need to return an empty stream.
|
|
123
|
-
pub fn empty_message_stream() -> MessageStream {
|
|
124
|
-
Box::pin(futures_util::stream::empty())
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/// Helper to create a single-message stream
|
|
128
|
-
///
|
|
129
|
-
/// Useful for converting unary responses to streaming responses.
|
|
130
|
-
///
|
|
131
|
-
/// # Example
|
|
132
|
-
///
|
|
133
|
-
/// ```ignore
|
|
134
|
-
/// use spikard_http::grpc::streaming::single_message_stream;
|
|
135
|
-
/// use bytes::Bytes;
|
|
136
|
-
///
|
|
137
|
-
/// let stream = single_message_stream(Bytes::from("response"));
|
|
138
|
-
/// ```
|
|
139
|
-
pub fn single_message_stream(message: Bytes) -> MessageStream {
|
|
140
|
-
Box::pin(futures_util::stream::once(async move { Ok(message) }))
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/// Helper to create an error stream
|
|
144
|
-
///
|
|
145
|
-
/// Returns a stream that immediately yields a gRPC error.
|
|
146
|
-
///
|
|
147
|
-
/// # Example
|
|
148
|
-
///
|
|
149
|
-
/// ```ignore
|
|
150
|
-
/// use spikard_http::grpc::streaming::error_stream;
|
|
151
|
-
/// use tonic::Status;
|
|
152
|
-
///
|
|
153
|
-
/// let stream = error_stream(Status::internal("Something went wrong"));
|
|
154
|
-
/// ```
|
|
155
|
-
pub fn error_stream(status: Status) -> MessageStream {
|
|
156
|
-
Box::pin(futures_util::stream::once(async move { Err(status) }))
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/// Helper to convert a Tonic ReceiverStream to our MessageStream
|
|
160
|
-
///
|
|
161
|
-
/// This is used in the service bridge to convert Tonic's streaming types
|
|
162
|
-
/// to our internal representation.
|
|
163
|
-
pub fn from_tonic_stream<S>(stream: S) -> MessageStream
|
|
164
|
-
where
|
|
165
|
-
S: Stream<Item = Result<Bytes, Status>> + Send + 'static,
|
|
166
|
-
{
|
|
167
|
-
Box::pin(stream)
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
#[cfg(test)]
|
|
171
|
-
mod tests {
|
|
172
|
-
use super::*;
|
|
173
|
-
use futures_util::StreamExt;
|
|
174
|
-
|
|
175
|
-
#[tokio::test]
|
|
176
|
-
async fn test_message_stream_from_vec() {
|
|
177
|
-
let messages = vec![Bytes::from("msg1"), Bytes::from("msg2"), Bytes::from("msg3")];
|
|
178
|
-
|
|
179
|
-
let mut stream = message_stream_from_vec(messages.clone());
|
|
180
|
-
|
|
181
|
-
let msg1 = stream.next().await.unwrap().unwrap();
|
|
182
|
-
assert_eq!(msg1, Bytes::from("msg1"));
|
|
183
|
-
|
|
184
|
-
let msg2 = stream.next().await.unwrap().unwrap();
|
|
185
|
-
assert_eq!(msg2, Bytes::from("msg2"));
|
|
186
|
-
|
|
187
|
-
let msg3 = stream.next().await.unwrap().unwrap();
|
|
188
|
-
assert_eq!(msg3, Bytes::from("msg3"));
|
|
189
|
-
|
|
190
|
-
assert!(stream.next().await.is_none());
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
#[tokio::test]
|
|
194
|
-
async fn test_empty_message_stream() {
|
|
195
|
-
let mut stream = empty_message_stream();
|
|
196
|
-
assert!(stream.next().await.is_none());
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
#[tokio::test]
|
|
200
|
-
async fn test_single_message_stream() {
|
|
201
|
-
let mut stream = single_message_stream(Bytes::from("single"));
|
|
202
|
-
|
|
203
|
-
let msg = stream.next().await.unwrap().unwrap();
|
|
204
|
-
assert_eq!(msg, Bytes::from("single"));
|
|
205
|
-
|
|
206
|
-
assert!(stream.next().await.is_none());
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
#[tokio::test]
|
|
210
|
-
async fn test_error_stream() {
|
|
211
|
-
let mut stream = error_stream(Status::internal("test error"));
|
|
212
|
-
|
|
213
|
-
let result = stream.next().await.unwrap();
|
|
214
|
-
assert!(result.is_err());
|
|
215
|
-
|
|
216
|
-
let error = result.unwrap_err();
|
|
217
|
-
assert_eq!(error.code(), tonic::Code::Internal);
|
|
218
|
-
assert_eq!(error.message(), "test error");
|
|
219
|
-
|
|
220
|
-
assert!(stream.next().await.is_none());
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
#[tokio::test]
|
|
224
|
-
async fn test_message_stream_from_vec_empty() {
|
|
225
|
-
let messages: Vec<Bytes> = vec![];
|
|
226
|
-
let mut stream = message_stream_from_vec(messages);
|
|
227
|
-
assert!(stream.next().await.is_none());
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
#[tokio::test]
|
|
231
|
-
async fn test_message_stream_from_vec_large() {
|
|
232
|
-
let mut messages = vec![];
|
|
233
|
-
for i in 0..100 {
|
|
234
|
-
messages.push(Bytes::from(format!("message{}", i)));
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
let mut stream = message_stream_from_vec(messages);
|
|
238
|
-
|
|
239
|
-
for i in 0..100 {
|
|
240
|
-
let msg = stream.next().await.unwrap().unwrap();
|
|
241
|
-
assert_eq!(msg, Bytes::from(format!("message{}", i)));
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
assert!(stream.next().await.is_none());
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
#[tokio::test]
|
|
248
|
-
async fn test_from_tonic_stream() {
|
|
249
|
-
let messages = vec![
|
|
250
|
-
Ok(Bytes::from("a")),
|
|
251
|
-
Ok(Bytes::from("b")),
|
|
252
|
-
Err(Status::cancelled("done")),
|
|
253
|
-
];
|
|
254
|
-
|
|
255
|
-
let tonic_stream = futures_util::stream::iter(messages);
|
|
256
|
-
let mut stream = from_tonic_stream(tonic_stream);
|
|
257
|
-
|
|
258
|
-
let msg1 = stream.next().await.unwrap().unwrap();
|
|
259
|
-
assert_eq!(msg1, Bytes::from("a"));
|
|
260
|
-
|
|
261
|
-
let msg2 = stream.next().await.unwrap().unwrap();
|
|
262
|
-
assert_eq!(msg2, Bytes::from("b"));
|
|
263
|
-
|
|
264
|
-
let result = stream.next().await.unwrap();
|
|
265
|
-
assert!(result.is_err());
|
|
266
|
-
|
|
267
|
-
assert!(stream.next().await.is_none());
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
#[test]
|
|
271
|
-
fn test_streaming_request_creation() {
|
|
272
|
-
let stream = empty_message_stream();
|
|
273
|
-
let request = StreamingRequest {
|
|
274
|
-
service_name: "test.Service".to_string(),
|
|
275
|
-
method_name: "StreamMethod".to_string(),
|
|
276
|
-
message_stream: stream,
|
|
277
|
-
metadata: tonic::metadata::MetadataMap::new(),
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
assert_eq!(request.service_name, "test.Service");
|
|
281
|
-
assert_eq!(request.method_name, "StreamMethod");
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
#[test]
|
|
285
|
-
fn test_streaming_response_creation() {
|
|
286
|
-
let stream = empty_message_stream();
|
|
287
|
-
let response = StreamingResponse {
|
|
288
|
-
message_stream: stream,
|
|
289
|
-
metadata: tonic::metadata::MetadataMap::new(),
|
|
290
|
-
trailers: None,
|
|
291
|
-
};
|
|
292
|
-
|
|
293
|
-
assert!(response.metadata.is_empty());
|
|
294
|
-
assert!(response.trailers.is_none());
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
#[test]
|
|
298
|
-
fn test_streaming_response_with_trailers() {
|
|
299
|
-
let stream = empty_message_stream();
|
|
300
|
-
let mut trailers = tonic::metadata::MetadataMap::new();
|
|
301
|
-
trailers.insert(
|
|
302
|
-
"x-request-id",
|
|
303
|
-
"test-123"
|
|
304
|
-
.parse::<tonic::metadata::MetadataValue<tonic::metadata::Ascii>>()
|
|
305
|
-
.unwrap(),
|
|
306
|
-
);
|
|
307
|
-
|
|
308
|
-
let response = StreamingResponse {
|
|
309
|
-
message_stream: stream,
|
|
310
|
-
metadata: tonic::metadata::MetadataMap::new(),
|
|
311
|
-
trailers: Some(trailers),
|
|
312
|
-
};
|
|
313
|
-
|
|
314
|
-
assert!(response.metadata.is_empty());
|
|
315
|
-
assert!(response.trailers.is_some());
|
|
316
|
-
let trailers = response.trailers.unwrap();
|
|
317
|
-
assert_eq!(trailers.len(), 1);
|
|
318
|
-
}
|
|
319
|
-
}
|