Documentation ¶
Index ¶
- Variables
- func CreateRegistry(config *Config) (*timemachine.Registry, error)
- func NewRuntime(ctx context.Context, config *Config) (wazero.Runtime, error)
- func OpenConfig() (io.ReadCloser, string, error)
- func OpenRegistry(config *Config) (*timemachine.Registry, error)
- func Version() string
- type Config
- type ExitError
- type HTTPRequest
- type HTTPResponse
- type LogSpec
- type ModuleSpec
- type Option
- type ProcessID
- type ProcessInfo
- type ProcessManager
- func (pm *ProcessManager) Close() error
- func (pm *ProcessManager) Lookup(processID ProcessID) (process ProcessInfo, ok bool)
- func (pm *ProcessManager) Start(moduleSpec ModuleSpec, logSpec *LogSpec, parentID *ProcessID) (ProcessID, error)
- func (pm *ProcessManager) Wait(processID ProcessID) error
- func (pm *ProcessManager) WaitAll() error
- type Replay
- func (r *Replay) ModuleCode(ctx context.Context) ([]byte, string, error)
- func (r *Replay) RecordReader(ctx context.Context) (records stream.ReadCloser[timemachine.Record], startTime time.Time, err error)
- func (r *Replay) Replay(ctx context.Context) error
- func (r *Replay) ReplayRecords(ctx context.Context, function string, moduleCode []byte, ...) error
- func (r *Replay) ReplayRecordsModule(ctx context.Context, function string, compiledModule wazero.CompiledModule, ...) error
- func (r *Replay) SetStderr(w io.Writer)
- func (r *Replay) SetStdout(w io.Writer)
- func (r *Replay) SetTrace(w io.Writer)
- type Server
- func (s *Server) Close() error
- func (s *Server) DiscardTasks(ctx context.Context, req *connect.Request[v1.DiscardTasksRequest]) (*connect.Response[v1.DiscardTasksResponse], error)
- func (s *Server) Kill(ctx context.Context, req *connect.Request[v1.KillRequest]) (*connect.Response[v1.KillResponse], error)
- func (s *Server) LookupTasks(ctx context.Context, req *connect.Request[v1.LookupTasksRequest]) (*connect.Response[v1.LookupTasksResponse], error)
- func (s *Server) PollTasks(ctx context.Context, req *connect.Request[v1.PollTasksRequest]) (*connect.Response[v1.PollTasksResponse], error)
- func (s *Server) ProcessID(context.Context, *connect.Request[v1.ProcessIDRequest]) (*connect.Response[v1.ProcessIDResponse], error)
- func (s *Server) Serve(l net.Listener) error
- func (s *Server) Spawn(ctx context.Context, req *connect.Request[v1.SpawnRequest]) (*connect.Response[v1.SpawnResponse], error)
- func (s *Server) SubmitTasks(ctx context.Context, req *connect.Request[v1.SubmitTasksRequest]) (*connect.Response[v1.SubmitTasksResponse], error)
- func (s *Server) Version(context.Context, *connect.Request[v1.VersionRequest]) (*connect.Response[v1.VersionResponse], error)
- type ServerFactory
- type TaskGroup
- func (g *TaskGroup) Close() error
- func (g *TaskGroup) Discard(id TaskID) (ok bool)
- func (g *TaskGroup) Lookup(id TaskID) (task TaskInfo, ok bool)
- func (g *TaskGroup) Poll() <-chan TaskID
- func (g *TaskGroup) Submit(moduleSpec ModuleSpec, logSpec *LogSpec, input TaskInput, processID ProcessID) (TaskID, error)
- type TaskID
- type TaskInfo
- type TaskInput
- type TaskOutput
- type TaskScheduler
- type TaskState
Constants ¶
This section is empty.
Variables ¶
var ConfigPath human.Path = defaultConfigPath
ConfigPath is the path to the timecraft configuration.
Functions ¶
func CreateRegistry ¶
func CreateRegistry(config *Config) (*timemachine.Registry, error)
CreateRegistry creates a timemachine registry.
func NewRuntime ¶
NewRuntime constructs a wazero.Runtime that's configured according to the provided timecraft Config.
func OpenConfig ¶
func OpenConfig() (io.ReadCloser, string, error)
OpenConfig opens the configuration file.
func OpenRegistry ¶
func OpenRegistry(config *Config) (*timemachine.Registry, error)
OpenRegistry opens a timemachine registry.
Types ¶
type Config ¶
type Config struct { Registry struct { Location Option[human.Path] `json:"location"` } `json:"registry"` Cache struct { Location Option[human.Path] `json:"location"` } `json:"cache"` }
Config is timecraft configuration.
func LoadConfig ¶
LoadConfig opens and reads the configuration file.
type ExitError ¶
type ExitError uint32
ExitError indicates a WebAssembly module exited with a non-zero exit code.
type HTTPRequest ¶
type HTTPRequest struct { Method string Path string // TODO: other parts of the URL, e.g. query Headers http.Header Body []byte Port int }
HTTPRequest is an HTTP request.
It's intended to buffer a full request in memory in case it needs to be used multiple times, compared to a http.Request with a generic io.ReadCloser Body that can only be consumed once.
type HTTPResponse ¶
HTTPResponse is an HTTP response.
type LogSpec ¶
type LogSpec struct { ProcessID ProcessID StartTime time.Time Compression timemachine.Compression BatchSize int }
LogSpec is details about the log that records a trace of execution.
type ModuleSpec ¶
type ModuleSpec struct { // Path is the path of the WebAssembly module. Path string // Name of the exported function to call in the WebAssembly module. // If empty, the _start function will be executed. Function string // Args are command-line arguments to pass to the module. Args []string // Env is the environment variables to pass to the module. Env []string // Dirs is a set of directories to make available to the module. Dirs []string // Listens is a set of listener sockets to make available to the module. Listens []string // Dials is a set of connection sockets to make available to the module. Dials []string // Sockets is the name of a sockets extension to use, or "auto" to // automatically detect the sockets extension. Sockets string // Stdio file descriptors. Stdin io.Reader Stdout io.Writer Stderr io.Writer // Trace is an optional writer that receives a trace of system calls // made by the module. Trace io.Writer // Allow the module to bind to the host network when opening listening // sockets. HostNetworkBinding bool // OutboundProxy is a run specification for a WebAssembly module to be // spawn alongside this module. The extra module is a sidecar that proxies // outbound network traffic. OutboundProxy *ModuleSpec }
ModuleSpec is the details about what WebAssembly module to execute, how it should be initialized, and what its inputs are.
func (*ModuleSpec) Key ¶
func (m *ModuleSpec) Key() string
Key is a string that uniquely identifies the ModuleSpec.
type Option ¶
type Option[T any] struct { // contains filtered or unexported fields }
Option is a value of type T or null.
func (Option[T]) MarshalJSON ¶
func (Option[T]) MarshalYAML ¶
func (*Option[T]) UnmarshalJSON ¶
func (*Option[T]) UnmarshalYAML ¶
type ProcessInfo ¶
type ProcessInfo struct { // ID is the ID of the process. ID ProcessID // Addr is a unique IP address for the process. Addr netip.Addr // DialContext is a dialer that can be used to send work to the // process over the work socket. DialContext func(ctx context.Context, network, address string) (net.Conn, error) // ParentID is the ID of the process that spawned this one (if applicable). ParentID *ProcessID // contains filtered or unexported fields }
ProcessInfo is information about a process.
type ProcessManager ¶
type ProcessManager struct {
// contains filtered or unexported fields
}
ProcessManager runs WebAssembly modules.
A running WebAssembly module is known as a process. Processes are allowed to spawn other processes. The ProcessManager manages the lifecycle of processes.
func NewProcessManager ¶
func NewProcessManager(ctx context.Context, registry *timemachine.Registry, runtime wazero.Runtime, serverFactory *ServerFactory, adapter func(ProcessID, wasi.System) wasi.System) *ProcessManager
NewProcessManager creates an ProcessManager.
func (*ProcessManager) Close ¶
func (pm *ProcessManager) Close() error
Close closes the process manager.
func (*ProcessManager) Lookup ¶
func (pm *ProcessManager) Lookup(processID ProcessID) (process ProcessInfo, ok bool)
Lookup looks up a process by ID.
The return flag is true if the process exists and is alive, and false otherwise.
func (*ProcessManager) Start ¶
func (pm *ProcessManager) Start(moduleSpec ModuleSpec, logSpec *LogSpec, parentID *ProcessID) (ProcessID, error)
Start starts a process.
The ModuleSpec describes the module to be executed. An optional LogSpec can be provided to instruct the ProcessManager to record a trace of execution to a log.
If Start returns an error it indicates that there was a problem initializing the WebAssembly module. If the WebAssembly module starts successfully, any errors that occur during execution must be retrieved via Wait or WaitAll.
func (*ProcessManager) Wait ¶
func (pm *ProcessManager) Wait(processID ProcessID) error
Wait blocks until a process exits.
func (*ProcessManager) WaitAll ¶
func (pm *ProcessManager) WaitAll() error
WaitAll blocks until all processes have exited.
type Replay ¶
type Replay struct {
// contains filtered or unexported fields
}
Replay coordinates the replay of WebAssembly modules.
func NewReplay ¶
NewReplay creates a Replay for a WebAssembly modules with a recorded trace of execution, identified by processID.
func (*Replay) ModuleCode ¶
ModuleCode reads the module's WebAssembly code.
func (*Replay) RecordReader ¶
func (r *Replay) RecordReader(ctx context.Context) (records stream.ReadCloser[timemachine.Record], startTime time.Time, err error)
RecordReader constructs a reader for the process replay log.
func (*Replay) ReplayRecords ¶
func (r *Replay) ReplayRecords(ctx context.Context, function string, moduleCode []byte, records stream.Reader[timemachine.Record]) error
ReplayRecords replays process execution using the specified records.
func (*Replay) ReplayRecordsModule ¶
func (r *Replay) ReplayRecordsModule(ctx context.Context, function string, compiledModule wazero.CompiledModule, records stream.Reader[timemachine.Record]) error
ReplayRecordsModule replays process execution using the specified records on a pre-compiled module.
type Server ¶
type Server struct { serverv1connect.UnimplementedTimecraftServiceHandler // contains filtered or unexported fields }
Server is a gRPC server that's available to guests. Every WebAssembly module has its own instance of a gRPC server.
func (*Server) DiscardTasks ¶
func (s *Server) DiscardTasks(ctx context.Context, req *connect.Request[v1.DiscardTasksRequest]) (*connect.Response[v1.DiscardTasksResponse], error)
func (*Server) Kill ¶
func (s *Server) Kill(ctx context.Context, req *connect.Request[v1.KillRequest]) (*connect.Response[v1.KillResponse], error)
func (*Server) LookupTasks ¶
func (s *Server) LookupTasks(ctx context.Context, req *connect.Request[v1.LookupTasksRequest]) (*connect.Response[v1.LookupTasksResponse], error)
func (*Server) PollTasks ¶
func (s *Server) PollTasks(ctx context.Context, req *connect.Request[v1.PollTasksRequest]) (*connect.Response[v1.PollTasksResponse], error)
func (*Server) ProcessID ¶
func (s *Server) ProcessID(context.Context, *connect.Request[v1.ProcessIDRequest]) (*connect.Response[v1.ProcessIDResponse], error)
func (*Server) Spawn ¶
func (s *Server) Spawn(ctx context.Context, req *connect.Request[v1.SpawnRequest]) (*connect.Response[v1.SpawnResponse], error)
func (*Server) SubmitTasks ¶
func (s *Server) SubmitTasks(ctx context.Context, req *connect.Request[v1.SubmitTasksRequest]) (*connect.Response[v1.SubmitTasksResponse], error)
func (*Server) Version ¶
func (s *Server) Version(context.Context, *connect.Request[v1.VersionRequest]) (*connect.Response[v1.VersionResponse], error)
type ServerFactory ¶
type ServerFactory struct { ProcessManager *ProcessManager Scheduler *TaskScheduler }
ServerFactory is used to create Server instances.
func (*ServerFactory) NewServer ¶
func (f *ServerFactory) NewServer(ctx context.Context, processID uuid.UUID, moduleSpec ModuleSpec, logSpec *LogSpec) *Server
NewServer creates a new Server.
type TaskGroup ¶
type TaskGroup struct {
// contains filtered or unexported fields
}
TaskGroup manages a logical group of tasks.
It exposes nearly the same API as the TaskScheduler, but adds a new Poll method, ensures that only tasks local to the group can be retrieved or discarded through the same group, and automatically discards all in-flight tasks when closed.
func NewTaskGroup ¶
func NewTaskGroup(s *TaskScheduler) *TaskGroup
NewTaskGroup creates a new task group.
func (*TaskGroup) Discard ¶
Discard discards a task by ID.
See TaskScheduler.Discard for more information.
func (*TaskGroup) Lookup ¶
Lookup looks up a task by ID.
See TaskScheduler.Lookup for more information.
type TaskInfo ¶
type TaskInfo struct {
// contains filtered or unexported fields
}
TaskInfo is information about a task.
type TaskInput ¶
type TaskInput interface {
// contains filtered or unexported methods
}
TaskInput is input for a task.
type TaskOutput ¶
type TaskOutput interface {
// contains filtered or unexported methods
}
TaskOutput is output from a task.
type TaskScheduler ¶
type TaskScheduler struct { ProcessManager *ProcessManager // contains filtered or unexported fields }
TaskScheduler schedules tasks across processes.
A task is a unit of work. A process (managed by the ProcessManager) is responsible for executing one or more tasks. The management of processes to execute tasks and the scheduling of tasks across processes are both implementation details of the scheduler.
func (*TaskScheduler) Close ¶
func (s *TaskScheduler) Close() error
Close closes the TaskGroup and discards all in-flight tasks.
func (*TaskScheduler) Discard ¶
func (s *TaskScheduler) Discard(id TaskID) (ok bool)
Discard discards a task by ID.
func (*TaskScheduler) Lookup ¶
func (s *TaskScheduler) Lookup(id TaskID) (task TaskInfo, ok bool)
Lookup looks up a task by ID.
func (*TaskScheduler) Submit ¶
func (s *TaskScheduler) Submit(moduleSpec ModuleSpec, logSpec *LogSpec, input TaskInput, processID ProcessID, completions chan<- TaskID) (TaskID, error)
Submit submits a task for execution.
The method returns a TaskID that can be passed to Lookup to query the task status and fetch task output.
The method accepts an optional channel that receives a completion notification once the task is complete (succeeds, or fails permanently).
Once a task is complete, it must be discarded via Discard.
type TaskState ¶
type TaskState int
TaskState is the state of a task.
const ( // Queued indicates that the task is waiting to be scheduled. Queued TaskState = iota + 1 // Initializing indicates that the task is in the process of being scheduled // on to a process. Initializing // Executing indicates that the task is currently being executed. Executing // Error indicates that the task failed with an error. This is a terminal // status. Error // Success indicates that the task executed successfully. This is a terminal // status. Success )