- Added DisposeAsync to the IConnectionFactory. It's responsible for disposing the connection after the pipe has closed.
- Added dispose callback to WithConnectionFactory
- Don't wait for poll request to end before unwinding from the transport
- Make sure all http requests are done before returning from StopAsync in both SSE and longpolling
- Get rid of LimitArrayPoolWriteStream and use MemoryBufferWriter in its place in the MessagePackProtocol implementation.
- Added tests for MemoryPoolBufferWriter and fixed a bug in CopyToAsync
- Added CopyTo(`IBufferWriter<byte>`)
- Changed MemoryBufferWriter to fill the underlying arrays that back segments, the segment size is now a minimum.
This change rationalizes the 2 very similar abstractions that exist in Connections.Abstractions, IConnection and ConnectionContext. It also introduces an IConnectionFactory to SignalR that is used to create a new ConnectionContext for a HubConnection.
- HubConnection just completes both ends of the transport pipe instead of calling DisposeAsync.
- Implemented ConnectionContext on HttpConnection and added HttpConnectionFactory
- Updated tests
- There are too many issues and questions with respect to back pressure and the buffering policy we should use when the client being streamed to can't support the data being pushed via OnNext.
As a result, we're dropping support for IObservable but keeping ChannelReader and we'll eventually support IAsyncEnumerable when that makes it into the BCL.
- Add sample showing Observable -> ChannelReader adaption
- Don't create the PipeWriterStream per operation, make it per Connection
- Reduce the buffer size for CopyToAsync operations to 4K where possible instead of 81K (the default)
- Closing pipes gracefully in most cases. The only case where we forcefully close the pipes is during application shutdown
- Return 404 if sending to connection after disposal
- Added tests
- Rename file to HttpTransportType.cs
- Add HttpTransportType.None
- Move All to static readonly field
- Make TransportType on client and service HttpConnectionOptions consistent
- Move setting defaults into ctor
- Use the AddLogging extension method by default in the HubConnection
- Removed WithConsoleLogger extension methods
- Removed WithLoggerFactory extension method (moved to test only)
- Added WithLogger that uses the new the new ILoggerBuilder
- Ripped of Kestrel's SocketConnection to make a TcpConnection
IConnection implementation.
- Fixed issue with SignalR assuming there will always be a non-null user
on the ConnectionContext.
- Renamed StreamPipeConnection to PipeReaderFactory
- Flow the transport cancellation token to the CopyToAsync routine
- Other small cleanup and nits to make the style consistent with the other pipe reader loops
- Return a cancelled ValueTask from PipeWriterStream.WriteAsync
- Move event stream request to start itself
- We no longer need to pass the tcs through.
- It also cleans up handling failure in start since the application pipe hasn't been read or written to
- Removed SendUtils.PrepareRequst and instead used HttpClient.DefaultRequstHeaders to set the common headers to apply HttpOptions to all outbound requests
- Modified how we check for the user agent request testing
- 5 seconds seems to be too low for long polling's RTT. We often see super flaky tests and it seems like this is the best fix. Ideally, we would do something more sophisitcated than just timeout the entire time to parse.
- We made a change to not initialize pipes up front
on connection creation. That change make it null ref in disposal because we didn't check if the pipes were initialized.
- Added a test
- Also fixed the EchoConnectionHandler in the functional ts tests.
- We made a change to not initialize pipes up front
on connection creation. That change make it null ref in disposal because we didn't check if the pipes were initialized.
- Added a test
- Also fixed the EchoConnectionHandler in the functional ts tests.
- Cancel reading from the application when initiating a transport stop
- Complete each side of the pipe in the place where the pipe is being consumed
- Errors from sending end up getting sent to the application
- The Running task never throws
- Removes ContinueWith
- These are the finishing touches before we disable batching on the
C# client and on the server. We're changing the IHubProtocol interface to
modify the input buffer with what was consumed. We're also changing it
to parse a single message at a time to be match what output writing does.
- Added TryParseResponseMessage and made it look like TryParseRequestMessage
- Directly pin the char[]
- Changed Utf8BufferTextReader to use the Utf8Decoder
- It copies whatever it can into the char buffer allocated in a stateful way (it's more efficient).
- Added tests for unicode and ascii reading
- Added a thread static cache
* Progress towards deleting Sockets.Abstractions
- Moved our custom DefaultConnectionContext to Sockets.Http and renamed it to HttpConnectionContext.
- Renamed ConnectionManager to HttpConnectionManager
- Use DefaultConnection in tests and benchmarks
- Delete ConnectionMetadata
- React to rename of EndPoint to ConnectionHandler
- Rename UseSockets to UseConnections
- Rename MapEndPoint to MapConnectionHandler
- Rename HttpSocketOptions to HttpConnectionOptions
- The long polling transport simulates a persistent connection
over multiple http requests. In order to expose common http request
properties, we need to copy them to a fake http context on the first poll
and set that as the HttpContext exposed via the IHttpContextFeature.
* Don't copy the array for incoming msgpack reads
- Don't use ToArray on the already sliced msgpack data.
- Turns out msgpack is self describing enough to not require the count, it just needs the buffer and start offset.
- Made HubCallerContext an abstract class
- Made DefaultHubCallerContext that gets data from the HubConnectionContext.
- Removed IP address
- Removed Connection property
- Don't allocate when enumerating connections
- Don't allocate tasks unless we truly go async
- Don't get the timestamp, just write the pings always (if there's no ongoing write)
- Track the time since last keep alive write instead of the last write
- ValueTask all the things!
- Renamed HubConnectionList to HubConnectionStore
- Introduced Utf8BufferTextReader that writes buffers directly into
the char[] allocated by JSON.NET when reading via the JsonReader.
- Use IArrayPool implementation over ArrayPool<char> when reading
incomming messages.
- Replaced JToken parsing with manual parsing using JsonTextReader.
- Added tests for parsing incoming JSON messages with out of order
properties.
- Make access to message headers lazy
- Changed IHubProtocol.TryParseMessage to be ReadOnlyMemory<byte> instead of ReadOnlySpan<byte>
- Return ValueTask instead of Task from WriteAsync helpers
- Use TryGet instead of foreach to avoid enumerator (though it's just a stack allocation here)
- This PR attempts to move things where they are needed instead of where they
happened to be used. As a result we should now have Sockets.Abstractions and
Sockets down to the minimal set of things required to make them run.
Sockets.Abstractions should go away in favor of Protocol.Abstractions and
Sockets contains the EndPoint abstraction and related types.
- Moved ConnectionManager and friends to
Sockets.Http.
-Removed Sockets and moved everything into Sockets.Abstractions.
- Moved DefaultConnection and put it in Sockets.Abstractions.
* Do over the websocket transport
- Unify client and server logic (no code sharing yet)
- Removed use of cancellation tokens to communicate shutdown and instead used the pipe reader and socket abort.
- Added CloseTimeout to HttpOptions
* Tackling some low hanging performance fruit
- Use native Memory/Span APIs on Stream and WebSocket in .NET Core 2.1
- Remove double copying in formatters
- Implemented custom HttpContent over ReadOnlyBuffer<byte>
* Remove the Channel<HubMessage> from the HubConnectionContext
- Replace the channel with a single lock around the pipewriter. Since writes are always synchronous, the lock is held for a very short time.
- We were only using them in this scenario for handling multiple producers (the hub output, the keep alive ping and the broadcast).
- Handle the scenario where there's back pressure (when we use pipes that are bounded) and give callers a single task representing when back pressure is released.
- Handle synchronous exceptions in RedisHubLifetimeManager
- Fixed benchmarks
- Reworked the Client to be based on pipelines instead of Channels
- SendAsync no longer fails if the http request itself fails but the connection is closed as a result.
- Updated tests
- Base64Encoder needed to support multiple messages in the same span of data