eva

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Dec 14, 2018 License: MIT Imports: 6 Imported by: 2

README

EVA

Build Status goreportcard for pshopper/eva godoc for pshopper/eva MIT Licence

Package EVA implements a fixed goroutine pool for managing and recycling a massive number of goroutines with unlimited task queue, allowing developers to limit the number of goroutines that created by your concurrent programs. For example, when processing jobs from HTTP requests that are CPU heavy you can create a pool with a size that matches your CPU count.

Features:

  • Friendly interfaces: submitting tasks, getting the number. of running goroutines, readjusting capacity of pool dynamically, closing pool.
  • Automatically managing and recycling a massive number of goroutines.
  • Availability of overriding the Task or Callable interface.
  • Unlimited task queue.
  • Recover panic in eva.CustomTask.

Installation

    go get github.com/pshopper/eva

Or, using dep:

    dep ensure -add github.com/pshopper/eva

Usage

Async
Simple

    config := &eva.Config{Size: 10, UnstoppableWorkers: 5}
    p := eva.NewPool(&config)

    t := eva.NewCustomTask(func(args ...interface{}) (interface{}, error) {
        // some work here...


        return result, err
    }, args)

    p.Submit(t)

    p.Wait()

    fmt.Printf("Task result=%v; error=%v; panic=%v, t.Get(), t.Error(), t.Panic())

    p.Close()

With completion

    config := &eva.Config{Size: 10, UnstoppableWorkers: 5}
    p := eva.NewPool(&config)

    completion := make(chan eva.Task, 3)

    for i := 0; i < 100; i++ {
        t := eva.NewCustomTask(func(args ...interface{}) (interface{}, error) {
            // some work here...


            return result, err
        }, args)

        p.SubmitWithCompletion(completion, t)
    }


    for i := 0; i < 100; i++ {
        select {
        case t := <-completion:
            fmt.Printf("Task result=%v; error=%v; panic=%v, t.Get(), t.Error(), t.Panic())
        }
    }


    p.Close()

With context

    config := &eva.Config{Size: 10, UnstoppableWorkers: 5}
    p := eva.NewPool(&config)

    context, cancel := context.WithCancel(context.Background()) // WithDeadline or WithTimeout

    for i := 0; i < 100; i++ {
        t := eva.NewCustomTask(func(args ...interface{}) (interface{}, error) {
            // some work here...


                return result, err
        }, args)

        p.SubmitWithContext(context, t)
    }

    // some work here...

    cancel()

    p.Close()

With custom

    config := &eva.Config{Size: 10, UnstoppableWorkers: 5}
    p := eva.NewPool(&config)

    context, cancel := context.WithCancel(context.Background()) // WithDeadline or WithTimeout
    completion := make(chan eva.Task, 3)

    for i := 0; i < 100; i++ {
        t := eva.NewCustomTask(func(args ...interface{}) (interface{}, error) {
            // some work here...


                return result, err
        }, args)

        p.SubmitCustom(context, completion, t)
    }

    for i := 0; i < 3; i++ {
        select {
        case t := <-completion:
            fmt.Printf("Task result=%v; error=%v; panic=%v, t.Get(), t.Error(), t.Panic())
        }
    }

    cancel()

    p.Close()

Immediate

    config := &eva.Config{Size: 10, UnstoppableWorkers: 5}
    p := eva.NewPool(&config)

    t := eva.NewCustomTask(func(args ...interface{}) (interface{}, error) {
        // some work here...


        return result, err
    }, args)

    err := p.SubmitImmediate(t)

    if err == nil {
        fmt.Printf("Task result=%v; error=%v; panic=%v, t.Get(), t.Error(), t.Panic())
    }

    p.Close()

Sync

    config := &eva.Config{Size: 10, UnstoppableWorkers: 5}
    p := eva.NewPool(&config)

    t := eva.NewCustomTask(func(args ...interface{}) (interface{}, error) {
        // some work here...


        return result, err
    }, args)

    p.Submit(t)

    fmt.Printf("Task result=%v; error=%v; panic=%v, t.Get(), t.Error(), t.Panic()) // like CompletableFuture

    p.Close()

Resize

You can change pool size:

    pool.SetSize(1000)
    pool.SetSize(1000000)

Or you can change changes unstoppable workers count

    pool.SetUnstoppableWorkers(1000)
    pool.SetUnstoppableWorkers(1000000)

This is safe to perform from any goroutine even if others are still processing.

Interfaces

You can implement Task interface and submit it in pool:


// Task interface for goroutines pool.
type Task interface {
	// Cancel perform cancel task.
	Cancel()

	// Error returns task Run error.
	// Blocked until the task is done.
	Error() error

	// Get returns task Run result.
	// Blocked until the task is done.
	Get() interface{}

	// IsCancelled returns true if this task has been canceled.
	IsCancelled() bool

	// IsDone returns true if this task has been done.
	IsDone() bool

	// Panic returns task Run panic.
	// Blocked until the task is done.
	Panic() interface{}

	// Run perform task.
	Run()
}

Ordering

All the tasks submitted to EVA pool will not be guaranteed to be processed in order, because those tasks distribute among a series of concurrent workers, thus those tasks are processed concurrently.

Documentation

Index

Constants

View Source
const (
	DefaultSize = 10
)

Constants that are used throughout the Eva API.

Variables

View Source
var (
	ErrPoolSize           = errors.New("pool size less than or equal 0")
	ErrUnstoppableWorkers = errors.New("unstoppable workers count less than 0")
	ErrPoolClosed         = errors.New("pool closed")
	ErrPoolUnavailable    = errors.New("pool temporarily unavailable")
)

Errors that are used throughout the Eva API.

View Source
var (
	ErrTaskQueueClosed = errors.New("task queue closed")
	ErrTaskQueueEmpty  = errors.New("task queue is empty")
)

Errors that are used throughout the Eva API.

Functions

This section is empty.

Types

type Callable

type Callable interface {
	// Call perform function.
	Call()

	// Error returns function Call error.
	Error() error

	// Result returns function Call result.
	Result() interface{}
}

Callable is interface, that Call function for task in goroutines pool.

type Config

type Config struct {
	//Maximum number of workers that could be spawned.
	// It includes ActiveWorkers count.
	// If size == 0, then size poll change set to default (10)
	Size int
	// Number of workers that are always running.
	// If UnstoppableWorkers > Size, the Size will be overwritten
	UnstoppableWorkers int
}

Config is pool configuration

type CustomCallable

type CustomCallable struct {
	// contains filtered or unexported fields
}

CustomCallable (implement Callable interface) for task in goroutines pool.

func NewCustomCallable

func NewCustomCallable(f func(...interface{}) (interface{}, error), args ...interface{}) *CustomCallable

NewCustomCallable is constructor for CustomCallable

func (*CustomCallable) Call

func (cc *CustomCallable) Call()

Call perform function.

func (*CustomCallable) Error

func (cc *CustomCallable) Error() error

Error returns function Call error.

func (*CustomCallable) Result

func (cc *CustomCallable) Result() interface{}

Result returns function Call result.

type CustomTask

type CustomTask struct {
	// contains filtered or unexported fields
}

CustomTask (implement Task interface) for goroutines pool.

func NewCustomTask

func NewCustomTask(f func(...interface{}) (interface{}, error), args ...interface{}) *CustomTask

NewCustomTask is constructor for CustomTask

func (*CustomTask) Cancel

func (ct *CustomTask) Cancel()

Cancel perform cancel task.

func (*CustomTask) Error

func (ct *CustomTask) Error() error

Error returns task Run error. Blocked until the task is done.

func (*CustomTask) Get

func (ct *CustomTask) Get() interface{}

Get returns task Run result. Blocked until the task is done.

func (*CustomTask) IsCancelled

func (ct *CustomTask) IsCancelled() bool

IsCancelled returns true if this task has been canceled.

func (*CustomTask) IsDone

func (ct *CustomTask) IsDone() bool

IsDone returns true if this task has been done.

func (*CustomTask) Panic

func (ct *CustomTask) Panic() interface{}

Panic returns task Run panic. Blocked until the task is done.

func (*CustomTask) Run

func (ct *CustomTask) Run()

Run perform task.

type Pool

type Pool struct {
	// contains filtered or unexported fields
}

Pool is a struct that manages a collection of workers, each with their own goroutine. The Pool can initialize, expand, compress and close the workers, as well as processing task.

func NewPool

func NewPool(c *Config) *Pool

NewPool is constructor for Pool

func (*Pool) ActiveCount

func (p *Pool) ActiveCount() int

ActiveCount returns the approximate number of workers that are actively executing tasks or idle.

func (*Pool) Close

func (p *Pool) Close()

Close terminates all spawned goroutines.

func (*Pool) IsClosed

func (p *Pool) IsClosed() bool

IsClosed returns true if this pool has been closed.

func (*Pool) SetSize

func (p *Pool) SetSize(size int) error

SetSize changes pool size. It returns ErrPoolClosed only if pool become closed. It returns ErrPoolSize only if size < 0.

func (*Pool) SetUnstoppableWorkers

func (p *Pool) SetUnstoppableWorkers(count int) error

SetUnstoppableWorkers changes unstoppable workers count. It returns ErrPoolClosed only if pool become closed. It returns ErrUnstoppableWorkers only if count < 0.

func (*Pool) Size

func (p *Pool) Size() int

Size returns the current number of workers in the pool.

func (*Pool) Submit

func (p *Pool) Submit(t Task) error

Submit makes task to be scheduled over pool's workers. It returns ErrPoolClosed only if pool become closed and task can not be executed over its workers.

func (*Pool) SubmitCustom

func (p *Pool) SubmitCustom(ctx context.Context, completion chan<- Task, t Task) error

SubmitCustom is a combination of SubmitWithCompletion and SubmitWithContext.

func (*Pool) SubmitImmediate

func (p *Pool) SubmitImmediate(t Task) error

SubmitImmediate makes task to be scheduled without waiting for free workers. That is, if all workers are busy and pool is not rubber, then ErrUnavailable is returned immediately. It returns ErrPoolClosed only if pool become closed and task can not be executed over its workers.

func (*Pool) SubmitWithCompletion

func (p *Pool) SubmitWithCompletion(completion chan<- Task, t Task) error

SubmitWithCompletion makes task to be scheduled over pool's workers with returning completed task by completion channel. It returns ErrPoolClosed only if pool become closed and task can not be executed over its workers. Be careful, may deadlock! You need read-loop from completion channel.

func (*Pool) SubmitWithContext

func (p *Pool) SubmitWithContext(ctx context.Context, t Task) error

SubmitWithContext makes task to be scheduled over pool's workers with context support. It returns ErrPoolClosed only if pool become closed and task can not be executed over its workers. It returns ctx.Err() error only available when ctx is done.

func (*Pool) TaskQueue

func (p *Pool) TaskQueue() TaskQueue

TaskQueue returns the task queue used by this pool.

func (*Pool) UnstoppableWorkers

func (p *Pool) UnstoppableWorkers() int

UnstoppableWorkers returns the current number of workers in the pool.

func (*Pool) Wait

func (p *Pool) Wait()

Wait pool is done with all its tasks.

type Task

type Task interface {
	// Cancel perform cancel task.
	Cancel()

	// Error returns task Run error.
	// Blocked until the task is done.
	Error() error

	// Get returns task Run result.
	// Blocked until the task is done.
	Get() interface{}

	// IsCancelled returns true if this task has been canceled.
	IsCancelled() bool

	// IsDone returns true if this task has been done.
	IsDone() bool

	// Panic returns task Run panic.
	// Blocked until the task is done.
	Panic() interface{}

	// Run perform task.
	Run()
}

Task interface for goroutines pool.

type TaskQueue

type TaskQueue interface {
	// Put inserts the task into this queue, waiting if necessary for
	// space to become available.
	Put(t Task) error

	// Size returns the current number of tasks in the queue.
	Size() int

	// Take retrieves and removes the head of this queue, waiting
	// if necessary until an task becomes available.
	Take() (Task, error)
}

TaskQueue is interface that additionally supports operations that wait for the queue to become non-empty when retrieving a task, and wait for space to become available in the queue when storing a task.

Jump to

Keyboard shortcuts

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