subflow

package module
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Feb 2, 2025 License: MIT Imports: 15 Imported by: 0

README

Subflow

Subflow is a Go library designed for managing and executing subprocesses. It provides an interface to define commands, manage input/output streams, and handle subprocess lifecycle events synchronously and asynchronously.


Installation

Install Subflow using go get:

go get github.com/bobcatalyst/subflow

Import it in your Go code:

import "github.com/bobcatalyst/subflow"

Quick Start

Define a Command

Create a basic command:

cmd := subflow.NewCommand("ls")

Add arguments and environment variables:

cmdArgsEnv := subflow.NewCommandArgsEnv("ls", []string{"-l", "-a"}, []string{"PATH=/usr/bin"})

Run a Command

Execute a command and get output:

ctx := context.Background()
output := subflow.Run(ctx, cmdArgsEnv, nil)
fmt.Printf("Stdout: %s\n", string(output.Stdout()))
fmt.Printf("Stderr: %s\n", string(output.Stderr()))

Manage Subprocesses

Asynchronous subprocess management:

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

subCmd, err := subflow.New(ctx, cmdArgsEnv)
if err != nil {
    log.Fatalf("failed to create command: %v", err)
}
defer subCmd.Close()

go func() {
    for msg := range subCmd.Listen(ctx) {
        fmt.Printf("Message: %v\n", msg)
    }
}()

subCmd.Start()
<-subCmd.Wait()

Streaming Input

Push input data to a running command:

subCmd.Push(subflow.NewInputln("example input"))

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BaseMessage

type BaseMessage[K fmt.Stringer] struct {
	Time time.Time     `json:"time"`
	Kind JSONString[K] `json:"kind"`
}

func NewBaseMessage

func NewBaseMessage[K fmt.Stringer]() BaseMessage[K]

NewBaseMessage initializes a new BaseMessage with the current time.

type Cmd

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

func New

func New(ctx context.Context, cmd CommandArgs) (_ *Cmd, finalErr error)

func (*Cmd) Close

func (cmd *Cmd) Close() error

Close closes the Cmd waiting indefinitely for the subprocess to exit.

func (*Cmd) CloseTimeout

func (cmd *Cmd) CloseTimeout(timeout time.Duration) error

CloseTimeout stops the command and cleans up resources. If the command does not terminate, it will be killed after a timeout.

func (*Cmd) Done

func (cmd *Cmd) Done() <-chan struct{}

Done returns a channel that closes when the process completes.

func (*Cmd) Listen

func (cmd *Cmd) Listen(ctx context.Context) <-chan Message

Listen emits the process start, stdout/err/in, and the exit code. It is non buffered, so any messages emitted before Listen is called will be lost. Call Listen before Start to get all messages.

c1 := cmd.Listen(context.Background)
cmd.Start()
c2 := cmd.Listen(context.Background)

c1 will contain the start message while c2 will not.

func (*Cmd) Push

func (cmd *Cmd) Push(in ...Input)

Push adds new inputs to the command's input stream

func (*Cmd) Start

func (cmd *Cmd) Start()

Start starts the command exactly once.

type Command

type Command interface {
	Command() string
}

func NewCommand

func NewCommand(command string) Command

type CommandArgs

type CommandArgs interface {
	Command
	Args() []string
}

func NewCommandArgs

func NewCommandArgs(command string, args []string) CommandArgs

type CommandArgsEnv

type CommandArgsEnv interface {
	CommandArgs
	Environment() []string
}

func NewCommandArgsEnv

func NewCommandArgsEnv(command string, args, env []string) CommandArgsEnv

type CommandEnv

type CommandEnv interface {
	Command
	Environment() []string
}

func NewCommandEnv

func NewCommandEnv(command string, env []string) CommandEnv

func WithEnv

func WithEnv(cmd Command, env []string) CommandEnv

WithEnv appends new environment variables to the command.

type Data

type Data []byte

Data represents a slice of bytes that can be serialized to/from JSON.

func (Data) MarshalJSON

func (d Data) MarshalJSON() ([]byte, error)

func (*Data) UnmarshalJSON

func (d *Data) UnmarshalJSON(b []byte) error

type DataLike

type DataLike interface {
	~string | ~[]byte
}

DataLike defines types that behave like Data (string or []byte).

type ErrExitCode

type ErrExitCode int

ErrExitCode represents a non zero process exit code.

func (ErrExitCode) Error

func (err ErrExitCode) Error() string

type ExitMessage

type ExitMessage struct {
	BaseMessage[kind[exit]]
	Code int `json:"code"`
}

ExitMessage represents a message indicating the end of a process, including the exit code.

type Input

type Input interface {
	Message
	Input() []byte
}

Input extends Message and provides a method to get the input data as bytes.

func NewInput

func NewInput[D DataLike](data D) Input

NewInput creates a new TextInput.

func NewInputf

func NewInputf(format string, a ...any) Input

NewInputf creates a new TextInput with formatted data.

func NewInputln

func NewInputln[D DataLike](data D) Input

NewInputln creates a new TextInput with a newline appended.

type JSONString

type JSONString[S fmt.Stringer] struct{}

JSONString wraps a type that implements fmt.Stringer for JSON serialization.

func (JSONString[S]) MarshalJSON

func (js JSONString[S]) MarshalJSON() ([]byte, error)

func (JSONString[S]) String

func (JSONString[S]) String() string

func (*JSONString[S]) UnmarshalJSON

func (js *JSONString[S]) UnmarshalJSON(b []byte) error

type Message

type Message interface {
	// contains filtered or unexported methods
}

Message represents a generic interface for message types.

func NewExitMessage

func NewExitMessage(code int) Message

func NewStartMessage

func NewStartMessage() Message

func NewStdioMessage

func NewStdioMessage[T StdioLike, D DataLike](data D) Message

NewStdioMessage creates a specific type of StdioMessage based on the provided data.

type Output

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

Output struct captures the result of asynchronously running a command. It includes the standard output, standard error, exit code, and any execution error.

func Run

func Run(ctx context.Context, cmd Command, stdin []byte) (out Output)

Run executes a command with the provided context and optional standard input.

func (*Output) Code

func (out *Output) Code() int

Code returns the exit code of the executed command.

func (*Output) Err

func (out *Output) Err() error

Err returns any error encountered during command execution.

func (*Output) Stderr

func (out *Output) Stderr() []byte

Stderr returns the standard error captured during command execution.

func (*Output) Stdout

func (out *Output) Stdout() []byte

Stdout returns the standard output captured during command execution.

type StartMessage

type StartMessage struct {
	BaseMessage[kind[start]]
}

StartMessage represents a message indicating the start of a process.

type StderrMessage

type StderrMessage = stdioMessage[kind[stderr]]

type StdinMessage

type StdinMessage = stdioMessage[kind[stdin]]

type StdioLike

type StdioLike interface {
	StderrMessage | StdoutMessage | StdinMessage
}

StdioLike groups StdioMessage types for stdin, stdout, and stderr.

type StdoutMessage

type StdoutMessage = stdioMessage[kind[stdout]]

type TextInput

type TextInput struct {
	BaseMessage[kind[text]]
	Data Data `json:"data"`
}

TextInput represents input data as a message.

func (TextInput) Input

func (ti TextInput) Input() []byte

Jump to

Keyboard shortcuts

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