scriptbgdraft

package
v1.146.2 Latest Latest
Warning

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

Go to latest
Published: Oct 16, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package scriptbgdraft is the long draft run (#2117): an administrator can run_draft an unsaved script past the 60 seconds a draft is held to, up to the deployment's scripts.draft.max_seconds, for a flow a short draft cannot get through -- driving a slow web app, a long export. A draft longer than the inline wait runs in the background and answers with its run id at once; get_run reads its log and progress as it goes, and the draft's whole result once it ends. It still runs as the caller, writes only with allow_writes and is recorded for tests, exactly as an inline draft is.

A background draft is kept in script_draft_runs, so get_run answers it on any replica. The replica executing it writes what it has reported every few seconds; a draft whose replica stopped reads as failed once its deadline has passed.

Index

Constants

View Source
const (
	StatusRunning   = "running"
	StatusSucceeded = "succeeded"
	StatusFailed    = "failed"
)

Status values a background draft has.

View Source
const CeilingSeconds = 3600

CeilingSeconds is the most scripts.draft.max_seconds may be.

View Source
const DefaultSeconds = int(scriptrun.DraftTimeout / time.Second)

DefaultSeconds is a draft's time limit when the deployment sets none, which is also the longest a draft is waited on inline.

View Source
const MaxBackground = 4

MaxBackground is how many background drafts one replica runs at once. A draft is an administrator's, but each holds a run's memory for up to an hour, so the next one waits for a slot rather than piling on.

View Source
const MaxSecondsKey = "scripts.draft.max_seconds"

MaxSecondsKey names the setting in a refusal.

Variables

View Source
var ErrBusy = fmt.Errorf("%d background drafts are already running on this replica; "+
	"read one with get_run and start the next when it ends", MaxBackground)

ErrBusy is a background draft refused because the replica runs MaxBackground already.

View Source
var ErrNotFound = errors.New("no background draft has that id")

ErrNotFound is a run id no background draft has.

View Source
var ErrTooLong = errors.New("the draft time limit asked for is not available")

ErrTooLong is a timeout_seconds the caller may not be given.

Functions

This section is empty.

Types

type Config

type Config struct {
	// MaxSeconds is the longest an administrator's run_draft may ask for with
	// timeout_seconds. Zero is DefaultSeconds, which no draft may pass.
	MaxSeconds int `yaml:"max_seconds,omitempty"`
}

Config is the scripts.draft section.

func (Config) Decide

func (c Config) Decide(seconds int, admin bool) (limit time.Duration, background bool, err error)

Decide reads run_draft's timeout_seconds for a caller: the draft's time limit, and whether it runs in the background because it is longer than a draft is waited on. Zero is the default limit.

func (Config) Max

func (c Config) Max() time.Duration

Max is the longest a draft may run on this deployment.

func (Config) Validate

func (c Config) Validate() error

Validate refuses a ceiling a draft cannot be given.

type Execution

type Execution func(ctx context.Context, long scriptdraft.Long) (draft map[string]any, failed bool, err error)

Execution runs one draft with long's id, reporter and time limit, and returns what run_draft would have answered inline and whether the script failed. err is the platform's own failure.

type Launcher

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

Launcher starts background drafts and reads them back.

func NewLauncher

func NewLauncher(store *Store, cfg Config) *Launcher

NewLauncher returns the launcher over store under cfg, or nil without a store: a deployment with nowhere to keep a background draft runs every draft inline, held to the default limit.

func (*Launcher) Answer

func (l *Launcher) Answer(ctx context.Context, id, caller string, admin bool) (out map[string]any, ok bool, err error)

Answer renders get_run for a background draft. ok is false when the run id is not one, so get_run reads its runs as before; err is what the caller is told instead of an answer.

func (*Launcher) Begin

func (l *Launcher) Begin(ctx context.Context, owner, script string, limit time.Duration, exec Execution) (map[string]any, error)

Begin starts a background draft and renders what run_draft answers: its run id and where to read it.

func (*Launcher) Max

func (l *Launcher) Max() time.Duration

Max is the longest a draft may run here.

func (*Launcher) Plan

func (l *Launcher) Plan(seconds int, admin bool) (limit time.Duration, background bool, err error)

Plan is Decide under the launcher's configuration.

func (*Launcher) Read

func (l *Launcher) Read(ctx context.Context, id, caller string, admin bool) (out *Run, ok bool, err error)

Read answers get_run for a background draft: ok is false when id is not one, so get_run reads its runs as before. A draft is its caller's and an administrator's, as an inline draft's answer is the caller's alone.

func (*Launcher) Start

func (l *Launcher) Start(ctx context.Context, owner, script string, limit time.Duration, exec Execution) (string, error)

Start records a draft and runs it in the background for at most limit, returning its run id at once.

type Run

type Run struct {
	ID         string          `json:"run_id"`
	Owner      string          `json:"-"`
	Script     string          `json:"script"`
	Status     string          `json:"status"`
	Log        string          `json:"log"`
	Progress   json.RawMessage `json:"progress,omitempty"`
	Error      string          `json:"error,omitempty"`
	Draft      json.RawMessage `json:"draft,omitempty"`
	StartedAt  time.Time       `json:"started_at"`
	Deadline   time.Time       `json:"deadline"`
	FinishedAt *time.Time      `json:"finished_at,omitempty"`
	// ReportedAt is when the executing replica last wrote the draft.
	ReportedAt time.Time `json:"-"`
}

Run is one background draft as get_run reads it.

type Store

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

Store keeps background drafts.

func NewStore

func NewStore(db *sql.DB) *Store

NewStore returns the store over db, or nil without one.

func (*Store) Get

func (s *Store) Get(ctx context.Context, id string) (*Run, error)

Get reads one background draft.

Jump to

Keyboard shortcuts

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