Documentation ¶
Overview ¶
Package nexus provides client and server implementations of the Nexus HTTP API
Index ¶
- Constants
- Variables
- func ExecuteOperation[I, O any](ctx context.Context, client *Client, operation OperationReference[I, O], ...) (O, error)
- func NewCompletionHTTPHandler(options CompletionHandlerOptions) http.Handler
- func NewCompletionHTTPRequest(ctx context.Context, url string, completion OperationCompletion) (*http.Request, error)
- func NewHTTPHandler(options HandlerOptions) http.Handler
- type CancelOperationOptions
- type Client
- func (c *Client) ExecuteOperation(ctx context.Context, operation string, input any, ...) (*LazyValue, error)
- func (c *Client) NewHandle(operation string, operationID string) (*OperationHandle[*LazyValue], error)
- func (c *Client) StartOperation(ctx context.Context, operation string, input any, ...) (*ClientStartOperationResult[*LazyValue], error)
- type ClientOptions
- type ClientStartOperationResult
- type CompletionHandler
- type CompletionHandlerOptions
- type CompletionRequest
- type Content
- type ExecuteOperationOptions
- type Failure
- type GetOperationInfoOptions
- type GetOperationResultOptions
- type Handler
- type HandlerError
- type HandlerErrorType
- type HandlerOptions
- type HandlerStartOperationResult
- type HandlerStartOperationResultAsync
- type HandlerStartOperationResultSync
- type Header
- type LazyValue
- type NoValue
- type Operation
- type OperationCompletion
- type OperationCompletionSuccessful
- type OperationCompletionUnsuccessful
- type OperationHandle
- func (h *OperationHandle[T]) Cancel(ctx context.Context, options CancelOperationOptions) error
- func (h *OperationHandle[T]) GetInfo(ctx context.Context, options GetOperationInfoOptions) (*OperationInfo, error)
- func (h *OperationHandle[T]) GetResult(ctx context.Context, options GetOperationResultOptions) (T, error)
- type OperationInfo
- type OperationReference
- type OperationRegistry
- type OperationState
- type Reader
- type RegisterableOperation
- type Serializer
- type StartOperationOptions
- type UnexpectedResponseError
- type UnimplementedHandler
- func (h UnimplementedHandler) CancelOperation(ctx context.Context, operation, operationID string, ...) error
- func (h UnimplementedHandler) GetOperationInfo(ctx context.Context, operation, operationID string, ...) (*OperationInfo, error)
- func (h UnimplementedHandler) GetOperationResult(ctx context.Context, operation, operationID string, ...) (any, error)
- func (h UnimplementedHandler) StartOperation(ctx context.Context, operation string, input *LazyValue, ...) (HandlerStartOperationResult[any], error)
- type UnimplementedOperation
- func (*UnimplementedOperation[I, O]) Cancel(context.Context, string, CancelOperationOptions) error
- func (*UnimplementedOperation[I, O]) GetInfo(context.Context, string, GetOperationInfoOptions) (*OperationInfo, error)
- func (*UnimplementedOperation[I, O]) GetResult(context.Context, string, GetOperationResultOptions) (O, error)
- func (h *UnimplementedOperation[I, O]) Start(ctx context.Context, input I, options StartOperationOptions) (HandlerStartOperationResult[O], error)
- type UnsuccessfulOperationError
Examples ¶
Constants ¶
const ( StatusDownstreamError = 520 StatusDownstreamTimeout = 521 )
Variables ¶
var ErrOperationStillRunning = errors.New("operation still running")
ErrOperationStillRunning indicates that an operation is still running while trying to get its result.
Functions ¶
func ExecuteOperation ¶ added in v0.0.2
func ExecuteOperation[I, O any](ctx context.Context, client *Client, operation OperationReference[I, O], input I, request ExecuteOperationOptions) (O, error)
ExecuteOperation is the type safe version of Client.ExecuteOperation. It accepts input of type I and returns output of type O, removing the need to consume the LazyValue returned by the client method.
ref := NewOperationReference[MyInput, MyOutput]("my-operation") out, err := ExecuteOperation(ctx, client, ref, MyInput{}, options) // returns MyOutput, error
func NewCompletionHTTPHandler ¶
func NewCompletionHTTPHandler(options CompletionHandlerOptions) http.Handler
NewCompletionHTTPHandler constructs an http.Handler from given options for handling operation completion requests.
func NewCompletionHTTPRequest ¶
func NewCompletionHTTPRequest(ctx context.Context, url string, completion OperationCompletion) (*http.Request, error)
NewCompletionHTTPRequest creates an HTTP request deliver an operation completion to a given URL.
func NewHTTPHandler ¶
func NewHTTPHandler(options HandlerOptions) http.Handler
NewHTTPHandler constructs an http.Handler from given options for handling Nexus service requests.
Types ¶
type CancelOperationOptions ¶
type CancelOperationOptions struct { // Header contains the request header fields either received by the server or to be sent by the client. // // Header will always be non empty in server methods and can be optionally set in the client API. Header Header }
CancelOperationOptions are options for the CancelOperation client and server APIs.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
A Client makes Nexus service requests as defined in the Nexus HTTP API.
It can start a new operation and get an OperationHandle to an existing, asynchronous operation.
Use an OperationHandle to cancel, get the result of, and get information about asynchronous operations.
OperationHandles can be obtained either by starting new operations or by calling Client.NewHandle for existing operations.
func NewClient ¶
func NewClient(options ClientOptions) (*Client, error)
NewClient creates a new Client from provided ClientOptions. Only BaseServiceURL is required.
func (*Client) ExecuteOperation ¶
func (c *Client) ExecuteOperation(ctx context.Context, operation string, input any, options ExecuteOperationOptions) (*LazyValue, error)
ExecuteOperation is a helper for starting an operation and waiting for its completion.
For asynchronous operations, the client will long poll for their result, issuing one or more requests until the wait period provided via ExecuteOperationOptions exceeds, in which case an ErrOperationStillRunning error is returned.
The wait time is capped to the deadline of the provided context. Make sure to handle both context deadline errors and ErrOperationStillRunning.
Note that the wait period is enforced by the server and may not be respected if the server is misbehaving. Set the context deadline to the max allowed wait period to ensure this call returns in a timely fashion.
⚠️ If this method completes successfully, the returned response's body must be read in its entirety and closed to free up the underlying connection.
Example ¶
package main import ( "context" "fmt" "github.com/nexus-rpc/sdk-go/nexus" ) type MyStruct struct { Field string } var ctx = context.Background() var client *nexus.Client func main() { response, err := client.ExecuteOperation(ctx, "operation name", MyStruct{Field: "value"}, nexus.ExecuteOperationOptions{}) if err != nil { // handle nexus.UnsuccessfulOperationError, nexus.ErrOperationStillRunning and, context.DeadlineExceeded } // must close the returned response body and read it until EOF to free up the underlying connection var output MyStruct _ = response.Consume(&output) fmt.Printf("Got response: %v\n", output) }
Output:
func (*Client) NewHandle ¶
func (c *Client) NewHandle(operation string, operationID string) (*OperationHandle[*LazyValue], error)
NewHandle gets a handle to an asynchronous operation by name and ID. Does not incur a trip to the server. Fails if provided an empty operation or ID.
func (*Client) StartOperation ¶
func (c *Client) StartOperation(ctx context.Context, operation string, input any, options StartOperationOptions) (*ClientStartOperationResult[*LazyValue], error)
StartOperation calls the configured Nexus endpoint to start an operation.
This method has the following possible outcomes:
The operation completes successfully. The result of this call will be set as a LazyValue in ClientStartOperationResult.Successful and must be consumed to free up the underlying connection.
The operation was started and the handler has indicated that it will complete asynchronously. An OperationHandle will be returned as ClientStartOperationResult.Pending, which can be used to perform actions such as getting its result.
The operation was unsuccessful. The returned result will be nil and error will be an UnsuccessfulOperationError.
Any other error.
Example ¶
package main import ( "context" "errors" "fmt" "github.com/nexus-rpc/sdk-go/nexus" ) type MyStruct struct { Field string } var ctx = context.Background() var client *nexus.Client func main() { result, err := client.StartOperation(ctx, "example", MyStruct{Field: "value"}, nexus.StartOperationOptions{}) if err != nil { var unsuccessfulOperationError *nexus.UnsuccessfulOperationError if errors.As(err, &unsuccessfulOperationError) { // operation failed or canceled fmt.Printf("Operation unsuccessful with state: %s, failure message: %s\n", unsuccessfulOperationError.State, unsuccessfulOperationError.Failure.Message) } // handle error here } if result.Successful != nil { // operation successful response := result.Successful // must consume the response to free up the underlying connection var output MyStruct _ = response.Consume(&output) fmt.Printf("Got response: %v\n", output) } else { // operation started asynchronously handle := result.Pending fmt.Printf("Started asynchronous operation with ID: %s\n", handle.ID) } }
Output:
type ClientOptions ¶
type ClientOptions struct { // Base URL of the service. ServiceBaseURL string // A function for making HTTP requests. // Defaults to [http.DefaultClient.Do]. HTTPCaller func(*http.Request) (*http.Response, error) // A [Serializer] to customize client serialization behavior. // By default the client handles, JSONables, byte slices, and nil. Serializer Serializer }
ClientOptions are options for creating a Client.
type ClientStartOperationResult ¶ added in v0.0.2
type ClientStartOperationResult[T any] struct { // Set when start completes synchronously and successfully. // // If T is a [LazyValue], ensure that your consume it or read the underlying content in its entirety and close it to // free up the underlying connection. Successful T // Set when the handler indicates that it started an asynchronous operation. // The attached handle can be used to perform actions such as cancel the operation or get its result. Pending *OperationHandle[T] }
ClientStartOperationResult is the return type of Client.StartOperation. One and only one of Successful or Pending will be non-nil.
func StartOperation ¶ added in v0.0.2
func StartOperation[I, O any](ctx context.Context, client *Client, operation OperationReference[I, O], input I, request StartOperationOptions) (*ClientStartOperationResult[O], error)
StartOperation is the type safe version of Client.StartOperation. It accepts input of type I and returns a ClientStartOperationResult of type O, removing the need to consume the LazyValue returned by the client method.
type CompletionHandler ¶
type CompletionHandler interface {
CompleteOperation(context.Context, *CompletionRequest) error
}
A CompletionHandler can receive operation completion requests as delivered via the callback URL provided in start-operation requests.
type CompletionHandlerOptions ¶
type CompletionHandlerOptions struct { // Handler for completion requests. Handler CompletionHandler // A stuctured logging handler. // Defaults to slog.Default(). Logger *slog.Logger }
CompletionHandlerOptions are options for NewCompletionHTTPHandler.
type CompletionRequest ¶
type CompletionRequest struct { // The original HTTP request. HTTPRequest *http.Request // State of the operation. State OperationState // Parsed from request and set if State is failed or canceled. Failure *Failure }
CompletionRequest is input for CompletionHandler.CompleteOperation.
type Content ¶ added in v0.0.2
type Content struct { // Header that should include information on how to deserialize this content. // Headers constructed by the framework always have lower case keys. // User provided keys are considered case-insensitive by the framework. Header Header // Data contains request or response data. May be nil for empty data. Data []byte }
A Content is a container for a Header and a byte slice. It is used by the SDK's Serializer interface implementations.
type ExecuteOperationOptions ¶
type ExecuteOperationOptions struct { // Callback URL to provide to the handle for receiving async operation completions. Optional. // Even though Client.ExecuteOperation waits for operation completion, some applications may want to set this // callback as a fallback mechanism. CallbackURL string // Request ID that may be used by the server handler to dedupe this start request. // By default a v4 UUID will be generated by the client. RequestID string // Header to attach to start and get-result requests. Optional. // // Header keys with the "content-" prefix are reserved for [Serializer] headers and should not be set in the // client API; they are not be avaliable to server [Handler] and [Operation] implementations. Header Header // Duration to wait for operation completion. // // ⚠ NOTE: unlike GetOperationResultOptions.Wait, zero and negative values are considered effectively infinite. Wait time.Duration }
ExecuteOperationOptions are options for Client.ExecuteOperation.
type Failure ¶
type Failure struct { // A simple text message. Message string `json:"message"` // A key-value mapping for additional context. Useful for decoding the 'details' field, if needed. Metadata map[string]string `json:"metadata,omitempty"` // Additional JSON serializable structured data. Details json.RawMessage `json:"details,omitempty"` }
A Failure represents failed handler invocations as well as `failed` or `canceled` operation results.
type GetOperationInfoOptions ¶
type GetOperationInfoOptions struct { // Header contains the request header fields either received by the server or to be sent by the client. // // Header will always be non empty in server methods and can be optionally set in the client API. Header Header }
GetOperationInfoOptions are options for the GetOperationInfo client and server APIs.
type GetOperationResultOptions ¶
type GetOperationResultOptions struct { // Header contains the request header fields either received by the server or to be sent by the client. // // Header will always be non empty in server methods and can be optionally set in the client API. Header Header // If non-zero, reflects the duration the caller has indicated that it wants to wait for operation completion, // turning the request into a long poll. Wait time.Duration }
GetOperationResultOptions are options for the GetOperationResult client and server APIs.
type Handler ¶
type Handler interface { // StartOperation handles requests for starting an operation. Return [HandlerStartOperationResultSync] to // respond successfully - inline, or [HandlerStartOperationResultAsync] to indicate that an asynchronous // operation was started. Return an [UnsuccessfulOperationError] to indicate that an operation completed as // failed or canceled. StartOperation(ctx context.Context, operation string, input *LazyValue, options StartOperationOptions) (HandlerStartOperationResult[any], error) // GetOperationResult handles requests to get the result of an asynchronous operation. Return non error result // to respond successfully - inline, or error with [ErrOperationStillRunning] to indicate that an asynchronous // operation is still running. Return an [UnsuccessfulOperationError] to indicate that an operation completed as // failed or canceled. // // When [GetOperationResultOptions.Wait] is greater than zero, this request should be treated as a long poll. // Long poll requests have a server side timeout, configurable via [HandlerOptions.GetResultTimeout], and exposed // via context deadline. The context deadline is decoupled from the application level Wait duration. // // It is the implementor's responsiblity to respect the client's wait duration and return in a timely fashion. // Consider using a derived context that enforces the wait timeout when implementing this method and return // [ErrOperationStillRunning] when that context expires as shown in the example. GetOperationResult(ctx context.Context, operation, operationID string, options GetOperationResultOptions) (any, error) // GetOperationInfo handles requests to get information about an asynchronous operation. GetOperationInfo(ctx context.Context, operation, operationID string, options GetOperationInfoOptions) (*OperationInfo, error) // CancelOperation handles requests to cancel an asynchronous operation. // Cancelation in Nexus is: // 1. asynchronous - returning from this method only ensures that cancelation is delivered, it may later be // ignored by the underlying operation implemention. // 2. idempotent - implementors should ignore duplicate cancelations for the same operation. CancelOperation(ctx context.Context, operation, operationID string, options CancelOperationOptions) error // contains filtered or unexported methods }
A Handler must implement all of the Nexus service endpoints as defined in the Nexus HTTP API.
Handler implementations must embed the UnimplementedHandler.
All Handler methods can return a HandlerError to fail requests with a custom HandlerErrorType and structured Failure. Arbitrary errors from handler methods are turned into HandlerErrorTypeInternal,their details are logged and hidden from the caller.
Example ¶
package main import ( "context" "net" "net/http" "time" "github.com/nexus-rpc/sdk-go/nexus" ) type myHandler struct { nexus.UnimplementedHandler } type MyResult struct { Field string `json:"field"` } // StartOperation implements the Handler interface. func (h *myHandler) StartOperation(ctx context.Context, operation string, input *nexus.LazyValue, options nexus.StartOperationOptions) (nexus.HandlerStartOperationResult[any], error) { if err := h.authorize(ctx, options.Header); err != nil { return nil, err } return &nexus.HandlerStartOperationResultAsync{OperationID: "meaningful-id"}, nil } // GetOperationResult implements the Handler interface. func (h *myHandler) GetOperationResult(ctx context.Context, operation, operationID string, options nexus.GetOperationResultOptions) (any, error) { if err := h.authorize(ctx, options.Header); err != nil { return nil, err } if options.Wait > 0 { // request is a long poll var cancel context.CancelFunc ctx, cancel = context.WithTimeout(ctx, options.Wait) defer cancel() result, err := h.pollOperation(ctx, options.Wait) if err != nil { // Translate deadline exceeded to "OperationStillRunning", this may or may not be semantically correct for // your application. // Some applications may want to "peek" the current status instead of performing this blind conversion if // the wait time is exceeded and the request's context deadline has not yet exceeded. if ctx.Err() != nil { return nil, nexus.ErrOperationStillRunning } // Optionally translate to operation failure (could also result in canceled state). // Optionally expose the error details to the caller. return nil, &nexus.UnsuccessfulOperationError{State: nexus.OperationStateFailed, Failure: nexus.Failure{Message: err.Error()}} } return result, nil } else { result, err := h.peekOperation(ctx) if err != nil { // Optionally translate to operation failure (could also result in canceled state). return nil, &nexus.UnsuccessfulOperationError{State: nexus.OperationStateFailed, Failure: nexus.Failure{Message: err.Error()}} } return result, nil } } func (h *myHandler) CancelOperation(ctx context.Context, operation, operationID string, options nexus.CancelOperationOptions) error { // Handlers must implement this. panic("unimplemented") } func (h *myHandler) GetOperationInfo(ctx context.Context, operation, operationID string, options nexus.GetOperationInfoOptions) (*nexus.OperationInfo, error) { // Handlers must implement this. panic("unimplemented") } func (h *myHandler) pollOperation(ctx context.Context, wait time.Duration) (*MyResult, error) { panic("unimplemented") } func (h *myHandler) peekOperation(ctx context.Context) (*MyResult, error) { panic("unimplemented") } func (h *myHandler) authorize(ctx context.Context, header nexus.Header) error { // Authorization for demo purposes if header.Get("Authorization") != "Bearer top-secret" { return &nexus.HandlerError{Type: nexus.HandlerErrorTypeForbidden, Failure: &nexus.Failure{Message: "Unauthorized"}} } return nil } func main() { handler := &myHandler{} httpHandler := nexus.NewHTTPHandler(nexus.HandlerOptions{Handler: handler}) listener, _ := net.Listen("tcp", "localhost:0") defer listener.Close() _ = http.Serve(listener, httpHandler) }
Output:
type HandlerError ¶
type HandlerError struct { // Defaults to HandlerErrorTypeInternal Type HandlerErrorType // Failure to report back in the response. Optional. Failure *Failure }
HandlerError is a special error that can be returned from Handler methods for failing a request with a custom status code and failure message.
func HandlerErrorf ¶ added in v0.0.2
func HandlerErrorf(typ HandlerErrorType, format string, args ...any) *HandlerError
HandlerErrorf creates a HandlerError with the given type and a formatted failure message.
func (*HandlerError) Error ¶
func (e *HandlerError) Error() string
Error implements the error interface.
type HandlerErrorType ¶ added in v0.0.2
type HandlerErrorType string
const ( // An internal error occured. HandlerErrorTypeInternal HandlerErrorType = "INTERNAL" HandlerErrorTypeUnavailable HandlerErrorType = "UNAVAILABLE" // Used by gateways to report that a downstream server has responded with an error. HandlerErrorTypeDownstreamError HandlerErrorType = "DOWNSTREAM_ERROR" // Used by gateways to report that a request to a downstream server has timed out. HandlerErrorTypeDownstreamTimeout HandlerErrorType = "DOWNSTREAM_TIMEOUT" // The client did not supply valid authentication credentials for this request. HandlerErrorTypeUnauthenticated HandlerErrorType = "UNAUTHENTICATED" // The caller does not have permission to execute the specified operation. HandlerErrorTypeForbidden HandlerErrorType = "UNAUTHORIZED" // Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system is out of space. HandlerErrorTypeResourceExhausted HandlerErrorType = "RESOURCE_EXHAUSTED" // The server cannot or will not process the request due to an apparent client error. HandlerErrorTypeBadRequest HandlerErrorType = "BAD_REQUEST" // The requested resource could not be found but may be available in the future. Subsequent requests by the client // are permissible. HandlerErrorTypeNotFound HandlerErrorType = "NOT_FOUND" // The server either does not recognize the request method, or it lacks the ability to fulfill the request. HandlerErrorTypeNotImplemented HandlerErrorType = "NOT_IMPLEMENTED" )
type HandlerOptions ¶
type HandlerOptions struct { // Handler for handling service requests. Handler Handler // A stuctured logger. // Defaults to slog.Default(). Logger *slog.Logger // Max duration to allow waiting for a single get result request. // Enforced if provided for requests with the wait query parameter set. // // Defaults to one minute. GetResultTimeout time.Duration // A [Serializer] to customize handler serialization behavior. // By default the handler handles, JSONables, byte slices, and nil. Serializer Serializer }
HandlerOptions are options for NewHTTPHandler.
type HandlerStartOperationResult ¶ added in v0.0.2
type HandlerStartOperationResult[T any] interface { // contains filtered or unexported methods }
An HandlerStartOperationResult is the return type from the Handler StartOperation and Operation Start methods. It has two implementations: HandlerStartOperationResultSync and HandlerStartOperationResultAsync.
type HandlerStartOperationResultAsync ¶ added in v0.0.2
type HandlerStartOperationResultAsync struct {
OperationID string
}
HandlerStartOperationResultAsync indicates that an operation has been accepted and will complete asynchronously.
type HandlerStartOperationResultSync ¶ added in v0.0.2
type HandlerStartOperationResultSync[T any] struct { Value T }
HandlerStartOperationResultSync indicates that an operation completed successfully.
type Header ¶ added in v0.0.2
Header is a mapping of string to string. It is used throughout the framework to transmit metadata.
type LazyValue ¶ added in v0.0.2
type LazyValue struct { Reader *Reader // contains filtered or unexported fields }
A LazyValue holds a value encoded in an underlying Reader.
⚠️ When a LazyValue is returned from a client - if directly accessing the Reader - it must be read it in its entirety and closed to free up the associated HTTP connection. Otherwise the LazyValue.Consume method must be called.
⚠️ When a LazyValue is passed to a server handler, it must not be used after the returning from the handler method.
type NoValue ¶ added in v0.0.2
type NoValue *struct{}
NoValue is a marker type for an operations that do not accept any input or return a value (nil).
nexus.NewSyncOperation("my-empty-operation", func(context.Context, nexus.NoValue, options, nexus.StartOperationOptions) (nexus.NoValue, error) { return nil, nil )}
type Operation ¶ added in v0.0.2
type Operation[I, O any] interface { RegisterableOperation OperationReference[I, O] // Start handles requests for starting an operation. Return [HandlerStartOperationResultSync] to respond // successfully - inline, or [HandlerStartOperationResultAsync] to indicate that an asynchronous operation was // started. Return an [UnsuccessfulOperationError] to indicate that an operation completed as failed or // canceled. Start(context.Context, I, StartOperationOptions) (HandlerStartOperationResult[O], error) // GetResult handles requests to get the result of an asynchronous operation. Return non error result to respond // successfully - inline, or error with [ErrOperationStillRunning] to indicate that an asynchronous operation is // still running. Return an [UnsuccessfulOperationError] to indicate that an operation completed as failed or // canceled. // // When [GetOperationResultOptions.Wait] is greater than zero, this request should be treated as a long poll. // Long poll requests have a server side timeout, configurable via [HandlerOptions.GetResultTimeout], and exposed // via context deadline. The context deadline is decoupled from the application level Wait duration. // // It is the implementor's responsiblity to respect the client's wait duration and return in a timely fashion. // Consider using a derived context that enforces the wait timeout when implementing this method and return // [ErrOperationStillRunning] when that context expires as shown in the [Handler] example. GetResult(context.Context, string, GetOperationResultOptions) (O, error) // GetInfo handles requests to get information about an asynchronous operation. GetInfo(context.Context, string, GetOperationInfoOptions) (*OperationInfo, error) // Cancel handles requests to cancel an asynchronous operation. // Cancelation in Nexus is: // 1. asynchronous - returning from this method only ensures that cancelation is delivered, it may later be // ignored by the underlying operation implemention. // 2. idempotent - implementors should ignore duplicate cancelations for the same operation. Cancel(context.Context, string, CancelOperationOptions) error }
Operation is a handler for a single operation.
Operation implementations must embed the UnimplementedOperation.
All Operation methods can return a HandlerError to fail requests with a custom HandlerErrorType and structured Failure. Arbitrary errors from handler methods are turned into HandlerErrorTypeInternal,their details are logged and hidden from the caller.
func NewSyncOperation ¶ added in v0.0.2
func NewSyncOperation[I, O any](name string, handler func(context.Context, I, StartOperationOptions) (O, error)) Operation[I, O]
NewSyncOperation is a helper for creating a synchronous-only Operation from a given name and handler function.
type OperationCompletion ¶
type OperationCompletion interface {
// contains filtered or unexported methods
}
OperationCompletion is input for NewCompletionHTTPRequest. It has two implementations: OperationCompletionSuccessful and OperationCompletionUnsuccessful.
type OperationCompletionSuccessful ¶
type OperationCompletionSuccessful struct { // Header to send in the completion request. Header http.Header // Body to send in the completion HTTP request. // If it implements `io.Closer` it will automatically be closed by the client. Body io.Reader }
OperationCompletionSuccessful is input for NewCompletionHTTPRequest, used to deliver successful operation results.
func NewOperationCompletionSuccessful ¶
func NewOperationCompletionSuccessful(result any) (*OperationCompletionSuccessful, error)
NewOperationCompletionSuccessful constructs an OperationCompletionSuccessful from a given result. Serializes the provided result using the SDK's default Serializer, which handles JSONables, byte slices and nils.
type OperationCompletionUnsuccessful ¶
type OperationCompletionUnsuccessful struct { // Header to send in the completion request. Header http.Header // State of the operation, should be failed or canceled. State OperationState // Failure object to send with the completion. Failure *Failure }
OperationCompletionUnsuccessful is input for NewCompletionHTTPRequest, used to deliver unsuccessful operation results.
type OperationHandle ¶
type OperationHandle[T any] struct { // Name of the Operation this handle represents. Operation string // Handler generated ID for this handle's operation. ID string // contains filtered or unexported fields }
An OperationHandle is used to cancel operations and get their result and status.
func NewHandle ¶ added in v0.0.2
func NewHandle[I, O any](client *Client, operation OperationReference[I, O], operationID string) (*OperationHandle[O], error)
NewHandle is the type safe version of Client.NewHandle. The [Handle.GetResult] method will return an output of type O.
func (*OperationHandle[T]) Cancel ¶
func (h *OperationHandle[T]) Cancel(ctx context.Context, options CancelOperationOptions) error
Cancel requests to cancel an asynchronous operation.
Cancelation is asynchronous and may be not be respected by the operation's implementation.
func (*OperationHandle[T]) GetInfo ¶
func (h *OperationHandle[T]) GetInfo(ctx context.Context, options GetOperationInfoOptions) (*OperationInfo, error)
GetInfo gets operation information, issuing a network request to the service handler.
func (*OperationHandle[T]) GetResult ¶
func (h *OperationHandle[T]) GetResult(ctx context.Context, options GetOperationResultOptions) (T, error)
GetResult gets the result of an operation, issuing a network request to the service handler.
By default, GetResult returns (nil, ErrOperationStillRunning) immediately after issuing a call if the operation has not yet completed.
Callers may set GetOperationResultOptions.Wait to a value greater than 0 to alter this behavior, causing the client to long poll for the result issuing one or more requests until the provided wait period exceeds, in which case (nil, ErrOperationStillRunning) is returned.
The wait time is capped to the deadline of the provided context. Make sure to handle both context deadline errors and ErrOperationStillRunning.
Note that the wait period is enforced by the server and may not be respected if the server is misbehaving. Set the context deadline to the max allowed wait period to ensure this call returns in a timely fashion.
⚠️ If a LazyValue is returned (as indicated by T), it must be consumed to free up the underlying connection.
type OperationInfo ¶
type OperationInfo struct { // ID of the operation. ID string `json:"id"` // State of the operation. State OperationState `json:"state"` }
OperationInfo conveys information about an operation.
type OperationReference ¶ added in v0.0.2
type OperationReference[I, O any] interface { Name() string // contains filtered or unexported methods }
OperationReference provides a typed interface for invoking operations. Every Operation is also an OperationReference. Callers may create references using NewOperationReference when the implementation is not available.
func NewOperationReference ¶ added in v0.0.2
func NewOperationReference[I, O any](name string) OperationReference[I, O]
NewOperationReference creates an OperationReference with the provided type parameters and name. It provides typed interface for invoking operations when the implementation is not available to the caller.
type OperationRegistry ¶ added in v0.0.2
type OperationRegistry struct {
// contains filtered or unexported fields
}
An OperationRegistry registers operations and constructs a Handler that dispatches requests to those operations.
func (OperationRegistry) NewHandler ¶ added in v0.0.2
func (r OperationRegistry) NewHandler() (Handler, error)
NewHandler creates a Handler that dispatches requests to registered operations based on their name.
func (*OperationRegistry) Register ¶ added in v0.0.2
func (r *OperationRegistry) Register(operations ...RegisterableOperation) error
Register one or more operations. Returns an error if duplicate operations were registered with the same name.
Can be called multiple times and is not thread safe.
type OperationState ¶
type OperationState string
OperationState represents the variable states of an operation.
const ( // "running" operation state. Indicates an operation is started and not yet completed. OperationStateRunning OperationState = "running" // "succeeded" operation state. Indicates an operation completed successfully. OperationStateSucceeded OperationState = "succeeded" // "failed" operation state. Indicates an operation completed as failed. OperationStateFailed OperationState = "failed" // "canceled" operation state. Indicates an operation completed as canceled. OperationStateCanceled OperationState = "canceled" )
type Reader ¶ added in v0.0.2
type Reader struct { // ReaderCloser contains request or response data. May be nil for empty data. io.ReadCloser // Header that should include information on how to deserialize this content. // Headers constructed by the framework always have lower case keys. // User provided keys are considered case-insensitive by the framework. Header Header }
A Reader is a container for a Header and an io.Reader. It is used to stream inputs and outputs in the various client and server APIs.
type RegisterableOperation ¶ added in v0.0.2
type RegisterableOperation interface { // Name of the operation. Used for invocation and registration. Name() string // contains filtered or unexported methods }
A RegisterableOperation is accepted in OperationRegistry.Register. Embed UnimplementedOperation to implement it.
type Serializer ¶ added in v0.0.2
type Serializer interface { // Serialize encodes a value into a [Content]. Serialize(any) (*Content, error) // Deserialize decodes a [Content] into a given reference. Deserialize(*Content, any) error }
Serializer is used by the framework to serialize/deserialize input and output. To customize serialization logic, implement this interface and provide your implementation to framework methods such as NewClient and NewHTTPHandler. By default, the SDK supports serialization of JSONables, byte slices, and nils.
type StartOperationOptions ¶
type StartOperationOptions struct { // Header contains the request header fields either received by the server or to be sent by the client. // // Header will always be non empty in server methods and can be optionally set in the client API. // // Header keys with the "content-" prefix are reserved for [Serializer] headers and should not be set in the // client API; they are not be avaliable to server [Handler] and [Operation] implementations. Header Header // Callbacks are used to deliver completion of async operations. // This value may optionally be set by the client and should be called by a handler upon completion if the started operation is async. // // Implement a [CompletionHandler] and expose it as an HTTP handler to handle async completions. CallbackURL string // Request ID that may be used by the server handler to dedupe a start request. // By default a v4 UUID will be generated by the client. RequestID string }
StartOperationOptions are options for the StartOperation client and server APIs.
type UnexpectedResponseError ¶
type UnexpectedResponseError struct { // Error message. Message string // The HTTP response. The response body will have already been read into memory and does not need to be closed. Response *http.Response // Optional failure that may have been emedded in the HTTP response body. Failure *Failure }
Error that indicates a client encountered something unexpected in the server's response.
func (*UnexpectedResponseError) Error ¶
func (e *UnexpectedResponseError) Error() string
Error implements the error interface.
type UnimplementedHandler ¶
type UnimplementedHandler struct{}
UnimplementedHandler must be embedded into any Handler implementation for future compatibility. It implements all methods on the Handler interface, returning unimplemented errors if they are not implemented by the embedding type.
func (UnimplementedHandler) CancelOperation ¶
func (h UnimplementedHandler) CancelOperation(ctx context.Context, operation, operationID string, options CancelOperationOptions) error
CancelOperation implements the Handler interface.
func (UnimplementedHandler) GetOperationInfo ¶
func (h UnimplementedHandler) GetOperationInfo(ctx context.Context, operation, operationID string, options GetOperationInfoOptions) (*OperationInfo, error)
GetOperationInfo implements the Handler interface.
func (UnimplementedHandler) GetOperationResult ¶
func (h UnimplementedHandler) GetOperationResult(ctx context.Context, operation, operationID string, options GetOperationResultOptions) (any, error)
GetOperationResult implements the Handler interface.
func (UnimplementedHandler) StartOperation ¶
func (h UnimplementedHandler) StartOperation(ctx context.Context, operation string, input *LazyValue, options StartOperationOptions) (HandlerStartOperationResult[any], error)
StartOperation implements the Handler interface.
type UnimplementedOperation ¶ added in v0.0.2
type UnimplementedOperation[I, O any] struct{}
UnimplementedOperation must be embedded into any Operation implementation for future compatibility. It implements all methods on the Operation interface except for `Name`, returning unimplemented errors if they are not implemented by the embedding type.
func (*UnimplementedOperation[I, O]) Cancel ¶ added in v0.0.2
func (*UnimplementedOperation[I, O]) Cancel(context.Context, string, CancelOperationOptions) error
Cancel implements Operation.
func (*UnimplementedOperation[I, O]) GetInfo ¶ added in v0.0.2
func (*UnimplementedOperation[I, O]) GetInfo(context.Context, string, GetOperationInfoOptions) (*OperationInfo, error)
GetInfo implements Operation.
func (*UnimplementedOperation[I, O]) GetResult ¶ added in v0.0.2
func (*UnimplementedOperation[I, O]) GetResult(context.Context, string, GetOperationResultOptions) (O, error)
GetResult implements Operation.
func (*UnimplementedOperation[I, O]) Start ¶ added in v0.0.2
func (h *UnimplementedOperation[I, O]) Start(ctx context.Context, input I, options StartOperationOptions) (HandlerStartOperationResult[O], error)
Start implements Operation.
type UnsuccessfulOperationError ¶
type UnsuccessfulOperationError struct { State OperationState Failure Failure }
UnsuccessfulOperationError represents "failed" and "canceled" operation results.
func (*UnsuccessfulOperationError) Error ¶
func (e *UnsuccessfulOperationError) Error() string
Error implements the error interface.