Documentation
¶
Overview ¶
Package deploymentpatch builds the deployment-patch primitives the watch loop needs: a managementapi.DeploymentPatchPoint describing a source tree (BuildPatchPoint) and the patch ops between two points (BuildPatchOps).
The per-file content hashes here must reproduce Truss's Python implementation bit-for-bit: the server-side build computes the signature with Python (truss/truss_handle/patch/{signature,dir_signature}.py), so a Go watch client that diffs against it has to match exactly.
Index ¶
- Variables
- func BuildPatchOps(ctx context.Context, opts BuildPatchOpsOptions) ([]managementapi.CreateDeploymentPatchRequest_PatchOps_Item, error)
- func BuildPatchPoint(ctx context.Context, opts BuildPatchPointOptions) (*managementapi.DeploymentPatchPoint, error)
- func CompileTrussIgnore(contents []byte) modelarchive.IgnoreFileFunc
- func ResolveTrussIgnore(dir string) (modelarchive.IgnoreFileFunc, error)
- func Watch(ctx context.Context, opts WatchOptions) (<-chan WatchEvent, error)
- type BuildPatchOpsOptions
- type BuildPatchPointOptions
- type WatchEvent
- type WatchOptions
Constants ¶
This section is empty.
Variables ¶
var ErrNeedsFullDeploy = errors.New("deploymentpatch: change cannot be patched, full deploy required")
ErrNeedsFullDeploy signals that the change between two patch points cannot be expressed as a patch and the deployment must be re-pushed. It corresponds to calc_truss_patch returning None (the caller should tell the user to run a full `baseten model push`). Only two changes trigger it, matching Truss: removing config.yaml, and any change strictly under the data directory.
Functions ¶
func BuildPatchOps ¶
func BuildPatchOps(ctx context.Context, opts BuildPatchOpsOptions) ([]managementapi.CreateDeploymentPatchRequest_PatchOps_Item, error)
BuildPatchOps computes the patch ops that take Prev to Next, porting truss/truss_handle/patch/calc_patch.py (calc_truss_patch). It returns ErrNeedsFullDeploy when the change can't be patched.
Unlike Truss, which re-globs and re-hashes the directory inside _calc_changed_paths, both sides already carry content_hashes (Next from BuildPatchPoint, Prev from the server), so we diff those maps directly. Likewise the config / env-var / external-data / requirement ops are derived from each point's stored Config text and Requirements list rather than being gated on config.yaml or the requirements file appearing in the changed paths: those fields only differ when Truss would have entered its config block, so the result is equivalent (see the per-section comments below).
func BuildPatchPoint ¶
func BuildPatchPoint(ctx context.Context, opts BuildPatchPointOptions) (*managementapi.DeploymentPatchPoint, error)
BuildPatchPoint walks opts.Dir and returns the patch point describing its current source state: the per-path content hashes, the verbatim config.yaml, and the requirements resolved from the config's requirements file (empty when requirements are inline).
This reproduces Truss's watch-client signature (calc_truss_signature over the local directory with the .truss_ignore patterns), so the result can be diffed against the server's patch state.
func CompileTrussIgnore ¶
func CompileTrussIgnore(contents []byte) modelarchive.IgnoreFileFunc
CompileTrussIgnore compiles raw .truss_ignore contents into an ignore predicate using gitignore semantics.
func ResolveTrussIgnore ¶
func ResolveTrussIgnore(dir string) (modelarchive.IgnoreFileFunc, error)
ResolveTrussIgnore returns the ignore predicate for a model directory: a .truss_ignore file at the root of dir takes precedence, otherwise the built-in defaults (modelarchive.DefaultIgnoreFile) apply.
The same predicate must drive both the archive upload (push) and the local source signature (watch); if they disagree on which paths exist, the watch client's content hashes will not line up with the server's.
func Watch ¶
func Watch(ctx context.Context, opts WatchOptions) (<-chan WatchEvent, error)
Watch watches opts.Dir recursively and returns a channel that receives one WatchEvent per debounced batch of changes to non-ignored paths. Changes to ignored paths (per ResolveTrussIgnore) never wake the caller.
Mirroring Truss (which watches recursively and filters each event through one ignore predicate), the same ignore drives both the watch and the patch computation. An entry-ignored directory (.git) is pruned from the watch entirely; a contents-only-ignored directory (__pycache__, kept as a null entry for hash parity) is still watched, but its events are filtered out.
The filter is best-effort, not authoritative: a spurious wake is harmless because the caller re-derives the patch point on each tick and finds zero ops.
The channel is closed when ctx is cancelled or the watcher fails. A setup failure (bad directory, watcher creation) is returned synchronously instead.
Types ¶
type BuildPatchOpsOptions ¶
type BuildPatchOpsOptions struct {
// Dir is the model directory holding the current (Next) source. Required;
// file contents for model-code and package ops are read from here.
Dir string
// Prev is the patch point being patched off of (the server's running or
// pending point). Required.
Prev *managementapi.DeploymentPatchPoint
// Next is the current local source state, as built by [BuildPatchPoint].
// Required.
Next *managementapi.DeploymentPatchPoint
// HotReload requests hot reload. Mirroring Truss, it only takes effect when
// every resulting op is a model-code change; mixed patches fall back to a
// cold restart.
HotReload bool
}
BuildPatchOpsOptions configures BuildPatchOps.
type BuildPatchPointOptions ¶
type BuildPatchPointOptions struct {
// Dir is the model directory whose source state is captured. Required.
Dir string
}
BuildPatchPointOptions configures BuildPatchPoint.
type WatchEvent ¶
type WatchEvent struct {
Err error
}
WatchEvent is one item on the channel returned by Watch. A zero value signals a debounced batch of filesystem changes under the watched directory. A non-nil Err means the underlying watcher failed and the channel is about to close; the caller should stop watching.