-
Notifications
You must be signed in to change notification settings - Fork 85
Handlers
Within Rend, the handlers.Handler
interface is where the rubber meets the road. It consists of all the operations that Rend may send on to a given backend storage. The interface hides things like where the data is stored, how it's accessed, and how long it takes. There's no timeouts or control mechanisms.
The interface follows the basic memcached operations plus an additional method GetE
, which is a get request that also requires the expiration time to be returned. The
type Handler interface {
Set(cmd common.SetRequest) error
Add(cmd common.SetRequest) error
Replace(cmd common.SetRequest) error
Append(cmd common.SetRequest) error
Prepend(cmd common.SetRequest) error
Get(cmd common.GetRequest) (<-chan common.GetResponse, <-chan error)
GetE(cmd common.GetRequest) (<-chan common.GetEResponse, <-chan error)
GAT(cmd common.GATRequest) (common.GetResponse, error)
Delete(cmd common.DeleteRequest) error
Touch(cmd common.TouchRequest) error
Close() error
}
Most of the methods are straightforward. Set
, Add
, Replace
, Append
, and Prepend
all take a common.SetRequest
struct, which contains data to use. GAT
is a get-and-touch operation which retrieves the data. Delete
removes the item from storage, and Touch
changes the expiration time. Close
ends up being implementation specific, and may be a no-op for things like a connection pool. It is assumed to operate on only the current external connection's resources and not the Handler
as a whole.
The Get
and GetE
methods return a couple of channels for results and errors. This is an asynchronous interface as opposed to the remainder of the methods, which are synchronous. This was done because of a couple of interacting features and goals:
-
GetRequest
s are always considered a batch request - Lower memory usage as a goal
In order to prevent having 1000 get results in memory at a time, the asynchronous interface was created. This allows there to be only a couple results in hand at a time: one in the process of being processed and written to the remote connection (the user) and one locally retrieved from the data storage. Since the channels are created by the implementation, it's not guaranteed that any given channel is unbuffered.
The contract for the channel communication is as follows:
Readers will select{}
both the results and error channels at the same time. A reader will receive results on the response channel unless there is an error. After an error occurs it is expected that no more responses will be sent and that both channels will be closed. The implementation must not send responses after sending an error on the error channel. For the positive case (no errors) once both channels are closed the reader will continue operation.
Notes on the above: Misses are not considered an error; they are covered by a boolean flag in the GetResponse
and GetEResponse
types. Errors are typically IO errors or other major problems and indicate the connection itself is bad. Simple example implementations can be found in the orcas.L1Only.Get
and GetE
methods.