* Fix non-determinism in fake NetConn.Write
Serialize the responses to write so that they show up in their specified
order. This was responsible for some spurious test failures.
Consolidate creation of senders and receivers with test hooks.
Make sending and receiving of frames log level 0 to get the minimum
amount of logging that can be useful.
* check for context cancelled
* add unit test for Conn.getWriteTimeout and update changelog
* use delta comparison
* log error verbatim
* Properly distinguish between input and output link handles
Per spec, peers can have different values for link handles. When
sending a frame, its Handle is set to the output (our) handle. When
receiving a frame, its Handle is set to the input (remote) handle.
Fixed session data structures to properly map an input handle to a link.
Renamed handle fields and supporting types to follow spec nomenclature.
Added a live test that reproduced the issue.
* set release date in changelog
* add debug logging message on link attach complete
* bump release date
* Robust handling of context expiration/cancellation
If a context expires or is cancelled during session/link creation while
waiting for the ack, add the instance to a slice for later cleanup.
Removed force-closing of sessions/links.
Exhausting available session channels will return a *ConnError and close
the Conn.
Exhausting available link handles will return a *SessionError and close
the Session.
* add some additional tests
* add logging for abandoned sessions and links
* fix off-by-one error for default max links value
* Honor context cancellation in Dial and NewConn
Previously they only honored a deadline, now they handle both.
TLS dialer now calls DialContext().
* make linter happy
* switch to context.WithCancel just because
* Disable Session sending frames after end performative
This is against the spec and results in the peer terminating the
connection. Just ignore any outgoing frames.
* add debug logging when discarding frames
* Replace messages channel with a queue (#244)
* Replace messages channel with a queue
The Receiver.messages channel placed an arbitrary restriction on the
amount of link credit that could be issued to a Receiver. Once the
Receiver has been created, it can never be issued credit that exceeds
the size of the channel.
In addition, if the Receiver were to receive messages that exceeds the
size of the channel, due to flow control bugs or other, the writes to
the channel could block leading to hangs.
The channel has been replaced with a segmented FIFO queue. While this
in theory could allow for unbounded growth, the reality is that the
total size can never be greater than that of the Session's incoming
window.
* use Ring from standard library
* switch to require.Same for pointer comparisons
fixed issue in last seg check and added another test
* refine and add another test
* size message queue to the incoming window
* add Holder[T] to abstract syncronized access
* Remove concept of "max credit" from Receivers (#251)
* Remove concept of "max credit" from Receivers
This exposed an implementation detail of how Receivers worked. With the
removal of the Message channel, this is no longer required and never
really made sense anyways.
The MaxCredit and ManualCredits options have been consolidated into a
single Credit option. This is used to set the total credit for a
Receiver in auto-flow mode, or to disable auto-flow.
Disposition batching needed some slight refactoring. Now you can
directly specify the batch size instead of it being tied to link credit.
Received messages that are sender-settled now correctly count towards a
Receiver's credit and must be settled to reclaim it.
* fix linter
* back out double-buffering change for now
* refine threshold logic
* switch to mutex instead of channel for better perf
* add back fix to remove double buffering
* rename local var for clarity
* revert cosmetic change
* Replace incoming frame channels with queues (#253)
* Replace incoming frame channels with queues
The rx channel in Session and link has been replaced with a queue. This
ensures that parents enqueueing frames to their children is always a non
blocking operation and removes the need to "pump the mux".
Consolidated some link creation code into newLink().
Links echoing a flow frame now correctly include session info.
Reverted workaround for sending disposition frames from senders as we
can now send directly from muxHandleFrame.
* minor cleanup from review
* Remove configuration of session window (#257)
The values weren't actually honored which is ok per spec, so remove them
from the public surface area.
Cleaned up handling of sender link credit. Since we don't use
availableCredit, it's been removed.
* Improve handling of sender-settled messages (#258)
Reclaim credit for sender-settled messages when Prefetch or Receive are
called. This removes the need to explicitly settle the message.
Detach has a specific meaning in AMQP and since we don't support link
detach/reattach the error type name is misleading.
Cleaned up any misused detach verbage.
* Enable at-most-once for senders
When a sender's peer is in mode second, the disposition confirmation
must be sent through the session so that the in-flight disposition
tracker can be closed.
* remove potential for recursion
* add a couple code comments
* consolidate frame handling
* Fix potential deadlock between senders and receivers
Receivers configured for ModeFirst weren't tracking unsettled messages.
As a result, their session would send them more messages than their link
credit would allow, causing the session mux to be blocked.
With the session mux blocked, senders within the same session were
unable to send messages.
* fix after rebasing
* fix auto-flow credit threshold
* Remove conn.mux
conn.connReader() dispatches frames directly to sessions now.
Added conn.NextSession() and conn.DeleteSession() for deterministic
session management.
Channel numbers are now recycled immediately which prompted a fix for
TestSessionClose.
Fixed various tests to handle close frame (the error was being swallowed
before).
Tests that utilize testconn were silently failing due to a bug in
Conn.Read which has been fixed.
* simplify reader/writer error handling
* clean-up
* fix testconn.SetDeadline
* update changelog
* refine error check when closing net.Conn
fixed propagation of RemoteErr on close
* always reset idle read timeout before reading
* remove connReaderRun as it's no longer necessary
* consolidate calls to closeOnce.Do
* replace magic number with constant
* Refactor error types
The session and link sentinel error types have been removed.
Added SessionError type which allows more descriptive errors.
Fixed some error corner-cases to ensure they return DetachError.
Removed spurious error text on peer-initiated ending of a session.
* Enusre that peer-initiated end/detach is not ambiguous
Fixed doc comment for Conn
* add RemoteErr *Error field to error types and removed Unwrap()
removed synthetic *Error{} when peer doesn't provide an error
* log partial writes
* fix up docs and add examples
* fix copy/pasta
* more example clean-up
* Replace varadic config for Sender and Receiver with struct config
Added SenderOptions and ReceiverOptions types which replicates the
previous functional options.
Options that are specific to senders/receivers have been moved to their
respective options types.
Added Ptr() methods to SenderSettleMode and ReceiverSettleMode to
simplify setting these optional values.
* Removed error return from Prefetched
* clean-up
* Replace variadic config for conn with struct config
Added ConnOptions type which replicates the previous functional options
with the exception of ConnTLS which is redundant.
The SASL authentication mechanism is now singular instead of last one
wins.
Added SASLType for configuring SALS configuration. The matching
configuration funcs have been renamed to match this type.
* fix linter issue
* update comment
* fix doc comments
Added a bit more coverage for mode second integration tests.
Cleaned up linter noise for spurious usage of fmt.Sprintf.
Replaced assert with required for receiver tests.
* Return *ConnectionError when connection has faulted
Errors reading from/writing to the underlying net.Conn were being
propagated to the sender/receiver APIs, making them hard to identify.
Now, when the connection is no longer functional, a ConnectionError
instance is returned. If the connection died due to a read/write error,
the ConnectionError will contain this information.
Removed ErrConnClosed as it's too simplistic and can't capture the
reason why the connection was closed.
* add comment about swallowed error
* remove comment
* Add unit tests for Session
Added disambiguating text to more debug statements.
Fixed a race condition when concurrently creating sessions.
Added support for sender attach performative and encoding SASL frames.
Fixed a hang in session mux for malformed attach frame.
Added some clarifying comments to a few chunks of code.
* fix test after updating handle error count
* add comment and missing break
* Add mocks package for unit testing
This includes a mock net.Conn and various helper funcs for creating mock
response frames.
Moved frame parsing out of conn.go and into frames package so that the
mock infrastructure can use it.
Fixed a bug in link uncovered by new unit tests.
Rewrote receiver tests using the new framework.
* remove unused const
* remove stuttering
* little more renaming
* refine earlier fix for link Source
apply same fix for link Target
* Move message disposition methods to Receiver
Moved methods from Message to Receiver.
Removed Receiver.HandleMessage.
Fixed auto-accept in ModeFirst.
Check for closed link during blocking Receive.
* don't touch Message internals
* remove from unsettled map after ack of disposition
* Run integration tests against local broker
Uses the .NET Core AMQP broker for local E2E tests.
Removed tests that were specific to EH and SB.
Removed github workflow.
* run dotnet restore before run
* switch to .net 5 and update TFM
* fix runtime version
use non-standard port number to avoid collisions
* log broker address
* switch to loopback address
* start broker before tests
* invoke broker directly
* add execute bit to broker
* fix URI
* treat as env var
* test
* test
* test
* kill broker
* add headless switch
* Misc clean-up
Removed some dead code.
Fixed minor linter issues.
Updated CI to latest versions of Go.
* fix 1.17 version string
* update build constraints for 1.17
* add basic codeowners file
* use pending messages to decide on flow control
* add detailed debug logging
* remove unecessary parenthesis
* add tests that shows receive failure and HandleMessage success
* lock on len(pendingMessages)
* add message.Ignore() to allow consumer to explicitely control the amqp message pump
* add integration tests
* mod tidy
* remove dependency on amqp-common
* re-add the build tag that got yanked in rebase
* rename pending to unsettled
* Fixes for initial release
Fixed references to new package path.
Removed dependencies on Azure SDK for now; this required disabling the
integration tests as they depend on it.
Added go.mod and go.sum files.
Added back content removed from README.md file.
* add initial devops CI pipeline
Server errors during link creation are reported by sending an Attach
without a source or target and immediately sending a follow up Detach.
Check for this situation and wait for the Detach so the error can be
returned to the user immediately.
LinkTargetAddress was incorrectly being used with Session.NewReceiver
instead of LinkSourceAddress.
Some Close calls were being done in seperate goroutines.
Batching has been enabled by default since the early days of this
library. In retrospect I think this was a mistake. I believe most users
would expect messages to be acknowledged immediately when calling
`Message.Accept()` (evidenced in #127). Requiring explicit opt-in
should lessen the risk of bugs due to the batching behavior.
Link should not send additional credits when there are queued
transfers/messages waiting to be read via `Receiver.Receive`. Message
decoding is moved into the `link.mux` goroutine so that the link can
know how many messages are queued by checking the `link.messages`
channel length. If the channel fills the link is effectively paused.
The receiver can indicate it can process additional message and unblock
the link my sending on `link.receiverReady`.
When additional credits are issued, `link.linkCredit` must be updated
before receiving any additional messages to ensure the sender and
receiver stay in sync.
Similarly, `link.deliveryCount` should not be arbitrarily changed based
on a flow frame received from the sender.
* Track numbers in a lazily initialized bitmap.
* Both will now use the lowest free number.
* Added SessionMaxLinks option mirroring ConnMaxSessions.
* Attempting to create a new link when max has been reached will return
an error.
* Fixed error causing fields set to zero to be encoded as null even
though the field default is not zero.
Resolves#68Resolves#76
* `Close()` is now `Close(context.Context)` for sessions and links.
* `Client.Close` does not take a context as it does not currently
block.
* Added `-count=1` to integration tests to prevent caching on Go1.10+.