rpc_dart 3.2.0
rpc_dart: ^3.2.0 copied to clipboard
Transport-agnostic RPC framework with contracts, streaming and included transports.
3.2.0 #
Built-in logging system:
- New
LogController/LogScopearchitecture replaces oldRpcLogger - Pipeline: level filter -> sampling -> enrichers -> redaction -> outputs
LogScope.noopfor zero-cost disable when no logger configuredsealed LogRecordwith three types:LogSpanStart,LogEvent,LogSpan- Endpoints accept
LogController? loggerparameter
Spans (operations with duration):
withSpan()/startSpan()API for measuring operation timing- Spans bypass level filter (telemetry, not logs) — available in production even with
minLevel = fatal spansEnabledflag for opt-out- Span ID (6 hex chars) links events to their span in console output
Console output (logfmt-style):
- One line per record, structured key=value fields
- Three formats:
pretty(colored),json,compact - traceId shown automatically when present
- Span start (
>>), events, and span end with duration on separate lines
Responder auto-logging:
context.login responder handlers auto-configured with scope, traceId, requestId- Scope includes service and method name:
rpc.{endpoint}.{Service}.{method} - Works for all stream types (unary, server, client, bidirectional)
Production features:
SamplingConfig— per-level rate limitingLogEnricher— auto-attach fields (host, pid, etc.) to every recordLogRedactor— strip sensitive fields (password, token) from dataRingBufferOutput— in-memory history, queryable byLogFilter
RPC log transport:
RpcLogOutput— send logs to remote peer with offline bufferRpcLogResponder— accept remote logs into local controllerRpcLogServiceResponder— expose subscribe stream + history + remote controlRpcLogServiceCaller— client API for remote diagnostics
Breaking:
- Removed
RpcLogger,RpcLoggerColors,AnsiColor,RpcLoggerLevel,RpcContextAwareLogger,RpcContextualLogging - Removed extension methods:
logRpcError,logRpcWarning,logStreamBound,logStreamFinished,logMessageReceived - Endpoint constructors:
loggerColorsparameter removed,loggerparameter now takesLogController?
3.1.1 #
Bug fix:
- Fixed
Uint8ListCBOR encoding on dart2js: addedTypedDatafallback in_FastCborWriterand_encodeValueto ensure typed byte arrays are always encoded as CBOR byte strings (major type 2), not integer arrays (major type 4). Without this fix, blob uploads from dart2js clients produced ~1.9x inflated byte counts on the server, causing "declared length does not match received bytes" errors.
3.1.0 #
Structured error model:
RpcStatusExceptionnow carries typeddetailslist — structured error information sent viagrpc-status-details-bintrailer (wire-compatible with standard gRPCgoogle.rpc.Status).- Added
RpcErrorDetailhierarchy:RpcBadRequest(field violations),RpcRetryInfo(retry delay),RpcDebugInfo(stack traces),RpcErrorInfo(reason/domain/metadata),RpcRawErrorDetail(unknown types passthrough). RpcStatusException.fromTrailer()factory reconstructs typed exceptions from wire data on the caller side.- All four caller patterns (unary, server-stream, client-stream, bidirectional) now throw
RpcStatusExceptioninstead of genericExceptionon gRPC errors. - All responder patterns forward
statusDetailsBinin error trailers when handler throwsRpcStatusExceptionwith details. - Minimal protobuf encoding/decoding for
google.rpc.Statusandgoogle.protobuf.Any— no external protobuf dependency.
Graceful drain:
- Added
RpcResponderEndpoint.drain({Duration timeout})— initiates graceful shutdown: rejects new streams withUNAVAILABLE, cancels active stream contexts via cancellation token, waits for completion. - Responder pipeline now attaches
RpcCancellationTokento all incoming stream contexts automatically — handlers can listen for cancellation during shutdown. RpcApp._drainEndpoints()(framework) now callsendpoint.drain()in parallel instead of polling.
Other:
- Added
RpcPeerContract— base class for bidirectional contracts where either side can initiate calls. ExtendsRpcResponderContractand exposescallUnary,callServerStream,callClientStream,callBidirectionalStreammethods bound to the sameRpcPeerEndpoint. RpcPeerEndpointis now exported from the library public API.RpcServiceKindenum added toannotations.dart(unidirectional/peer) for use with@RpcService(kind: ...).@RpcServicegainedgrpcDescriptorflag (defaultfalse) — whentrue, the generator emits agrpcDescriptorstatic field for gRPC Server Reflection registration.RpcContextUtils.generateTraceId()is now public (was_generateTraceId).RpcResponderContract.serviceNamesupports dynamic suffix viaserviceNameSuffixsetter — used for scoped/isolated service registrations.- Internal refactor:
caller_pipeline.dartandresponder_pipeline.dartextracted as separate part files; logic unchanged.
3.0.1 #
RpcMessageParser: replacedList<int>backing buffer withUint8List— eliminates integer boxing and reduces message extraction from two copies to one.special_cbor.dart: fixed JS-unsafe 64-bit integer encoding — replaced>> 56/>> 48/ ... bit-shift chains withByteData.setUint64, which is correctly implemented on both Dart VM and dart2js.RpcContext.withAdditionalHeaders: removed duplicate_sanitizeHeaderscall that could silently drop headers when the merged map exceeded the 128-header or 64 KB limit.RpcCallerEndpoint: changedcompressionEnableddefault fromtruetofalseto avoid compatibility issues with servers that do not advertise compression support.- Removed CORD-specific API (
createChain,forBusinessOperation,forDomainCall,extractDomainMetadata,DomainMetadata,RpcContextAware,correlationId).
3.0.0 #
Breaking changes and major additions:
3-layer transport architecture (IRpcChannel / IRpcMultiplexedChannel / RpcChannelTransport):
IRpcChannel— minimal raw byte pipe interfaceIRpcMultiplexedChannel— multiplexed message channel between channel and transportRpcFrameMultiplexedChannel— wrapsIRpcChannelwith 9-byte frame codecRpcDirectMultiplexedChannel— zero-copy in-memory paired channelRpcChannelTransport—IRpcTransportwrapper with.pair(),.memoryPair(),.fromChannel()factoriesRpcInMemoryTransport.pair()is now a thin delegate toRpcChannelTransport.memoryPair()
Resilience primitives (moved from rpc_dart_framework to core):
RpcRetryInterceptor— configurable retry withBackoffPolicy(constant, linear, exponential)RpcCircuitBreakerInterceptor— circuit breaker with open/half-open/closed statesRpcClientConnection— reconnect state machine with health monitoringRpcRateLimiter— pluggable rate limiting with per-key dynamic limits
gRPC Health Checking Protocol:
RpcGrpcHealthService— implementsgrpc.health.v1.Health(Check+Watch)RpcGrpcHealthClient— typed client for health checks
Other:
RpcBinaryCodec<T>now works with anyT extends Object(not justIRpcSerializable)RpcStatusException(statusCode, message)— handlers can return specific gRPC status codesdart:typed_datare-exported viarpc_dart.dart(Uint8Listavailable without extra import)- Removed
onServiceRegisteredcallback fromRpcResponderEndpoint
2.6.3 #
- Added
RpcRemovedannotation. Marks an inherited RPC method as removed in a versioned contract. The generator produces a@Deprecated+throw UnsupportedErrorimplementation so callers receive a compile-time warning and a clear runtime error message.
2.6.2 #
RpcMessageParser: replaced per-message buffer slicing with a read-offset approach —advance()moves a pointer in O(1) and a singlecompact()at the end of each parse pass drops consumed bytes in O(remaining), eliminating the previous O(N²) copy behaviour when multiple gRPC frames arrive in a single chunk (relevant for HTTP/2 and WebSocket transports).RpcMessageParser: fixed a latent bug where the loop conditionbuffer.length >= 5prevented re-entry after a 5-byte header arrived without a body shorter than 5 bytes, causing such messages to stall in the buffer indefinitely.
2.6.1 #
IRpcServer: removedhostandportfrom the interface — these are transport-level concerns, not RPC server concerns.IRpcServerFactoryinterface removed along withRpcHttp2ServerFactoryandRpcWebSocketServerFactory— the abstraction had no consumers.
2.6.0 #
- Added
RpcHeadersclass with gRPC semantic header name constants; all internal metadata and protocol code now usesRpcHeaders.*instead of raw strings. - Core parser passes compressed frames through when no decompressor is configured so the application layer (transport) can handle decompression — core stays agnostic.
- Transport packages now own their own wire-format: pseudo-headers (
:method,:path,:status, etc.) are generated by each transport and never stored inRpcMetadata;http2HeadersToRpcMetadatafilters them out automatically. RpcHttpCorsPolicy: always exposesgrpc-encoding,grpc-status,grpc-message,grpc-accept-encodinginAccess-Control-Expose-Headersso browsers do not block them in cross-origin responses.RpcHttpCorsPolicy: always allowsgrpc-timeout,grpc-encoding,grpc-accept-encodinginAccess-Control-Allow-Headers.RpcHttpCorsPolicy:exposedHeadersparameter renamed toextraExposedHeadersto clarify it is additive on top of the required gRPC headers.RpcCallerEndpoint: injectsgrpc-accept-encodinginto context based oncompressionEnabledso globally-registered codecs do not force server-side compression when the endpoint has compression disabled.- WebSocket transport: metadata is now encoded as binary CBOR (
WsMetadataCodec) instead of JSON — ~40 % more compact, self-describing, no extra dependencies; wire format:{"h":[["name","val"],...],"p":"/Svc/Method"}. - WebSocket transport:
_ensureGrpcFramenormalises parser output to gRPC frames, consistent with HTTP/2 transport delivery toincomingMessages. - Exported
CborCodecfromrpc_dartfor use by transport packages.
2.5.1 #
- Compression is now pluggable via
RpcCompressionCodecinterface andRpcGrpcCompression.register(). - Native dart:io gzip continues to auto-register on startup as before.
- External packages (e.g.
rpc_dart_compression) can now register codecs on web/JS/Wasm.
2.5.0 #
- Added gzip compression support:
RpcCallerEndpointnow has acompressionEnabledflag (defaulttrue) that automatically injectsgrpc-encoding: gzipfor non-zero-copy transports (e.g. network transports). StreamProcessorauto-detects request/response encoding from incoming metadata (grpc-encoding/grpc-accept-encoding), enabling transparent decompression on the server side.UnaryRespondercapturesgrpc-accept-encodingper stream to compress unary responses when the client advertises support.RpcMetadata.forServerInitialResponsenow accepts an optionalencodingparameter to includegrpc-encodingin the initial server response headers for streaming compression.- Added compression tests for all stream types (unary, server streaming, client streaming, bidirectional).
- Fix:
UnaryRespondernow capturesgrpc-encodingfrom incoming client metadata per stream and uses it for decompression, matching the behaviour ofStreamProcessor. - Fix: caller and streaming processors now validate
grpc-encodingagainst supported encodings before compressing and throwRpcExceptionwith a clear message instead ofUnsupportedError. - Fix:
UnaryRespondernow throwsRpcException(was bareException) when the request frame is empty. - Refactor: per-stream state in
UnaryResponderconsolidated from five parallel maps into a single_UnaryStreamStateobject — cleanup is now atomic. - Refactor: response-encoding negotiation logic extracted to
RpcGrpcCompression.selectResponseEncoding()and reused by bothUnaryResponderandStreamProcessor. - Refactor:
RpcCallerEndpoint._effectiveContextrenamed to_prepareContextfor clarity.
2.4.1 #
- Add interface for transport server
2.4.0 #
- Breaking: removed transport toolkit (
transport_toolkit.dart) from the public API surface. - Added
RpcSecurityPolicyto centralize transport/parser limits and metadata validation. - Security:
grpc-messageis now percent-encoded per gRPC HTTP/2 spec; addeddecodeGrpcMessagehelper. - Protocol: client request metadata now includes
grpc-accept-encoding(advertises supported message encodings). - Fix: clean up
RpcCallerEndpointcancellation token registry after completed calls (prevents memory growth in long-lived clients). - Security:
RpcInMemoryTransportnow enforces policy limits (metadata validation, active stream cap);pair()accepts an optionalpolicy.
2.3.4 #
- fix lints package compatibility
2.3.3 #
- fix test package compatibility
2.3.2 #
- Added annotations for codegeneration
2.3.1 #
- Optimize ping requests
- Introduced a unified middleware and interceptor pipeline across caller and responder endpoints, ensuring context propagation for unary and streaming RPC flows.
- Added
RpcMiddlewareContextenhancements and default async hooks so extensions can enrich request/response handling without touching the core. - Hardened serialization by validating codec decoders and shipping a
pluggable
RpcBinaryCodecfor external binary formats such as protobuf. - Expanded the test suite with exhaustive pipeline coverage for all RPC shapes and binary codec scenarios.
2.3.0 #
- Added aggregated diagnostics for caller and responder endpoints with
health()/reconnect()snapshots that combine endpoint metrics and transport status viaRpcEndpointHealthandRpcHealthStatus. - Implemented a built-in ping protocol between endpoints that exposes
round-trip timing, responder metadata and debug labels through
RpcCallerEndpoint.ping(). - Extended transport infrastructure with
IRpcTransport.health()andIRpcTransport.reconnect()plus detailed implementations forRpcInMemoryTransport,RpcTransportRouterand the transport toolkit, including automatic partner shutdown to avoid close deadlocks. - Improved
RpcStreamIdManagerso stream identifiers are recycled after hitting the HTTP/2 limit, preventing allocation failures during long-lived workloads. - Updated documentation and examples with health monitoring guidance and diagnostics-driven workflows.
2.2.2 #
- Docs: simplify everything
2.2.1 #
- Fix: remove base class modifier to allow mock contracts
2.2.0 #
- Added support for cancellation in caller/responder
- Fix timeout passing through headers
2.1.1 #
- Update logo
2.1.0 #
- Added dispose base method to responder to cleanup resources
2.0.0 #
- Updated license to MIT
- Added logo to the package
- Added readme translations (RU, EN)
1.8.0 #
- Added ability to specify data transfer mode in contract (zero-copy, codec, auto)
1.7.0 #
- Added ability to specify whether transport supports Zero-Copy
1.6.0 #
- Added Zero-Copy optimization for
RpcInMemoryTransport- object transfer without serialization/deserialization
1.5.0 #
- Added Transport Router for smart routing of RPC calls between transports
- Added typedef RpcRoutingCondition for typing routing condition functions
- Added support for routing rules with priorities (routeCall, routeWhen)
- Added conditional routing capability with access to RpcContext
- Added automatic validation of transport roles (client/server)
- Implemented correct Stream ID routing between transports
- Added router statistics and detailed logging
- Updated documentation with Transport Router usage examples
RpcLoggerSettings->RpcLoggerRpcContextPropagation->RpcContext
1.4.0 #
- Added RpcContext API with full gRPC-style context support
- Added support for headers, metadata, deadline and timeout
- Added distributed tracing support with trace ID
- Added
internallogging level for library internal details - Eliminated log duplication, library is "silent" by default
- Optimized InMemoryTransport for improved performance
- Fixed race conditions and deadlock situations
- Increased reliability of tests and CI/CD pipeline
1.3.2 #
- Removed auto-start of Responders
- Removed bundleId from
StreamDistributor - Updated documentation
1.3.1 #
- Optimized CBOR serializer and deserializer
- Added benchmarks for performance testing
1.3.0 #
- Updated documentation
1.2.2 #
- Added 1ms delay for data transfer stability
1.2.1 #
- Fixed specific errors in rpc-method operations (timeouts)
1.2.0 #
- Fixed critical bug with stream processing in Stream Processor
- Added explicit support for
bindToMessageStream()method for manual stream binding - Improved error handling in streams through gRPC statuses in metadata
- Fixed deadlock situations in client, server and bidirectional streams
- Optimized timeouts in tests for faster execution
- Improved documentation on working with streams and error handling
- Fixed issue with double stream listening in ClientStreamResponder
1.1.0 #
- Added
RpcStreamIdManagerfor stream ID management
1.0.3 #
- CBOR serializer now works only with
Map<String, dynamic>
1.0.2 #
- Added
StreamDistributor - Fixed linter issues
1.0.1 #
- Added subcontract registration
- Fixed unary method operations
1.0.0 #
- First stable release
- Implemented contract-based Backend-for-Domain (BFD) architecture
- Added support for all RPC types: unary calls, server streaming, client streaming, bidirectional streaming
- Added efficient CBOR serialization
- Added primitive types (String, Int, Double, Bool, Null) with operator support
- Implemented extensible logging system with color and level support
- Added universal transports: InMemoryTransport and IsolateTransport
- Implemented timeout handling and informative errors
- Main package contains only platform-independent transports, platform-specific ones will be available in separate packages
0.2.0 #
- Improved stream handling (BidiStream, ClientStreamingBidiStream, ServerStreamingBidiStream)
- Added support for diagnostic metrics and monitoring
- Improved marker handling in streams for more reliable interaction
- Added typed markers for various operations (stream completion, timeouts, etc.)
- Improved error handling and status transfer between client and server
- Optimized metadata handling in requests and responses
- Improved deadline and timeout handling in RPC operations
- Added operation cancellation mechanism
0.1.1 #
- Fixed error when registering contracts
- Added MsgPack serializer
0.1.0 #
- Initial release