func ATProcessCloseInput(w selina.Worker) error {
	input := make(chan []byte)
	output := make(chan []byte)
	resp := make(chan error, 1)
	go func() {
		args := selina.ProcessArgs{Input: input, Output: output}
		resp <- w.Process(context.Background(), args)
	}()
	go func() {
		for range output {
		}
	}()
	time.Sleep(waitProcessSleepDuration)
	close(input)
	select {
	case err := <-resp:
		return err
	case <-time.After(closeInputTimeout):
		return ErrNotTerminatedOnCloseInput
	}
}
ATProcessCloseInput a worker must finish its job and return nil
when input chanel (<-chan []byte )is closed
package workers
import (
	"context"
	"errors"
	"time"
	"github.com/licaonfee/selina"
)
const waitProcessSleepDuration = time.Millisecond * 50
const closeInputTimeout = time.Millisecond * 50
var ErrProcessIgnoreCtx = errors.New("ignored context.Done")
var ErrNotTerminatedOnCloseInput = errors.New("not terminate on closed input")
var ErrOutputNotClosed = errors.New("output channel is not closed")
func ATProcessCancel(w selina.Worker) error {
	input := make(chan []byte)
	output := make(chan []byte)  
	ctx, cancel := context.WithCancel(context.Background())
	errC := make(chan error, 1)
	go func() {
		time.Sleep(waitProcessSleepDuration)  
		cancel()
	}()
	go func() {
		args := selina.ProcessArgs{Input: input, Output: output}
		errC <- w.Process(ctx, args)
	}()
	<-ctx.Done()  
	select {
	case err := <-errC:
		if err != context.Canceled {
			if err == nil {
				return ErrProcessIgnoreCtx
			}
			return err
		}
		return nil
	case <-time.After(waitProcessSleepDuration):
		return ErrProcessIgnoreCtx
	}
}