Documentation ¶
Index ¶
- Constants
- Variables
- func GetAPIErrorCode(e error) int
- func IsAPIError(e error) bool
- type APIError
- type Annotations
- func (m Annotations) Equals(other Annotations) bool
- func (m Annotations) Get(key string) ([]byte, bool)
- func (m Annotations) MergeChange(newVs Annotations) Annotations
- func (m *Annotations) Scan(value interface{}) error
- func (m Annotations) Validate() APIError
- func (m Annotations) Value() (driver.Value, error)
- func (m Annotations) With(key string, data interface{}) (Annotations, error)
- func (m Annotations) Without(key string) Annotations
- type App
- type AppFilter
- type AppWrapper
- type Call
- type CallFilter
- type Config
- type Datastore
- type Error
- type ErrorBody
- type Headers
- type LogStore
- type MessageQueue
- type MilliCPUs
- type Reason
- type Route
- type RouteFilter
- type RouteWrapper
- type Routes
Constants ¶
const ( // TypeNone ... TypeNone = "" // TypeSync ... TypeSync = "sync" // TypeAsync ... TypeAsync = "async" )
const ( // FormatDefault ... FormatDefault = "default" // FormatHTTP ... FormatHTTP = "http" // FormatJSON ... FormatJSON = "json" // FormatCloudEvent ... FormatCloudEvent = "cloudevent" )
const ( MinMilliCPUs = 0 // 0 is unlimited MaxMilliCPUs = 1024000 // 1024 CPUs )
const ( DefaultTimeout = 30 // seconds DefaultIdleTimeout = 30 // seconds DefaultMemory = 128 // MB MaxSyncTimeout = 120 // 2 minutes MaxAsyncTimeout = 3600 // 1 hour MaxIdleTimeout = MaxAsyncTimeout )
Variables ¶
var ( ErrInvalidJSON = err{ // contains filtered or unexported fields } ErrCallTimeout = err{ // contains filtered or unexported fields } ErrCallTimeoutServerBusy = err{ // contains filtered or unexported fields } ErrAppsMissingName = err{ // contains filtered or unexported fields } ErrAppsTooLongName = err{ // contains filtered or unexported fields } ErrAppsInvalidName = err{ // contains filtered or unexported fields } ErrAppsAlreadyExists = err{ // contains filtered or unexported fields } ErrAppsMissingNew = err{ // contains filtered or unexported fields } ErrAppsNameImmutable = err{ // contains filtered or unexported fields } ErrAppsNotFound = err{ // contains filtered or unexported fields } ErrDeleteAppsWithRoutes = err{ // contains filtered or unexported fields } ErrDatastoreEmptyApp = err{ // contains filtered or unexported fields } ErrDatastoreEmptyAppID = err{ // contains filtered or unexported fields } ErrDatastoreEmptyRoute = err{ // contains filtered or unexported fields } ErrDatastoreEmptyKey = err{ // contains filtered or unexported fields } ErrDatastoreEmptyCallID = err{ // contains filtered or unexported fields } ErrInvalidPayload = err{ // contains filtered or unexported fields } ErrRoutesAlreadyExists = err{ // contains filtered or unexported fields } ErrRoutesMissingNew = err{ // contains filtered or unexported fields } ErrRoutesNotFound = err{ // contains filtered or unexported fields } ErrRoutesPathImmutable = err{ // contains filtered or unexported fields } ErrFoundDynamicURL = err{ // contains filtered or unexported fields } ErrRoutesInvalidPath = err{ // contains filtered or unexported fields } ErrRoutesInvalidType = err{ // contains filtered or unexported fields } ErrRoutesInvalidFormat = err{ // contains filtered or unexported fields } ErrRoutesMissingAppID = err{ // contains filtered or unexported fields } ErrRoutesMissingImage = err{ // contains filtered or unexported fields } ErrRoutesMissingName = err{ // contains filtered or unexported fields } ErrRoutesMissingPath = err{ // contains filtered or unexported fields } ErrRoutesMissingType = err{ // contains filtered or unexported fields } ErrPathMalformed = err{ // contains filtered or unexported fields } ErrInvalidToTime = err{ // contains filtered or unexported fields } ErrInvalidFromTime = err{ // contains filtered or unexported fields } ErrRoutesInvalidTimeout = err{ // contains filtered or unexported fields } ErrRoutesInvalidIdleTimeout = err{ // contains filtered or unexported fields } ErrRoutesInvalidMemory = err{ // contains filtered or unexported fields } ErrCallNotFound = err{ // contains filtered or unexported fields } ErrCallLogNotFound = err{ // contains filtered or unexported fields } ErrInvokeNotSupported = err{ // contains filtered or unexported fields } ErrAPINotSupported = err{ // contains filtered or unexported fields } ErrPathNotFound = err{ // contains filtered or unexported fields } ErrInvalidCPUs = err{ // contains filtered or unexported fields } ErrFunctionResponseTooBig = err{ // contains filtered or unexported fields } ErrInvalidAnnotationKey = err{ // contains filtered or unexported fields } ErrInvalidAnnotationKeyLength = err{ // contains filtered or unexported fields } ErrInvalidAnnotationValue = err{ // contains filtered or unexported fields } ErrInvalidAnnotationValueLength = err{ // contains filtered or unexported fields } ErrTooManyAnnotationKeys = err{ // contains filtered or unexported fields } )
var RouteMaxMemory = uint64(8 * 1024)
Functions ¶
func GetAPIErrorCode ¶
func IsAPIError ¶
Types ¶
type APIError ¶
APIError any error that implements this interface will return an API response with the provided status code and error message body
func NewAPIError ¶
type Annotations ¶
type Annotations map[string]*annotationValue
Annotations encapsulates key-value metadata associated with resource. The structure is immutable via its public API and nil-safe for its contract permissive nilability is here to simplify updates and reduce the need for nil handling in extensions - annotations should be updated by over-writing the original object:
target.Annotations = target.Annotations.With("fooKey",1)
old MD remains empty Annotations is lenable
func EmptyAnnotations ¶
func EmptyAnnotations() Annotations
func (Annotations) Equals ¶
func (m Annotations) Equals(other Annotations) bool
Equals is defined based on un-ordered k/v comparison at of the annotation keys and (compacted) values of annotations, JSON object-value equality for values is property-order dependent
func (Annotations) Get ¶
func (m Annotations) Get(key string) ([]byte, bool)
Get returns a raw JSON value of a annotation key
func (Annotations) MergeChange ¶
func (m Annotations) MergeChange(newVs Annotations) Annotations
MergeChange merges a delta (possibly including deletes) with an existing annotations object and returns a new (copy) annotations object or an error. This assumes that both old and new annotations objects contain only valid keys and only newVs may contain deletes
func (*Annotations) Scan ¶
func (m *Annotations) Scan(value interface{}) error
Scan implements sql.Scanner
func (Annotations) Validate ¶
func (m Annotations) Validate() APIError
Validate validates a final annotations object prior to store, This will reject partial/patch changes with empty values (containing deletes)
func (Annotations) Value ¶
func (m Annotations) Value() (driver.Value, error)
Value implements sql.Valuer, returning a string
func (Annotations) With ¶
func (m Annotations) With(key string, data interface{}) (Annotations, error)
With Creates a new annotations object containing the specified value - this does not perform size checks on the total number of keys this validates the correctness of the key and value. this returns a new the annotations object with the key set.
func (Annotations) Without ¶
func (m Annotations) Without(key string) Annotations
Without returns a new annotations object with a value excluded
type App ¶
type App struct { ID string `json:"id" db:"id"` Name string `json:"name" db:"name"` Config Config `json:"config,omitempty" db:"config"` Annotations Annotations `json:"annotations,omitempty" db:"annotations"` CreatedAt strfmt.DateTime `json:"created_at,omitempty" db:"created_at"` UpdatedAt strfmt.DateTime `json:"updated_at,omitempty" db:"updated_at"` }
func (*App) SetDefaults ¶
func (a *App) SetDefaults()
type AppFilter ¶
type AppFilter struct { Name string // NameIn will filter by all names in the list (IN query) NameIn []string PerPage int Cursor string }
AppFilter is the filter used for querying apps
type AppWrapper ¶
type AppWrapper struct {
App *App `json:"app"`
}
func (*AppWrapper) Validate ¶
func (m *AppWrapper) Validate() error
type Call ¶
type Call struct { // Unique identifier representing a specific call. ID string `json:"id" db:"id"` // NOTE: this is stale, retries are not implemented atm, but this is nice, so leaving // States and valid transitions. // // +---------+ // +---------> delayed <----------------+ // +----+----+ | // | | // | | // +----v----+ | // +---------> queued <----------------+ // +----+----+ * // | * // | retry * creates new call // +----v----+ * // | running | * // +--+-+-+--+ | // +---------|-|-|-----+-------------+ // +---|---------+ | +-----|---------+ | // | | | | | | // +-----v---^-+ +--v-------^+ +--v---^-+ // | success | | cancelled | | error | // +-----------+ +-----------+ +--------+ // // * delayed - has a delay. // * queued - Ready to be consumed when it's turn comes. // * running - Currently consumed by a runner which will attempt to process it. // * success - (or complete? success/error is common javascript terminology) // * error - Something went wrong. In this case more information can be obtained // by inspecting the "reason" field. // - timeout // - killed - forcibly killed by worker due to resource restrictions or access // violations. // - bad_exit - exited with non-zero status due to program termination/crash. // * cancelled - cancelled via API. More information in the reason field. // - client_request - Request was cancelled by a client. Status string `json:"status" db:"status"` // Path of the route that is responsible for this call Path string `json:"path" db:"path"` // Name of Docker image to use. Image string `json:"image,omitempty" db:"-"` // Number of seconds to wait before queueing the call for consumption for the // first time. Must be a positive integer. Calls with a delay start in state // "delayed" and transition to "running" after delay seconds. Delay int32 `json:"delay,omitempty" db:"-"` // Type indicates whether a task is to be run synchronously or asynchronously. Type string `json:"type,omitempty" db:"-"` // Format is the format to pass input into the function. Format string `json:"format,omitempty" db:"-"` // Payload for the call. This is only used by async calls, to store their input. // TODO should we copy it into here too for debugging sync? Payload string `json:"payload,omitempty" db:"-"` // Full request url that spawned this invocation. URL string `json:"url,omitempty" db:"-"` // Method of the http request used to make this call. Method string `json:"method,omitempty" db:"-"` // Priority of the call. Higher has more priority. 3 levels from 0-2. Calls // at same priority are processed in FIFO order. Priority *int32 `json:"priority,omitempty" db:"-"` // Maximum runtime in seconds. Timeout int32 `json:"timeout,omitempty" db:"-"` // Hot function idle timeout in seconds before termination. IdleTimeout int32 `json:"idle_timeout,omitempty" db:"-"` // Memory is the amount of RAM this call is allocated. Memory uint64 `json:"memory,omitempty" db:"-"` // CPU as in MilliCPUs where each CPU core is split into 1000 units, specified either // *) milliCPUs as "100m" which is 1/10 of a CPU or // *) as floating point number "0.1" which is 1/10 of a CPU CPUs MilliCPUs `json:"cpus,omitempty" db:"-"` // Config is the set of configuration variables for the call Config Config `json:"config,omitempty" db:"-"` // Annotations is the set of annotations for the app/route of the call. Annotations Annotations `json:"annotations,omitempty" db:"-"` // Headers are headers from the request that created this call Headers http.Header `json:"headers,omitempty" db:"-"` // Time when call completed, whether it was successul or failed. Always in UTC. CompletedAt strfmt.DateTime `json:"completed_at,omitempty" db:"completed_at"` // Time when call was submitted. Always in UTC. CreatedAt strfmt.DateTime `json:"created_at,omitempty" db:"created_at"` // Time when call started execution. Always in UTC. StartedAt strfmt.DateTime `json:"started_at,omitempty" db:"started_at"` // Stats is a list of metrics from this call's execution, possibly empty. Stats drivers.Stats `json:"stats,omitempty" db:"stats"` // Error is the reason why the call failed, it is only non-empty if // status is equal to "error". Error string `json:"error,omitempty" db:"error"` // App this call belongs to. AppID string `json:"app_id" db:"app_id"` }
Call is a representation of a specific invocation of a route.
type CallFilter ¶
type Datastore ¶
type Datastore interface { // GetAppByID gets an App by ID. // Returns ErrDatastoreEmptyAppID for empty appID. // Returns ErrAppsNotFound if no app is found. GetAppByID(ctx context.Context, appID string) (*App, error) // GetAppID gets an app ID by app name, ensures if app exists. // Returns ErrDatastoreEmptyAppName for empty appName. // Returns ErrAppsNotFound if no app is found. GetAppID(ctx context.Context, appName string) (string, error) // GetApps gets a slice of Apps, optionally filtered by name. // Missing filter or empty name will match all Apps. GetApps(ctx context.Context, filter *AppFilter) ([]*App, error) // InsertApp inserts an App. Returns ErrDatastoreEmptyApp when app is nil, and // ErrDatastoreEmptyAppName when app.Name is empty. // Returns ErrAppsAlreadyExists if an App by the same name already exists. InsertApp(ctx context.Context, app *App) (*App, error) // UpdateApp updates an App's Config. Returns ErrDatastoreEmptyApp when app is nil, and // ErrDatastoreEmptyAppName when app.Name is empty. // Returns ErrAppsNotFound if an App is not found. UpdateApp(ctx context.Context, app *App) (*App, error) // RemoveApp removes the App named appName. Returns ErrDatastoreEmptyAppName if appName is empty. // Returns ErrAppsNotFound if an App is not found. RemoveApp(ctx context.Context, appID string) error // GetRoute looks up a matching Route for appName and the literal request route routePath. // Returns ErrDatastoreEmptyAppName when appName is empty, and ErrDatastoreEmptyRoutePath when // routePath is empty. // Returns ErrRoutesNotFound when no matching route is found. GetRoute(ctx context.Context, appID, routePath string) (*Route, error) // GetRoutesByApp gets a slice of routes for a appName, optionally filtering on filter (filter.AppName is ignored). // Returns ErrDatastoreEmptyAppName if appName is empty. GetRoutesByApp(ctx context.Context, appID string, filter *RouteFilter) ([]*Route, error) // InsertRoute inserts a route. Returns ErrDatastoreEmptyRoute when route is nil, and ErrDatastoreEmptyAppName // or ErrDatastoreEmptyRoutePath for empty AppName or Path. // Returns ErrRoutesAlreadyExists if the exact route.Path already exists InsertRoute(ctx context.Context, route *Route) (*Route, error) // UpdateRoute updates route's Config and Header fields. Returns ErrDatastoreEmptyRoute when route is nil, and // ErrDatastoreEmptyAppName or ErrDatastoreEmptyRoutePath for empty AppName or Path. UpdateRoute(ctx context.Context, route *Route) (*Route, error) // RemoveRoute removes a route. Returns ErrDatastoreEmptyAppID when appName is empty, and // ErrDatastoreEmptyRoutePath when routePath is empty. Returns ErrRoutesNotFound when no route exists. RemoveRoute(ctx context.Context, appID, routePath string) error // Implement LogStore methods for convenience LogStore // GetDatabase returns the underlying sqlx database implementation GetDatabase() *sqlx.DB }
type Error ¶
type Error struct {
Error *ErrorBody `json:"error,omitempty"`
}
Error uniform error output
type ErrorBody ¶
type LogStore ¶
type LogStore interface { // InsertLog will insert the log at callID, overwriting if it previously // existed. InsertLog(ctx context.Context, appID, callID string, callLog io.Reader) error // GetLog will return the log at callID, an error will be returned if the log // cannot be found. GetLog(ctx context.Context, appID, callID string) (io.Reader, error) // InsertCall inserts a call into the datastore, it will error if the call already // exists. InsertCall(ctx context.Context, call *Call) error // GetCall returns a call at a certain id and app name. GetCall(ctx context.Context, appName, callID string) (*Call, error) // GetCalls returns a list of calls that satisfy the given CallFilter. If no // calls exist, an empty list and a nil error are returned. GetCalls(ctx context.Context, filter *CallFilter) ([]*Call, error) }
type MessageQueue ¶
type MessageQueue interface { // Push a call onto the queue. If any error is returned, the call SHOULD not be // queued. Note that this does not completely avoid double queueing, that is // OK, a check against the datastore will be performed after a dequeue. // // If the job's Delay value is > 0, the job should NOT be enqueued. The job // should only be available in the queue after at least Delay seconds have // elapsed. No ordering is required among multiple jobs queued with similar // delays. That is, if jobs {A, C} are queued at t seconds, both with Delay // = 5 seconds, and the same priority, then they may be available on the // queue as [C, A] or [A, C]. Push(context.Context, *Call) (*Call, error) // Remove a job from the front of the queue, reserve it for a timeout and // return it. MQ implementations MUST NOT lose jobs in case of errors. That // is, in case of reservation failure, it should be possible to retrieve the // job on a future reservation. Reserve(context.Context) (*Call, error) // If a reservation is pending, consider it acknowledged and delete it. If // the job does not have an outstanding reservation, error. If a job did not // exist, succeed. Delete(context.Context, *Call) error }
When a job is required to be restored to the queue, it should maintain it's approximate order in the queue. That is, for jobs [A, B, C], with A being the head of the queue: Reserve() leads to A being passed to a consumer, and timeout started. Next Reserve() leads to B being dequeued. This consumer finishes running the call, leading to Delete() being called. B is now permanently erased from the queue. A's timeout occurs before the job is finished. At this point the ordering should be [A, C] and not [C, A].
type MilliCPUs ¶
type MilliCPUs uint64
MilliCPU units
func (*MilliCPUs) MarshalJSON ¶
implements json.Marshaler
func (*MilliCPUs) UnmarshalJSON ¶
implements json.Unmarshaler
type Reason ¶
type Reason string
Reason Machine usable reason for job being in this state. Valid values for error status are `timeout | killed | bad_exit`. Valid values for cancelled status are `client_request`. For everything else, this is undefined.
swagger:model Reason
type Route ¶
type Route struct { AppID string `json:"app_id" db:"app_id"` Path string `json:"path" db:"path"` Image string `json:"image" db:"image"` Memory uint64 `json:"memory" db:"memory"` CPUs MilliCPUs `json:"cpus" db:"cpus"` Headers Headers `json:"headers,omitempty" db:"headers"` Type string `json:"type" db:"type"` Format string `json:"format" db:"format"` Timeout int32 `json:"timeout" db:"timeout"` IdleTimeout int32 `json:"idle_timeout" db:"idle_timeout"` Config Config `json:"config,omitempty" db:"config"` Annotations Annotations `json:"annotations,omitempty" db:"annotations"` CreatedAt strfmt.DateTime `json:"created_at,omitempty" db:"created_at"` UpdatedAt strfmt.DateTime `json:"updated_at,omitempty" db:"updated_at"` }
func (*Route) SetDefaults ¶
func (r *Route) SetDefaults()
SetDefaults sets zeroed field to defaults.
type RouteFilter ¶
type RouteWrapper ¶
type RouteWrapper struct {
Route *Route `json:"route"`
}
func (*RouteWrapper) Validate ¶
func (m *RouteWrapper) Validate() error