Description
This is an alternative to, and intended to solve the same problem as, issue #406.
New Event
s
Three new event constructors are introduced:
data Event =
...
| OutboundConnectionOpened ConnectionId Reliability EndPointAddress
| OutboundConnectionClosed ConnectionId
| OutboundConnectionSent ConnectionId [ByteString]
Or perhaps instead:
data Provenance = Local | Peer
deriving (Show, Eq, Generic)
instance Binary Provenance
data Event =
-- Replaces 'Received', which can now mean 'Sent'.
Data Provenance ConnectionId [ByteString]
| ConnectionOpened Provenance ConnectionId Reliability EndPointAddress
| ConnectionClosed Provenance ConnectionId
| ...
deriving (Show, Eq, Generic)
pattern Received connid bss = Data Peer connid bss
pattern Sent connid bss = Data Local connid bss
and in any case:
data Connection = Connection {
...
, connectionId :: ConnectionId
}
Events with provenance Peer
are the familiar incoming events, whereas events with provenance Local
are generated in response to locally-initiated connection features: connect
, send
, and close
.
Semantics of local-provenance Event
s
When connect ep address reliability hints
succeeds, a ConnectionOpened Local connid reliability address
must be posted exactly once to ep
s event queue, where connid
is any suitable (unique) ConnectionId
.
When close conn
succeeds, a ConnectionClosed connid
must be posted exactly once to the event queue of the EndPoint
against which conn
was created.
When send conn bs
succeeds, a Data Local connid bs
must be posted exactly once to the event queue of the EndPoint
against which conn
was created, even if the connection is not reliable (in which case the receiver may see different Data
events than the sender for the same connection).
If the connection is ordered, then Data Local
events must be posted in the same order that the peer will observe the Data Peer
events corresponding to these sends (it's assumed the concrete transport is capable of doing this, else it shouldn't allow an ordered connection).
Regardless of reliability and ordering, a Data Local
event must come after the ConnectionOpened
for that connection, and before any event which terminates that connection (ConnectionClosed
or error events which cause it to close).
Note that these rules imply that for self connections (from one EndPoint
to itself), the EndPoint
will see two of each posted event, one for each provenance (they are both Local
and Peer
).
The connectionId
of a Connection
must be unique among incoming and outgoing connections, but need not match the ConnectionId
which the peer uses for that same connection.
It solves the problem brought up in #406
There is now an ordering on outgoing connections. If we observe ErrorEvent (TransportError (EventConnectionLost addr) _)
then every ConnectionOpened Local connid _ addr
which is unmatched by a ConnectionClosed Local connid
is known to be broken, and subsequent ConnectionOpened Local connid' _ addr
are not broken by that error event.