Documentation ¶
Overview ¶
Package sio provides a single-crew system with pluggable IO.
Index ¶
- Variables
- func DefaultState(s *core.State) *core.State
- func JS(x interface{}) string
- func JSON(x interface{}) string
- func JShort(x interface{}) string
- func ResolveSpecSource(ctx context.Context, specSource interface{}) (*crew.SpecSource, *core.Spec, error)
- func ShellExpand(msg string) (string, error)
- type Changed
- type Couplings
- type Crew
- func (c *Crew) DeleteMachine(ctx context.Context, mid string) error
- func (c *Crew) DoOp(ctx context.Context, op *CrewOp) error
- func (c *Crew) Errorf(format string, args ...interface{})
- func (c *Crew) GetChanged(ctx context.Context) (map[string]*Changed, error)
- func (c *Crew) GetTimers(ctx context.Context) (*Timers, error)
- func (c *Crew) Logf(format string, args ...interface{})
- func (c *Crew) Loop(ctx context.Context) error
- func (c *Crew) NewCaptainSpec() *core.Spec
- func (c *Crew) NewTimersSpec() *core.Spec
- func (c *Crew) ProcessMsg(ctx context.Context, msg interface{}) (*Result, error)
- func (c *Crew) RunMachine(ctx context.Context, msg interface{}, m *crew.Machine) (*core.Walked, error)
- func (c *Crew) RunMachines(ctx context.Context, msg interface{}) (map[string]*core.Walked, error)
- func (c *Crew) SetMachine(ctx context.Context, mid string, src *crew.SpecSource, state *core.State) error
- type CrewConf
- type CrewOp
- type JSONStore
- type Limits
- type Result
- type Stdio
- type Stroll
- type TimerEntry
- type TimerMsg
- type Timers
Constants ¶
This section is empty.
Variables ¶
var (
// CaptainMachine is the id of the captain.
CaptainMachine = "captain"
)
var DefaultLimits = &Limits{
MaxSheens: 100,
MaxStatePerSheen: 10 * 1024,
}
DefaultLimits is just that.
var ( // Interpreters are the standard action interpreters. Interpreters = core.InterpretersMap{ "goja": interpreter, "ecmascript": interpreter, "ecmascript-5.1": interpreter, } )
var (
// TimersMachine is the id of the timers machine.
TimersMachine = "timers"
)
Functions ¶
func DefaultState ¶
DefaultState returns a state at "state" with empty bindings.
func JShort ¶
func JShort(x interface{}) string
JShort renders its argument as JS() but only up to 73 characters.
func ResolveSpecSource ¶
func ResolveSpecSource(ctx context.Context, specSource interface{}) (*crew.SpecSource, *core.Spec, error)
ResolveSpecSource attempts to find and compile a spec based on a crew.SpecSource (or something that looks like one).
ToDo: Test and document.
func ShellExpand ¶
ShellExpand expands shell commands delimited by '<<' and '>>'. Use at your wown risk, of course!
Types ¶
type Changed ¶
type Changed struct { State *core.State `json:",omitempty"` SpecSrc *crew.SpecSource `json:",omitempty"` Deleted bool `json:",omitempty"` // PreviousState is optional data that can be used to decide // if the new state is really different from the old state. // // In this implementation, PreviousState is a JSON // representation of this struct. PreviousState []byte `json:"-"` }
Changed represents changes to a machine after message processing.
type Couplings ¶
type Couplings interface { // Start initializes the Couplings. Start(context.Context) error // IO returns the input and result channels. // // Consumer can see all emitted messages and state updates via // the Result(s). IO(context.Context) (chan interface{}, chan *Result, chan bool, error) // Read (optionally) returns an initial set of machines. // // An implementation that supports persistence would read // machine state and pass it to this method. Read(context.Context) (map[string]*crew.Machine, error) // Stop shuts down the Couplings. Stop(context.Context) error }
Couplings provide channels for message input, results output, and persistence.
For example, an implementation could couple a crew to an MQTT broker (for IO). For persistence, an implementation could use https://github.com/etcd-io/bbolt, DynamoDB, SQLite, etc.
type Crew ¶
type Crew struct { // Machines represents this's Crews current machines. Machines map[string]*crew.Machine // Conf provides some basic Crew parameters. Conf *CrewConf `json:"conf"` // Verbose turns on logging. Verbose bool // Mutex can probably be removed once code is cleaned up to // perform all state changes, including timers state changes, // the Crew loop. ToDo. sync.Mutex // contains filtered or unexported fields }
Crew represents a collection of machines and associated gear to support message processing, with I/O coupled via two channels (in and out).
func NewCrew ¶
NewCrew makes a crew with the given configuration and couplings.
The coupling's IO() method is called to obtain the crew's in/out channels.
func (*Crew) DeleteMachine ¶
DeleteMachine removes a machine from the crew.
No error is returned if the machine doesn't exist.
func (*Crew) GetChanged ¶
GetChanged computes the net machine changes since this method was previously called.
ToDo: Make private.
func (*Crew) Loop ¶
Loop starts the input processing loop in the current goroutine.
This loop calls ProcessMsg on each message that arrives via the input coupling, and the loop halts when ctx.Done().
func (*Crew) NewCaptainSpec ¶
NewCaptainSpec creates a machine Spec for a "captain" who can execute CrewOps.
func (*Crew) NewTimersSpec ¶
NewTimersSpec creates a new spec that can process a TimerMsg.
func (*Crew) ProcessMsg ¶
ProcessMsg processes the given message and returns the results, which can then be processed by the crew's Result coupling.
func (*Crew) RunMachine ¶
func (c *Crew) RunMachine(ctx context.Context, msg interface{}, m *crew.Machine) (*core.Walked, error)
RunMachines presents the message to the given machine.
func (*Crew) RunMachines ¶
RunMachines presents the message to the machines returned by toMachines.
type CrewConf ¶
CrewConf contains (or will contain) basic crew configuration data.
Not much is needed now.
type CrewOp ¶
type CrewOp struct { Update map[string]*crew.Machine `json:"update,omitempty"` Delete []string `json:"delete,omitempty"` }
CrewOp is a crude structure for crew-level operations (such as adding a machine).
type JSONStore ¶
type JSONStore struct { // StateOutputFilename, if not empty, will be the filename // writing state as JSON. StateOutputFilename string // StateInputFilename optionall gives a filename that contains // state to return when Read is called. StateInputFilename string WG sync.WaitGroup // contains filtered or unexported fields }
JSONStore is a primitive facility to store crew state as JSON in a file.
Not glamorous or efficient.
func NewJSONStore ¶
func NewJSONStore() *JSONStore
func (*JSONStore) Read ¶
Read reads s.StateInputFilename, which should contain a JSON representation of the crew's state.
type Limits ¶
type Limits struct { MaxSheens int `json:"maxSheens"` MaxStatePerSheen int `json:"maxStatePerSheen"` }
Limits provides some operation limits.
Currently these limits are not enforced at all.
ToDo: Use!
type Result ¶
type Result struct { // Changed represents all machine changes. Changed map[string]*Changed // Emitted is list of message batches emitted by machines // during processing. // // A message batch is ordered: A machine (usually) emits // messages in a specified, deterministic order. // // The collection of batches is a partial order given by // recursive message processing calls. When processing a // message results in emitted messages that are directed back // to the crew, the results of those recursive processings // give a determinstic order their emitted batches. However, // with respect to a processig a single message, multiple // batches are NOT orders (because the order that machines are // presented with an in-bound message is not specified). Emitted [][]interface{} // Diag includes internal processing data. Diag []*Stroll }
Result represents all visible output from processing a message.
type Stdio ¶
type Stdio struct { // In is coupled to crew input. In io.Reader // Out is coupled to crew output. Out io.Writer // ShellExpand enables input to include inline shell commands // delimited by '<<' and '>>'. Use at your wown risk, of // course! ShellExpand bool // Timestamps prepends a timestamp to each output line. Timestamps bool // EchoInput writes input lines (prepended with "input") to // the output. EchoInput bool // Tags prefixes tags indicating type of output ("input", // "emit", "diag"). Tags bool // PadTags adds some padding to tags ("input", "emit", // "update") used in output. PadTags bool // PrintUpdates will print update messages to stdout. PrintUpdates bool JSONStore // InputEOF will be closed on EOF from stdin. InputEOF chan bool // WriteStatePerMsg will write out ALL state after every input // message is processed. // // Inefficient! WriteStatePerMsg bool // PrintDiag turns on printing of diagnostic data. PrintDiag bool }
Stdio is a fairly simple Couplings that uses stdin for input and stdout for output.
State is optionally crudely written as JSON to a file.
func NewStdio ¶
NewStdio creates a new Stdio.
ShellExpand enables input to include inline shell commands delimited by '<<' and '>>'. Use at your wown risk, of course!
In and Out are initialized with os.Stdin and os.Stdout respectively.
type Stroll ¶
type Stroll struct { Msg interface{} `json:"msg"` Walkeds interface{} `json:"walks"` Err string `json:"err,omitempty"` }
Stroll is a internal processing data for the given message.
Result.Diag gathers this information.
type TimerEntry ¶
type TimerEntry struct { Id string Msg interface{} At time.Time Ctl chan bool `json:"-"` // contains filtered or unexported fields }
TimerEntry represents a pending timer.
type TimerMsg ¶
type TimerMsg struct { // Add the given timer. Add struct { Id string `json:"id"` Msg interface{} `json:"msg"` In string `json:"in"` To string `json:"to"` // ToDo: Support array } `json:"makeTimer"` // Cancel the given timer. Cancel struct { Id string } `json:"cancelTimer"` }
TimerMsg is a command that the timers machine can execute.
type Timers ¶
type Timers struct { Map map[string]*TimerEntry Emitter func(context.Context, *TimerEntry) `json:"-"` sync.Mutex // contains filtered or unexported fields }
Timers represents pending timers.
func NewTimers ¶
func NewTimers(emitter func(context.Context, *TimerEntry)) *Timers
NewTimers creates a Timers with the given function that the TimerEntries will use to emit their messages.
func (*Timers) Add ¶
Add creates a new Timer that will emit the given message later (if the timer isn't cancelled first).