Skip to content

Handlers

Scott Mansfield edited this page Feb 26, 2017 · 1 revision

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:

  • GetRequests 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.

Clone this wiki locally