|
|
|
@ -80,6 +80,7 @@ class EventEngine { |
|
|
|
|
/// callback. Each EventEngine method that takes a callback parameter, defines
|
|
|
|
|
/// the expected sets and meanings of statuses for that use case.
|
|
|
|
|
using Callback = std::function<void(absl::Status)>; |
|
|
|
|
/// A callback handle, used to cancel a callback.
|
|
|
|
|
struct TaskHandle { |
|
|
|
|
intptr_t key; |
|
|
|
|
}; |
|
|
|
@ -113,25 +114,34 @@ class EventEngine { |
|
|
|
|
/// allocation being handled by the quota system.
|
|
|
|
|
class Endpoint { |
|
|
|
|
public: |
|
|
|
|
virtual ~Endpoint() = 0; |
|
|
|
|
|
|
|
|
|
// TODO(hork): define status codes for the callback
|
|
|
|
|
/// The Endpoint destructor is responsible for shutting down all connections
|
|
|
|
|
/// and invoking all pending read or write callbacks with an error status.
|
|
|
|
|
virtual ~Endpoint() = default; |
|
|
|
|
/// Read data from the Endpoint.
|
|
|
|
|
///
|
|
|
|
|
/// When data is available on the connection, that data is moved into the
|
|
|
|
|
/// \a buffer, and the \a on_read callback is called. The caller must ensure
|
|
|
|
|
/// that the callback has access to the buffer when executed later.
|
|
|
|
|
/// Ownership of the buffer is not transferred. Valid slices *may* be placed
|
|
|
|
|
/// into the buffer even if the callback is invoked with Status != OK.
|
|
|
|
|
/// into the buffer even if the callback is invoked with a non-OK Status.
|
|
|
|
|
///
|
|
|
|
|
/// For failed read operations, implementations should pass the appropriate
|
|
|
|
|
/// statuses to \a on_read. For example, callbacks might expect to receive
|
|
|
|
|
/// DEADLINE_EXCEEDED when the deadline is exceeded, and CANCELLED on
|
|
|
|
|
/// endpoint shutdown.
|
|
|
|
|
virtual void Read(Callback on_read, SliceBuffer* buffer, |
|
|
|
|
absl::Time deadline) = 0; |
|
|
|
|
// TODO(hork): define status codes for the callback
|
|
|
|
|
/// Write data out on the connection.
|
|
|
|
|
///
|
|
|
|
|
/// \a on_writable is called when the connection is ready for more data. The
|
|
|
|
|
/// Slices within the \a data buffer may be mutated at will by the Endpoint
|
|
|
|
|
/// until \a on_writable is called. The \a data SliceBuffer will remain
|
|
|
|
|
/// valid after calling \a Write, but its state is otherwise undefined.
|
|
|
|
|
///
|
|
|
|
|
/// For failed write operations, implementations should pass the appropriate
|
|
|
|
|
/// statuses to \a on_writable. For example, callbacks might expect to
|
|
|
|
|
/// receive DEADLINE_EXCEEDED when the deadline is exceeded, and CANCELLED
|
|
|
|
|
/// on endpoint shutdown.
|
|
|
|
|
virtual void Write(Callback on_writable, SliceBuffer* data, |
|
|
|
|
absl::Time deadline) = 0; |
|
|
|
|
// TODO(hork): define status codes for the callback
|
|
|
|
@ -144,40 +154,66 @@ class EventEngine { |
|
|
|
|
virtual const ResolvedAddress* GetLocalAddress() const = 0; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/// Called when a new connection is established. This callback takes ownership
|
|
|
|
|
/// of the Endpoint and is responsible for its destruction.
|
|
|
|
|
using OnConnectCallback = std::function<void(absl::Status, Endpoint*)>; |
|
|
|
|
/// Called when a new connection is established.
|
|
|
|
|
///
|
|
|
|
|
/// If the connection attempt was not successful, implementations should pass
|
|
|
|
|
/// the appropriate statuses to this callback. For example, callbacks might
|
|
|
|
|
/// expect to receive DEADLINE_EXCEEDED statuses when appropriate, or
|
|
|
|
|
/// CANCELLED statuses on EventEngine shutdown.
|
|
|
|
|
using OnConnectCallback = |
|
|
|
|
std::function<void(absl::StatusOr<std::unique_ptr<Endpoint>>)>; |
|
|
|
|
|
|
|
|
|
/// An EventEngine Listener listens for incoming connection requests from gRPC
|
|
|
|
|
/// clients and initiates request processing once connections are established.
|
|
|
|
|
class Listener { |
|
|
|
|
public: |
|
|
|
|
/// A callback handle, used to cancel a callback. Called when the listener
|
|
|
|
|
/// has accepted a new client connection. This callback takes ownership of
|
|
|
|
|
/// the Endpoint and is responsible its destruction.
|
|
|
|
|
using AcceptCallback = std::function<void(absl::Status, Endpoint*)>; |
|
|
|
|
|
|
|
|
|
virtual ~Listener() = 0; |
|
|
|
|
|
|
|
|
|
// TODO(hork): define return status codes
|
|
|
|
|
/// Bind an address/port to this Listener. It is expected that multiple
|
|
|
|
|
/// addresses/ports can be bound to this Listener before Listener::Start has
|
|
|
|
|
/// been called. Returns the bound port or an error status.
|
|
|
|
|
/// Called when the listener has accepted a new client connection.
|
|
|
|
|
using AcceptCallback = std::function<void(std::unique_ptr<Endpoint>)>; |
|
|
|
|
virtual ~Listener() = default; |
|
|
|
|
/// Bind an address/port to this Listener.
|
|
|
|
|
///
|
|
|
|
|
/// It is expected that multiple addresses/ports can be bound to this
|
|
|
|
|
/// Listener before Listener::Start has been called. Returns either the
|
|
|
|
|
/// bound port or an appropriate error status.
|
|
|
|
|
virtual absl::StatusOr<int> Bind(const ResolvedAddress& addr) = 0; |
|
|
|
|
virtual absl::Status Start() = 0; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// TODO(hork): define status codes for the callback
|
|
|
|
|
// TODO(hork): define return status codes
|
|
|
|
|
// TODO(hork): document status arg meanings for on_accept and on_shutdown
|
|
|
|
|
/// Factory method to create a network listener.
|
|
|
|
|
/// Factory method to create a network listener / server.
|
|
|
|
|
///
|
|
|
|
|
/// Once a \a Listener is created and started, the \a on_accept callback will
|
|
|
|
|
/// be called once asynchronously for each established connection. Note that
|
|
|
|
|
/// unlike other callbacks, there is no status code parameter since the
|
|
|
|
|
/// callback will only be called in healthy scenarios where connections can be
|
|
|
|
|
/// accepted.
|
|
|
|
|
///
|
|
|
|
|
/// This method may return a non-OK status immediately if an error was
|
|
|
|
|
/// encountered in any synchronous steps required to create the Listener. In
|
|
|
|
|
/// this case, \a on_shutdown will never be called.
|
|
|
|
|
///
|
|
|
|
|
/// If this method returns a Listener, then \a on_shutdown will be invoked
|
|
|
|
|
/// exactly once, when the Listener is shut down. The status passed to it will
|
|
|
|
|
/// indicate if there was a problem during shutdown.
|
|
|
|
|
///
|
|
|
|
|
/// The provided \a SliceAllocatorFactory is used to create \a SliceAllocators
|
|
|
|
|
/// for Endpoint construction.
|
|
|
|
|
virtual absl::StatusOr<std::unique_ptr<Listener>> CreateListener( |
|
|
|
|
Listener::AcceptCallback on_accept, Callback on_shutdown, |
|
|
|
|
const ChannelArgs& args, |
|
|
|
|
SliceAllocatorFactory slice_allocator_factory) = 0; |
|
|
|
|
// TODO(hork): define status codes for the callback
|
|
|
|
|
// TODO(hork): define return status codes
|
|
|
|
|
/// Creates a network connection to a remote network listener.
|
|
|
|
|
/// Creates a client network connection to a remote network listener.
|
|
|
|
|
///
|
|
|
|
|
/// \a Connect may return an error status immediately if there was a failure
|
|
|
|
|
/// in the synchronous part of establishing a connection. In that event, the
|
|
|
|
|
/// \a on_connect callback *will not* have been executed. Otherwise, it is
|
|
|
|
|
/// expected that the \a on_connect callback will be asynchronously executed
|
|
|
|
|
/// exactly once by the EventEngine.
|
|
|
|
|
///
|
|
|
|
|
/// Implementation Note: it is important that the \a slice_allocator be used
|
|
|
|
|
/// for all read/write buffer allocations in the EventEngine implementation.
|
|
|
|
|
/// This allows gRPC's \a ResourceQuota system to monitor and control memory
|
|
|
|
|
/// usage with graceful degradation mechanisms. Please see the \a
|
|
|
|
|
/// SliceAllocator API for more information.
|
|
|
|
|
virtual absl::Status Connect(OnConnectCallback on_connect, |
|
|
|
|
const ResolvedAddress& addr, |
|
|
|
|
const ChannelArgs& args, |
|
|
|
@ -201,28 +237,40 @@ class EventEngine { |
|
|
|
|
/// Called with the collection of sockaddrs that were resolved from a given
|
|
|
|
|
/// target address.
|
|
|
|
|
using LookupHostnameCallback = |
|
|
|
|
std::function<void(absl::Status, std::vector<ResolvedAddress>)>; |
|
|
|
|
std::function<void(absl::StatusOr<std::vector<ResolvedAddress>>)>; |
|
|
|
|
/// Called with a collection of SRV records.
|
|
|
|
|
using LookupSRVCallback = |
|
|
|
|
std::function<void(absl::Status, std::vector<SRVRecord>)>; |
|
|
|
|
std::function<void(absl::StatusOr<std::vector<SRVRecord>>)>; |
|
|
|
|
/// Called with the result of a TXT record lookup
|
|
|
|
|
using LookupTXTCallback = std::function<void(absl::Status, std::string)>; |
|
|
|
|
using LookupTXTCallback = std::function<void(absl::StatusOr<std::string>)>; |
|
|
|
|
|
|
|
|
|
virtual ~DNSResolver() = 0; |
|
|
|
|
virtual ~DNSResolver() = default; |
|
|
|
|
|
|
|
|
|
// TODO(hork): define status codes for the callback
|
|
|
|
|
/// Asynchronously resolve an address. \a default_port may be a non-numeric
|
|
|
|
|
/// named service port, and will only be used if \a address does not already
|
|
|
|
|
/// contain a port component.
|
|
|
|
|
/// Asynchronously resolve an address.
|
|
|
|
|
///
|
|
|
|
|
/// \a default_port may be a non-numeric named service port, and will only
|
|
|
|
|
/// be used if \a address does not already contain a port component.
|
|
|
|
|
///
|
|
|
|
|
/// When the lookup is complete, the \a on_resolve callback will be invoked
|
|
|
|
|
/// with a status indicating the success or failure of the lookup.
|
|
|
|
|
/// Implementations should pass the appropriate statuses to the callback.
|
|
|
|
|
/// For example, callbacks might expect to receive DEADLINE_EXCEEDED when
|
|
|
|
|
/// the deadline is exceeded or CANCELLED if the lookup was cancelled.
|
|
|
|
|
virtual LookupTaskHandle LookupHostname(LookupHostnameCallback on_resolve, |
|
|
|
|
absl::string_view address, |
|
|
|
|
absl::string_view default_port, |
|
|
|
|
absl::Time deadline) = 0; |
|
|
|
|
// TODO(hork): define status codes for the callback
|
|
|
|
|
/// Asynchronously perform an SRV record lookup.
|
|
|
|
|
///
|
|
|
|
|
/// \a on_resolve has the same meaning and expectations as \a
|
|
|
|
|
/// LookupHostname's \a on_resolve callback.
|
|
|
|
|
virtual LookupTaskHandle LookupSRV(LookupSRVCallback on_resolve, |
|
|
|
|
absl::string_view name, |
|
|
|
|
absl::Time deadline) = 0; |
|
|
|
|
// TODO(hork): define status codes for the callback
|
|
|
|
|
/// Asynchronously perform a TXT record lookup.
|
|
|
|
|
///
|
|
|
|
|
/// \a on_resolve has the same meaning and expectations as \a
|
|
|
|
|
/// LookupHostname's \a on_resolve callback.
|
|
|
|
|
virtual LookupTaskHandle LookupTXT(LookupTXTCallback on_resolve, |
|
|
|
|
absl::string_view name, |
|
|
|
|
absl::Time deadline) = 0; |
|
|
|
@ -230,7 +278,7 @@ class EventEngine { |
|
|
|
|
virtual void TryCancelLookup(LookupTaskHandle handle) = 0; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
virtual ~EventEngine() = 0; |
|
|
|
|
virtual ~EventEngine() = default; |
|
|
|
|
|
|
|
|
|
// TODO(hork): define return status codes
|
|
|
|
|
/// Retrieves an instance of a DNSResolver.
|
|
|
|
@ -238,12 +286,18 @@ class EventEngine { |
|
|
|
|
|
|
|
|
|
/// Intended for future expansion of Task run functionality.
|
|
|
|
|
struct RunOptions {}; |
|
|
|
|
// TODO(hork): define status codes for the callback
|
|
|
|
|
// TODO(hork): consider recommendation to make TaskHandle an output arg
|
|
|
|
|
/// Run a callback as soon as possible.
|
|
|
|
|
///
|
|
|
|
|
/// The \a fn callback's \a status argument is used to indicate whether it was
|
|
|
|
|
/// executed normally. For example, the status may be CANCELLED if
|
|
|
|
|
/// \a TryCancel was called, or if the EventEngine is being shut down.
|
|
|
|
|
virtual TaskHandle Run(Callback fn, RunOptions opts) = 0; |
|
|
|
|
// TODO(hork): define status codes for the callback
|
|
|
|
|
/// Synonymous with scheduling an alarm to run at time \a when.
|
|
|
|
|
///
|
|
|
|
|
/// The callback \a fn will execute when either when time \a when arrives
|
|
|
|
|
/// (receiving status OK), or when the \a fn is cancelled (reveiving status
|
|
|
|
|
/// CANCELLED). The callback is guaranteed to be called exactly once.
|
|
|
|
|
virtual TaskHandle RunAt(absl::Time when, Callback fn, RunOptions opts) = 0; |
|
|
|
|
/// Immediately tries to cancel a callback.
|
|
|
|
|
/// Note that this is a "best effort" cancellation. No guarantee is made that
|
|
|
|
@ -258,20 +312,22 @@ class EventEngine { |
|
|
|
|
/// callback will be run exactly once from either cancellation or from its
|
|
|
|
|
/// activation.
|
|
|
|
|
virtual void TryCancel(TaskHandle handle) = 0; |
|
|
|
|
// TODO(hork): define return status codes
|
|
|
|
|
// TODO(hork): Carefully evaluate shutdown requirements, determine if we need
|
|
|
|
|
// a callback parameter to be added to this method.
|
|
|
|
|
/// Immediately run all callbacks with status indicating the shutdown. Every
|
|
|
|
|
/// EventEngine is expected to shut down exactly once. No new callbacks/tasks
|
|
|
|
|
/// should be scheduled after shutdown has begun. Any registered callbacks
|
|
|
|
|
/// must be executed.
|
|
|
|
|
virtual absl::Status Shutdown() = 0; |
|
|
|
|
/// should be scheduled after shutdown has begun, no new connections should be
|
|
|
|
|
/// created.
|
|
|
|
|
///
|
|
|
|
|
/// If the \a on_shutdown_complete callback is given a non-OK status, errors
|
|
|
|
|
/// are expected to be unrecoverable. For example, an implementation could
|
|
|
|
|
/// warn callers about leaks if memory cannot be freed within a certain
|
|
|
|
|
/// timeframe.
|
|
|
|
|
virtual void Shutdown(Callback on_shutdown_complete) = 0; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// Lazily instantiate and return a default global EventEngine instance if no
|
|
|
|
|
// custom instance is provided. If a custom EventEngine is provided for every
|
|
|
|
|
// channel/server via ChannelArgs, this method should never be called, and the
|
|
|
|
|
// default instance will never be instantiated.
|
|
|
|
|
/// Lazily instantiate and return a default global EventEngine instance if no
|
|
|
|
|
/// custom instance is provided. If a custom EventEngine is provided for every
|
|
|
|
|
/// channel/server via ChannelArgs, this method should never be called, and the
|
|
|
|
|
/// default instance will never be instantiated.
|
|
|
|
|
std::shared_ptr<EventEngine> GetDefaultEventEngine(); |
|
|
|
|
|
|
|
|
|
} // namespace experimental
|
|
|
|
|