base

package module
v2.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 21, 2022 License: MIT Imports: 15 Imported by: 13

Documentation

Overview

This package contains shared utility functions for HMS Go code.

HMS Type and Component Definitions

These are functions that define common types that are used to describe HMS component data that represents system components and valid values for that data.

HMS Errors and RFC 7807 ProblemDetails RFC 7807 ProblemDetails">¶

These are common methods for defining a custom HMS error type and producing RFC 7807-compliant ProblemDetails payloads for reporting problems that occur during HMS API calls.

Index

Constants

View Source
const HMSErrorUnsetDefault = "no error message or class set"
View Source
const ProblemDetailContentType = "application/problem+json"
View Source
const ProblemDetailsHTTPStatusType = "about:blank"
View Source
const USERAGENT = "User-Agent"

Variables

View Source
var ErrHMSNeedForce = e.NewChild("operation not allowed and not forced.")
View Source
var ErrHMSStateInvalid = e.NewChild("was not a valid HMS state")
View Source
var ErrHMSStateUnsupported = e.NewChild("HMSState value not supported for this operation")
View Source
var ErrHMSTypeInvalid = e.NewChild("got HMSTypeInvalid instead of valid type")
View Source
var ErrHMSTypeUnsupported = e.NewChild("HMSType value not supported for this operation") // TODO should this be in base?
View Source
var JStatString = map[JobStatus]string{
	JSTAT_DEFAULT:    "JSTAT_DEFAULT",
	JSTAT_QUEUED:     "JSTAT_QUEUED",
	JSTAT_PROCESSING: "JSTAT_PROCESSING",
	JSTAT_COMPLETE:   "JSTAT_COMPLETE",
	JSTAT_CANCELLED:  "JSTAT_CANCELLED",
	JSTAT_ERROR:      "JSTAT_ERROR",
	JSTAT_MAX:        "JSTAT_MAX",
}

Functions

func GetHMSArchList

func GetHMSArchList() []string

Get a list of all valid HMS Arch

func GetHMSClassList

func GetHMSClassList() []string

Get a list of all valid HMS Class

func GetHMSFlagList

func GetHMSFlagList() []string

Get a list of all valid HMS flags

func GetHMSNetTypeList

func GetHMSNetTypeList() []string

Get a list of all valid HMS NetTypes

func GetHMSRoleList

func GetHMSRoleList() []string

Get a list of all valid HMS roles

func GetHMSStateList

func GetHMSStateList() []string

func GetHMSSubRoleList

func GetHMSSubRoleList() []string

Get a list of all valid HMS subroles

func GetServiceInstanceName

func GetServiceInstanceName() (string, error)

func GetValidStartStateWForce

func GetValidStartStateWForce(
	afterState string,
	force bool,
) (beforeStates []string, err error)

Same as above, but with force flag. If not found, returns ErrHMSStateInvalid. If can only be forced, and force = false, error will be ErrHMSNeedForce. Otherwise list of starting states. If force = true and no errors, an empty array means no restrictions.

func GetValidStartStates

func GetValidStartStates(afterState string) (beforeStates []string, ok bool)

If ok == true, beforeStates contain valid current states a component can be in if it is being transitioned to afterState without being forced (either because it is a bad idea, or the state should only be set by HSM and not by other software). An empty array means 'None without force=true

If ok == false, afterState matched no valid HMS State (case insensitive)

func InitTypes

func InitTypes(configpath string) error

main

func IsAlphaNum

func IsAlphaNum(s string) bool

