scriptrec

package
v1.138.0 Latest Latest
Warning

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

Go to latest
Published: Sep 29, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package scriptrec records the host calls a managed script's run makes and the answers they were given, and answers a later execution from that record (#1939).

A run cannot read a clock or a random number, its fire time and run id are pinned, and every effect goes through a host binding. A run is therefore a function of its parameters, its state and the answers its host calls returned, and replaying a recording reproduces it exactly: the script's tests run against one (internal/platform/scripttest), and a save replays a script's recent runs through its new source to show what changed (#1942).

What is recorded is the answer a binding was finally given: a call the host paced or retried is recorded once, with the answer the script saw. A recording is gzipped JSON lines, the header first and one call per line, written as the run goes so it never holds more than its compressed bytes, and capped at MaxBytes: a run whose recording outgrows the cap keeps its history and has no recording, and says so.

Index

Constants

View Source
const (
	KindRun   = "run"
	KindDraft = "draft"
)

The kinds of run a recording is of.

View Source
const MaxBytes = 8 << 20

MaxBytes is the most one run's recording may hold, compressed.

Variables

View Source
var ErrNotFound = errors.New("no such recording")

ErrNotFound is a recording no store holds.

Functions

func DescribeCall

func DescribeCall(tool string, args map[string]any) string

DescribeCall names a tool call the way the script wrote it: a query by its SQL, anything else by its tool and arguments.

func ExportKey

func ExportKey(req scriptrun.ExportRequest) string

ExportKey is what an output write is matched by: its name, where it goes, its format and its key.

func PublishKey

func PublishKey(req scriptrun.PublishRequest) string

PublishKey is what a data-region refresh is matched by: the asset's name.

func SourceHash

func SourceHash(source string) string

SourceHash is the hex digest a recording names the source it ran by.

func ToolKey

func ToolKey(tool string, args map[string]any) string

ToolKey is what a tool call is matched by: its tool and its arguments.

Types

type Answerer

type Answerer interface {
	Answer(tool string, args map[string]any) (out map[string]any, errText string, ok bool)
}

Answerer answers a tool call before the recording is consulted. ok is false when it holds no answer for the call; errText is set when the answer it holds is a failure.

type Call

type Call struct {
	// Key is what a replay matches a call by: the tool and its arguments, or
	// the output's identity.
	Key  string         `json:"key"`
	Tool string         `json:"tool,omitempty"`
	Args map[string]any `json:"args,omitempty"`
	Out  map[string]any `json:"out,omitempty"`
	// Output is set for a written output: what the writer answered.
	Output *scriptrun.ExportResult `json:"output,omitempty"`
	// Error is the failure the call answered with instead, if it failed.
	Error string `json:"error,omitempty"`
}

Call is one host call and its answer: a tool call, or an output the run wrote.

type Header struct {
	V        int            `json:"v"`
	RunID    string         `json:"run_id"`
	FireTime time.Time      `json:"fire_time"`
	Params   map[string]any `json:"params"`
	State    map[string]any `json:"state"`
	RunURL   string         `json:"run_url,omitempty"`
	// MaxRows is the row cap the run's queries carried, which is part of each
	// query's arguments.
	MaxRows int `json:"max_rows"`
	// Preview is true when the run's outputs were previewed rather than
	// written: a draft. A replay of it previews them too.
	Preview bool `json:"preview"`
}

Header is what a run started from: everything a replay pins so that the calls it makes are the calls the run made.

type Made

type Made struct {
	Tool     string
	Args     map[string]any
	Out      map[string]any
	Error    string
	Declared bool
}

Made is one tool call an execution made against a Replay, with what it was answered. Declared is true when a test's declared answer answered it.

type Meta

type Meta struct {
	// RunID is the run's id, or the draft's, and is what a test names.
	RunID string `json:"run_id"`
	// ScriptID is the script recorded, empty for a draft of a script not yet
	// saved until a script naming the recording in a test is saved.
	ScriptID   string `json:"script_id,omitempty"`
	ScriptName string `json:"script_name"`
	Kind       string `json:"kind"`
	// RecordedBy is who the recorded run ran for: the draft's author, or the
	// owner of the script a run ran.
	RecordedBy string `json:"recorded_by"`
	// Version is the version a run executed, zero for a draft.
	Version      int    `json:"version,omitempty"`
	SourceSHA256 string `json:"source_sha256"`
	Succeeded    bool   `json:"succeeded"`
	// Reason says why there is no recording to replay, when there is none.
	Reason string `json:"reason,omitempty"`
	Bytes  int    `json:"bytes"`
	// Kept is true while a test in the script's latest version names the
	// recording, which keeps it past the run-retention sweep.
	Kept      bool      `json:"kept"`
	CreatedAt time.Time `json:"created_at"`
}

Meta describes a stored recording.

func (Meta) Replayable

func (m Meta) Replayable() bool

Replayable reports whether the recording can be replayed.

type MissingError

type MissingError struct {
	Call string
	// Held is how many answers the recording holds for the call, and so how
	// many times it could be made.
	Held int
}

MissingError is a call the recording holds no answer for. Its text names the call, which is what the author reads to know what the recording lacks.

func (*MissingError) Error

func (e *MissingError) Error() string

type Recorder

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

Recorder writes one run's recording as the run makes its calls. Hand OnCall to scriptrun.Options.OnCall and wrap the run's Exporter with Exporter.

func NewRecorder

func NewRecorder(h Header) *Recorder

NewRecorder starts a recording of a run that starts from h.

func (*Recorder) Exporter

func (r *Recorder) Exporter(inner scriptrun.Exporter) scriptrun.Exporter

Exporter wraps the run's writer so that what it answered is recorded. A nil writer stays nil: the run previews, and there is nothing to record.

func (*Recorder) Finish

func (r *Recorder) Finish() (data []byte, reason string)

Finish ends the recording. data is the gzipped recording, nil with the reason when there is none to keep.

func (*Recorder) OnCall

func (r *Recorder) OnCall(tool string, args, out map[string]any, err error)

OnCall records one tool call and the answer it was finally given.

func (*Recorder) SaveTo

func (r *Recorder) SaveTo(ctx context.Context, store Store, m Meta) bool

SaveTo finishes the recording and stores it under m, with the reason when there is none to keep, and reports whether a replayable recording was kept. A failure to store it is logged and not returned: a run whose recording could not be kept still ran.

type Recording

type Recording struct {
	Header
	Calls []Call
}

Recording is one run's header and its calls, in the order they were made.

func Decode

func Decode(data []byte) (*Recording, error)

Decode reads a recording back.

type Replay

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

Replay answers an execution's host calls from a recording, and never reaches an upstream: it is the scriptrun.Caller a test and a regression replay run with. Calls with the same key are answered in the order the run made them.

func NewReplay

func NewReplay(rec *Recording) *Replay

NewReplay answers from rec.

func (*Replay) CallTool

func (r *Replay) CallTool(_ context.Context, name string, args map[string]any) (map[string]any, error)

CallTool answers one tool call from the recording.

func (*Replay) Exporter

func (r *Replay) Exporter() scriptrun.Exporter

Exporter is the writer an execution replaying the recording uses: nil when the recorded run previewed its outputs, so the replay previews them too, and otherwise one answering each write with what the run's writer answered.

func (*Replay) Header

func (r *Replay) Header() Header

Header is what the recorded run started from.

func (*Replay) Lenient

func (r *Replay) Lenient() *Replay

Lenient returns the replay answering a tool call the recording holds no answer for with the next unused answer the same tool gave. A test's replay is never lenient; the check that alters a recording's rows is, because the calls a script makes after reading altered rows carry altered arguments.

func (*Replay) Made

func (r *Replay) Made() []Made

Made is every tool call the execution made, in order.

func (*Replay) WithAnswers

func (r *Replay) WithAnswers(a Answerer) *Replay

WithAnswers returns the replay answering a tool call from a before the recording.

type Store

type Store interface {
	// Save stores a recording, replacing one recorded under the same run id
	// (a run taken over from a worker that died records again).
	Save(ctx context.Context, rec Stored) error
	// Get returns one recording, or ErrNotFound.
	Get(ctx context.Context, runID string) (*Stored, error)
	// Recent returns the newest replayable recordings of the script's
	// successful runs, newest first.
	Recent(ctx context.Context, scriptID string, limit int) ([]Stored, error)
	// Keep marks the recordings runIDs names as kept, and every other
	// recording of the script as not, and attaches to the script the ones
	// among them author recorded as drafts of it before it was saved.
	Keep(ctx context.Context, scriptID, author string, runIDs []string) error
	// Purge deletes the recordings older than retention that are not kept.
	Purge(ctx context.Context, retention time.Duration) (int64, error)
}

Store keeps recordings.

type Stored

type Stored struct {
	Meta
	Data []byte
}

Stored is a recording as a store holds it.

Directories

Path Synopsis
Package recstore is the PostgreSQL store of managed-script recordings (internal/platform/scriptrec, migration 000166).
Package recstore is the PostgreSQL store of managed-script recordings (internal/platform/scriptrec, migration 000166).

Jump to

Keyboard shortcuts

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