Returns true if s is alphanumeric only (only letters and numbers, no punctuation or spaces.

func IsHMSError

func IsHMSError(err error) bool

See if an error (some thing implementing Error() interface is an HMSError

Returns 'true' if err is HMSError Returns 'false' if err is something else that implements Error()

func IsHMSErrorClass

func IsHMSErrorClass(err error, class string) bool

Returns false if 'err' is not an HMSError, or, if it is, if 'class' doesn't match the HMSError's Class field.

func IsHMSErrorClassIgnCase

func IsHMSErrorClassIgnCase(err error, class string) bool

Returns false if 'err' is not an HMSError, or, if it is, if 'class' doesn't match the HMSError's Class field (case insensitive).

func IsNumeric

func IsNumeric(s string) bool

Returns true if s is numeric only (only numbers, no letters, punctuation or spaces.

func IsPostBootState

func IsPostBootState(stateStr string) bool

Check to see if the state is above on (on is the highest we will get from Redfish, so these are state set by higher software layers)

func RemoveLeadingZeros

func RemoveLeadingZeros(s string) string

Remove leading zeros, i.e. for each run of numbers, trim off leading zeros so each run starts with either non-zero, or is a single zero.

func SendProblemDetails

func SendProblemDetails(w http.ResponseWriter, p *ProblemDetails, status int) error

Send specially-coded RFC7807 Problem Details response. A set ProblemDetails struct is expected ('p') and should always contain at least Type to conform to the spec (we will always print the Type field, but it would contain the empty string if unset which isn't technically valid for the spec.

The HTTP status code in the header is set to the 'status' arg if it is NON-zero. If 'status' = 0, then 'p'.Status will be used. If that is unset (i.e. 0) also, we will use a default error code of 400.

For example:

p := base.NewProblemDetails(
    "https://example.com/probs/MyProblem",
    "My Problem's Title",
    "Detail for this problem",
    "/instances/myprob/1",
    http.StatusConflict)  // 409
...
if err != nil {
   base.SendProblemDetails(w, p, 0)
   return
}

...will include the following in the response header:

HTTP/1.1 409 Conflict
Content-Type: application/problem+json

With the following body:

{
   "Type": "https://example.com/probs/MyProblem",
   "Title": "My Problem's Title",
   "Detail": "Detail for this problem",
   "Instance": "/instances/myprob/1",
   "Status": 409
}

func SendProblemDetailsGeneric

func SendProblemDetailsGeneric(w http.ResponseWriter, status int, msg string) error

Generate and then send a generic RFC 7807 problem response based on a HTTP status code ('status') and a message string ('msg'). This generates a generic title and type based on the HTTP 'status' code. The ProblemDetails "Detail" field is filled in using 'msg'.

If you are already returning just a simple error message and want an easy way to convert this into a basic (but valid) RFC7807 ProblemDetails, this is almost a drop-in replacement.

// If request was for a component that is not in DB, send RFC 7807
// ProblemDetails and exit HTTP handler
err := GetComponentFromDB(component_from_query)
if err != nil {
   base.SendProblemDetailsGeneric(w, http.StatusNotFound, "No such component")
   return
}

The above will include the following in the response header:

HTTP/1.1 404 Not Found
Content-Type: application/problem+json

With the following body:

{
   "Type": "about:blank",
   "Title": "Not Found",
   "Detail": "No such component",
   "Status": 404
}

func SetHTTPUserAgent

func SetHTTPUserAgent(req *http.Request, instName string)

func VerifyNormalizeArch

func VerifyNormalizeArch(archStr string) string

Returns the given arch string (adjusting any capitalization differences), if a valid arch was given. Else, return the empty string.

func VerifyNormalizeClass

func VerifyNormalizeClass(classStr string) string

Returns the given class string (adjusting any capitalization differences), if a valid class was given. Else, return the empty string.

func VerifyNormalizeFlag

func VerifyNormalizeFlag(flagStr string) string

Returns the given flag string (adjusting any capitalization differences), if a valid flag was given. Else, return the empty string.

func VerifyNormalizeFlagOK

func VerifyNormalizeFlagOK(flag string) string

As above, but if flag is the empty string, then return FlagOK. If non-empty and invalid, return the empty string.

func VerifyNormalizeNetType

func VerifyNormalizeNetType(netTypeStr string) string

Returns the given net type string (adjusting any capitalization differences), if a valid netType was given. Else, return the empty string.

func VerifyNormalizeRole

func VerifyNormalizeRole(roleStr string) string

Returns the given role string (adjusting any capitalization differences), if a valid role was given. Else, return the empty string.

func VerifyNormalizeState

func VerifyNormalizeState(stateStr string) string

Returns the given state string (adjusting any capitalization differences), if a valid state is given. Else, return the empty string.

func VerifyNormalizeSubRole

func VerifyNormalizeSubRole(subRoleStr string) string

Returns the given SubRole string (adjusting any capitalization differences), if a valid SubRole was given. Else, return the empty string.

Types

type Auth

type Auth struct {
	Username string
	Password string
}

HTTP basic authentication structure.

func (Auth) String

func (auth Auth) String() string

Custom String function to prevent passwords from being printed directly (accidentally) to output.

type Component

type Component struct {
	ID                  string      `json:"ID"`
	Type                string      `json:"Type"`
	State               string      `json:"State,omitempty"`
	Flag                string      `json:"Flag,omitempty"`
	Enabled             *bool       `json:"Enabled,omitempty"`
	SwStatus            string      `json:"SoftwareStatus,omitempty"`
	Role                string      `json:"Role,omitempty"`
	SubRole             string      `json:"SubRole,omitempty"`
	NID                 json.Number `json:"NID,omitempty"`
	Subtype             string      `json:"Subtype,omitempty"`
	NetType             string      `json:"NetType,omitempty"`
	Arch                string      `json:"Arch,omitempty"`
	Class               string      `json:"Class,omitempty"`
	ReservationDisabled bool        `json:"ReservationDisabled,omitempty"`
	Locked              bool        `json:"Locked,omitempty"`
}

This is the equivalent to rs_node_t in Cascade. It is the minimal amount of of information for tracking component state and other vital info at an abstract level. The hwinv is for component-type specific fields and detailed HW attributes, i.e. just like XC.

For most HMS operations (and non-inventory ones in the managed plane) this info should be sufficient. We want to keep it minimal for speed. Those fields that are not fixed at discovery should be those that can change outside of discovery in response to system activity, i.e. hwinv should contain only fields that are basically static between discoveries of the endpoint. Things like firmware versions might be an exception, but that would be a separate process SM would

1.0.0

type ComponentArray

type ComponentArray struct {
	Components []*Component `json:"Components"`
}

A collection of 0-n Components. It could just be an ordinary array but we want to save the option to have indentifying info, etc. packaged with it, e.g. the query parameters or options that produced it, especially if there are fewer fields than normal being included.

type HMSArch

type HMSArch string
const (
	ArchX86     HMSArch = "X86"
	ArchARM     HMSArch = "ARM"
	ArchUnknown HMSArch = "UNKNOWN"
	ArchOther   HMSArch = "Other"
)

func (HMSArch) String

func (r HMSArch) String() string

Allow HMSArch to be treated as a standard string type.

type HMSClass

type HMSClass string
const (
	ClassRiver    HMSClass = "River"
	ClassMountain HMSClass = "Mountain"
	ClassHill     HMSClass = "Hill"
)

func (HMSClass) String

func (r HMSClass) String() string

Allow HMSClass to be treated as a standard string type.

type HMSError

type HMSError struct {
	// Used to identify similar groups of errors to higher-level software.
	Class string `json:"class"`

	// Message, used as error string for Error()
	Message string `json:"message"`

	// Optional full ProblemDetails
	Problem *ProblemDetails `json:"problem,omitempty"`
}

Custom Go 'error' type for HMS - Implements Error()

Works like a standard Go 'error', but can be distinguished as an HMS-specific error with an optional class for better handling upstream. An RFC7807 error can optionally be added in case we need to pass those through multiple layers- but without forcing us to (since they still look like regular Go errors). Note that this is just a starting point. We can attach other types of info later if we want.

Part of the motivation is so we can determine which errors are safe to return to users, i.e. we don't want to give them things that expose details about the database structure.

Can attach custom RFC7807 response if needed.

func GetHMSError

func GetHMSError(err error) (*HMSError, bool)

Test and retrieve HMSError info, if error is in fact of that type.

If bool is 'true', HMSError will be a non-nil HMSError with the expected extended HMSError fields.

If bool is 'false', err is not an HMSError and *HMSError will be nil

func NewHMSError

func NewHMSError(class, msg string) *HMSError

New HMSError, with message string and optional class.

A subsequent call to AddProblem() can associate a ProblemDetails with it. By default Problem pointer is nil (again, this is optional functionality)

func (*HMSError) AddProblem

func (e *HMSError) AddProblem(p *ProblemDetails)

Add an ProblemDetails to be associated with e

Note: This simply associates the pointer to p with e. There is no new ProblemDetails created and no deep copy is performed.

func (*HMSError) Error

func (e *HMSError) Error() string

Implement Error() interface - This makes it so an HMSError can be returned anywhere an ordinary Go 'error' is returned.

The receiver of an 'error' can then use one of the IsHMSError* or HasHMSError functions to test if it is an HMSError, and if so, to obtain the additional fields.

func (*HMSError) GetProblem

func (e *HMSError) GetProblem() *ProblemDetails

If e has a ProblemDetails associated with it, return a pointer to it If not, return nil.

func (*HMSError) IsClass

func (e *HMSError) IsClass(class string) bool

Return true if 'class' exactly matches Class field for HMSError

func (*HMSError) IsClassIgnCase

func (e *HMSError) IsClassIgnCase(class string) bool

Return true if 'class' matches Class field for HMSError (case insensitive)

func (*HMSError) NewChild

func (e *HMSError) NewChild(msg string) *HMSError

Create a new HMSError that is a copy of e, except with an updated "Message" field if 'msg' is not the empty string. Conversely, if 'msg' IS the empty string, i.e. "", the operation is equivalent to a copy.

Note: This DOES NOT COPY ProblemDetails if added with AddProblem. Instead, use NewChildWithProblem() for cases like this (or if you're unsure).

The (newerr).Problem pointer is always set to nil with this function.

func (*HMSError) NewChildWithProblem

func (e *HMSError) NewChildWithProblem(msg, instance string) *HMSError

Create a newly-allocated child HMSError, deep-copying the parent, including any ProblemDetails that (may) have been associated using AddProblem().

In addition to copying, the 'msg' arg (if non-empty) is used to overwrite HMSError's "Message" and (if ProblemDetails are present) the ProblemDetails "Detail" field is also set to the same string.

The ProblemDetails 'Instance' is also updated if the 'instance' arg is a non-empty string.

If both 'msg' and 'instance' are unset the result is effectively a simple (deep) copy of e (including a deep copy of e.Problem).

This method basically combines the functionality of both the HMSError and ProblemDetails NewChild() functions.

type HMSFlag

type HMSFlag string
const (
	FlagUnknown HMSFlag = "Unknown"
	FlagOK      HMSFlag = "OK"      // Functioning properly
	FlagWarning HMSFlag = "Warning" // Continues to operate, but has an issue that may require attention.
	FlagAlert   HMSFlag = "Alert"   // No longer operating as expected.  The state may also have changed due to error.
	FlagLocked  HMSFlag = "Locked"  // Another service has reserved this component.
)

Valid flag values.

func (HMSFlag) String

func (f HMSFlag) String() string

Allow HMSFlag to be treated as a standard string type.

type HMSNetType

type HMSNetType string
const (
	NetSling      HMSNetType = "Sling"
	NetInfiniband HMSNetType = "Infiniband"
	NetEthernet   HMSNetType = "Ethernet"
	NetOEM        HMSNetType = "OEM" // Placeholder for non-slingshot
	NetNone       HMSNetType = "None"
)

func (HMSNetType) String

func (r HMSNetType) String() string

Allow HMSNetType to be treated as a standard string type.

type HMSRole

type HMSRole string
const (
	RoleCompute     HMSRole = "Compute"
	RoleService     HMSRole = "Service"
	RoleSystem      HMSRole = "System"
	RoleApplication HMSRole = "Application"
	RoleStorage     HMSRole = "Storage"
	RoleManagement  HMSRole = "Management"
)

Valid role values.

func (HMSRole) String

func (r HMSRole) String() string

Allow HMSRole to be treated as a standard string type.

type HMSState

type HMSState string

State field used in component, set in response to events by state manager. 1.0.0

const (
	StateUnknown   HMSState = "Unknown"   // The State is unknown.  Appears missing but has not been confirmed as empty.
	StateEmpty     HMSState = "Empty"     // The location is not populated with a component
	StatePopulated HMSState = "Populated" // Present (not empty), but no further track can or is being done.
	StateOff       HMSState = "Off"       // Present but powered off
	StateOn        HMSState = "On"        // Powered on.  If no heartbeat mechanism is available, it's software state may be unknown.

	StateStandby HMSState = "Standby" // No longer Ready and presumed dead.  It typically means HB has been lost (w/alert).
	StateHalt    HMSState = "Halt"    // No longer Ready and halted.  OS has been gracefully shutdown or panicked (w/ alert).
	StateReady   HMSState = "Ready"   // Both On and Ready to provide its expected services, i.e. used for jobs.

)

Valid state values for components - should refect hardware state Enabled/Disabled is a separate boolean field, as the component should still have it's actual physical state known and tracked at all times, so we know what it is when it is enabled. It also avoids the primary case where admins need to modify the state field manually.

NOTE: there will be no state between on and ready. If the managed plane software does not have heartbeats, On is as high as it will ever get. So "active" is not useful. 'Paused' is not in scope now that the software status field exists.

func (HMSState) String

func (s HMSState) String() string

Allow HMSState to be treated as a standard string type.

type HMSSubRole

type HMSSubRole string
const (
	SubRoleMaster  HMSSubRole = "Master"
	SubRoleWorker  HMSSubRole = "Worker"
	SubRoleStorage HMSSubRole = "Storage"
)

Valid SubRole values.

func (HMSSubRole) String

func (r HMSSubRole) String() string

Allow HMSSubRole to be treated as a standard string type.

type HTTPRequest

type HTTPRequest struct {
	Context            context.Context // Context to pass to the underlying HTTP client.
	FullURL            string          // The full URL to pass to the HTTP client.
	Method             string          // HTTP method to use.
	Payload            []byte          // Bytes payload to pass if desired of ContentType.
	Auth               *Auth           // Basic authentication if necessary using Auth struct.
	Timeout            time.Duration   // Timeout for entire transaction.
	SkipTLSVerify      bool            // Ignore TLS verification errors?
	ExpectedStatusCode int             // Expected HTTP status return code.
	ContentType        string          // HTTP content type of Payload.
}

Package to slightly abstract some of the most mundane of HTTP interactions. Primary intention is as a JSON getter and parser, with the latter being a generic interface that can be converted to a custom structure.

func NewHTTPRequest

func NewHTTPRequest(fullURL string) *HTTPRequest

NewHTTPRequest creates a new HTTPRequest with default settings.

func (*HTTPRequest) DoHTTPAction

func (request *HTTPRequest) DoHTTPAction() (payloadBytes []byte, err error)

Given a HTTPRequest this function will facilitate the desired operation using the retryablehttp package to gracefully retry should the connection fail.

func (*HTTPRequest) GetBodyForHTTPRequest

func (request *HTTPRequest) GetBodyForHTTPRequest() (v interface{}, err error)

Returns an interface for the response body for a given request by calling DoHTTPAction and unmarshaling. As such, do NOT call this method unless you expect a JSON body in return!

A powerful way to use this function is by feeding its result to the mapstructure package's Decode method:

v := request.GetBodyForHTTPRequest()
myTypeInterface := v.(map[string]interface{})
var myPopulatedStruct MyType
mapstructure.Decode(myTypeInterface, &myPopulatedStruct)

In this way you can generically make all your HTTP requests and essentially "cast" the resulting interface to a structure of your choosing using it as normal after that point. Just make sure to infer the correct type for `v`.

func (*HTTPRequest) String

func (request *HTTPRequest) String() string

type Job

type Job interface {
	Log(format string, a ...interface{})
	//New(t JobType)
	Type() JobType
	//JobSCN() JobSCN
	Run()
	GetStatus() (JobStatus, error)
	SetStatus(JobStatus, error) (JobStatus, error)
	Cancel() JobStatus
}

type JobStatus

type JobStatus int
const (
	JSTAT_DEFAULT    JobStatus = 0
	JSTAT_QUEUED     JobStatus = 1
	JSTAT_PROCESSING JobStatus = 2
	JSTAT_COMPLETE   JobStatus = 3
	JSTAT_CANCELLED  JobStatus = 4
	JSTAT_ERROR      JobStatus = 5
	JSTAT_MAX        JobStatus = 6
)

type JobType

type JobType int

type ProblemDetails

type ProblemDetails struct {
	Type     string `json:"type"` // either url or "about:blank"
	Title    string `json:"title,omitempty"`
	Detail   string `json:"detail,omitempty"`
	Instance string `json:"instance,omitempty"`
	Status   int    `json:"status,omitempty"`
}

RFC 7807 Problem Details

These are the officially-specified fields. The implementation is allowed to add new ones, but we'll stick with these for now. Almost all are optional, however, and blank fields are not encoded if they are the empty string (which is fine

The only required field is Type and is expected to be a URL that should describe the problem type when dereferenced. It's not intended to be a dead link, but I don't think clients are allowed to assume it's not, either. We don't implement a way of serving these URLs here, in any case. It's not obligatory to have a lot of different problem types, or even desirable if the client can just andling them all the same basic way.

The only non-URL that is allowed for Type is "about:blank", but only in the situation where the semantics of the problem can be understood okay as a basic HTTP error. In this case Title should be the official HTTP status code string, not something custom. You are free to put anything you want in Detail however, so if you already have an error function that returns an error string, you can easily convert it into one of these generic HTTP errors. In fact, we offer a shortcut to doing this.

If Type is a URL, Title should describe the problem type. If you are doing this, and not just using type:"about:blank" and the HTTP error, for the title, it should be because you have some kind of problem that needs, or could benefit from, special or more involved treatment that the URL describes when dereferenced.

Detail explains in a human readible way what happened when a specific problem occurred.

Instance is another URI describing a specific occurrence of a problem. So within a particular Type and Title (a general problem type) the Detail and Instance document a specific incident in which that problem occurred. Or at least that's the general idea.

Status is the numerical HTTP status code. It is optional, and if present, should match at least the intended HTTP code in the header, though this is not strictly required.

For more info, reading RFC 7807 would obviously be the authoritative source.

func NewProblemDetails

func NewProblemDetails(ptype, title, detail, instance string, status int) *ProblemDetails

New full ProblemDetails, will all fields specified. Type is the only required field, and if any of the other args are left as the empty string, the fields won't appear in the JSON output at all.

p := base.NewProblemDetails(
    "https://example.com/probs/MyProblem",
    "My Problem's Title",
    "Details for this problem",
    "/instances/myprob/1",
    http.StatusBadRequest,
)

func NewProblemDetailsStatus

func NewProblemDetailsStatus(detail string, status int) *ProblemDetails

New generic ProblemDetails for errors that are just based on the HTTP status code. Type and Title are filled in based on the status code.

There is no need for a URL in this case, as the Type is allowed to be "about:blank" if title is just the Status code text and there is no special handling needed beside the usual for that HTTP (error) StatusCode.

NOTE: Status should only be filled in using http.Status* instead of a literal number.

'status' will be treated as http.StatusBadRequest (400) if it does not match a valid http status code.

Example:

p := base.NewProblemDetailsStatus(http.StatusNotFound, "No such component")

Produces a struct p with the following fields

&ProblemDetails{
   Type: "about:blank",
   Title: "Not Found",
   Detail: "No such component",
   Status: 404,
}

func (*ProblemDetails) NewChild

func (p *ProblemDetails) NewChild(detail, instance string) *ProblemDetails

Create a new ProblemDetails struct copied from p with only detail and instance (optionally) updated. If either field is the empty string, it will not be updated and the parent values will be used.

The basic idea here is to be able to define a few prototype ProblemDetails with the Type and Title filled in (along with a default Detail and HTTP Status code, if desired), and then create a child copy when a problem actually occurs with the specific Detail and (optionally) instance URI filled in.

Example:

p := base.NewProblemDetails(
    "https://example.com/probs/MyProblem",
    "My Problem's Title",
    "Generic details for this problem type",
    "/instances/myprobs/",
    http.StatusBadRequest,
)

// Copy updates Detail and instance
pChild := p.NewChild("Specific details for this problem", "/instances/myprobs/1")

// Copy has updated Detail field only
// i.e. p.Instance == pChildDetailOnly.Instance
pChildDetailOnly := p.NewChild("Specific details for this problem", "")

// Strict copy only, new ProblemDetails has identical fields.
pCopy := p.NewChild("", "")

type Worker

type Worker struct {
	WorkerPool  chan chan Job
	JobChannel  chan Job
	StopChannel chan bool
}

///////////////////////////////////////////////////////////////////////////// Workers /////////////////////////////////////////////////////////////////////////////

func NewWorker

func NewWorker(workerPool chan chan Job) Worker

Create a new worker

func (Worker) Start

func (w Worker) Start()

Start a worker to start consuming Jobs

func (Worker) Stop

func (w Worker) Stop()

Send as stop signal to the worker

type WorkerPool

type WorkerPool struct {
	Workers     []Worker
	Pool        chan chan Job
	JobQueue    chan Job
	StopChannel chan bool
}

///////////////////////////////////////////////////////////////////////////// WorkerPool /////////////////////////////////////////////////////////////////////////////

func NewWorkerPool

func NewWorkerPool(maxWorkers, maxJobQueue int) *WorkerPool

Create a new pool of workers

func (*WorkerPool) Queue

func (p *WorkerPool) Queue(job Job) int

Queue a job. Returns 1 if the operation would block because the work queue is full.

func (*WorkerPool) Run

func (p *WorkerPool) Run()

Starts all of the workers and the job dispatcher

func (*WorkerPool) Stop

func (p *WorkerPool) Stop()

Command the dispatcher to stop itself and all workers

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL