Documentation
¶
Overview ¶
- secretsreconcile — the level-triggered reconcile loop.
- ForceRevokeSecret fan-out — revocation is absence (I12).
Notify never carries secret material: it only shrinks latency. If a notify fails, the reconcile loop converges the workspace on a later pass (I3: notify failure costs latency, never correctness).
M2 (validation): a 429 that carries retryAfterMs schedules ONE deferred retry (capped 2.5s) so a rapid second mutation does not lose its notify until the next 60s loop pass. The retry runs detached from any request context, never blocks the bind path, is canceled by Stop, and never schedules a second retry — if the retry also 429s, the reconcile loop owns convergence.
Index ¶
- Variables
- type ModelCache
- type NotifyResult
- type Option
- func WithHTTPClient(c *http.Client) Option
- func WithLogger(l pkginterfaces.LoggerInterface) Option
- func WithModelCache(c ModelCache) Option
- func WithNotifyMetricsHook(hook func(outcome string)) Option
- func WithPasswordProvider(p PasswordProvider) Option
- func WithPodIPResolver(r PodIPResolver) Option
- type PasswordProvider
- type PodIPResolver
- type Service
- func (s *Service) Notify(ctx context.Context, userID, workspaceID string) (NotifyResult, error)
- func (s *Service) PushDevPreviewState(ctx context.Context, userID, workspaceID string, enabled bool) error
- func (s *Service) PushUserTimezone(ctx context.Context, userID, workspaceID, timezone string) error
- func (s *Service) Stop()
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNoPodIPResolver — the service was constructed without a resolver. // A wiring bug; the service can't deliver anything and should not have // been used. Return 503 at the HTTP boundary. ErrNoPodIPResolver = errors.New("agentpush: pod IP resolver not configured") // ErrNoRunningPod — the workspace exists but has no reachable pod // right now (Pending, Suspended, or recreating). Not a hard failure: // user-initiated callers surface 409, background callers log at info // and record the "no_pod" metric outcome (transient during pod boot // races). ErrNoRunningPod = errors.New("agentpush: workspace has no running pod") // ErrNoPasswordProvider — the service was constructed without a // password provider. A wiring bug; agentd enforces Basic auth on the // user mux (#848) so the dispatch cannot succeed. ErrNoPasswordProvider = errors.New("agentpush: password provider not configured") )
Sentinels — callers switch on these to map to HTTP status codes.
Functions ¶
This section is empty.
Types ¶
type ModelCache ¶
type ModelCache interface {
Evict(workspaceID string)
}
ModelCache is invalidated after a notify the pod acted on (applied) so ListModels refetches against the fresh provider set. Optional; nil skips the eviction.
type NotifyResult ¶ added in v0.27.0
type NotifyResult struct {
Status string `json:"status"`
AppliedRev string `json:"appliedRev"`
Restarted bool `json:"restarted"`
}
NotifyResult reports what agentd did with the resync request.
type Option ¶
type Option func(*Service)
Option configures a Service.
func WithHTTPClient ¶
WithHTTPClient overrides the default 5s-timeout HTTP client (tests).
func WithLogger ¶
func WithLogger(l pkginterfaces.LoggerInterface) Option
WithLogger installs the logger used for non-fatal warnings.
func WithModelCache ¶
func WithModelCache(c ModelCache) Option
WithModelCache installs the cache to evict after the pod applied a resync.
func WithNotifyMetricsHook ¶ added in v0.27.0
WithNotifyMetricsHook installs an outcome-recording callback for notify dispatches. Outcomes: "success", "rate_limited", "retry_scheduled" (a 429's deferred retry was armed; it records its own outcome when it fires), "no_pod", "failed". Optional; nil is silently skipped.
func WithPasswordProvider ¶ added in v0.15.9
func WithPasswordProvider(p PasswordProvider) Option
WithPasswordProvider installs the workspace-password lookup required for the authenticated dispatch (#848).
func WithPodIPResolver ¶
func WithPodIPResolver(r PodIPResolver) Option
WithPodIPResolver installs the pod-IP lookup.
type PasswordProvider ¶ added in v0.15.9
type PasswordProvider interface {
WorkspacePassword(ctx context.Context, workspaceID string) (string, error)
}
PasswordProvider resolves the workspace's agentd Basic-auth password. agentd rejects unauthenticated posts on its user mux (#848); satisfied by interfaces.WorkspacePasswordProvider (US-46.11).
type PodIPResolver ¶
type PodIPResolver interface {
GetWorkspacePodIP(ctx context.Context, userID, workspaceID string) (string, error)
}
PodIPResolver looks up the running pod IP for a workspace. Returns an empty string (and nil error, or a wrapped one) when no pod is running.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service is the concrete notifier.
func New ¶
New builds a Service from options alone: a notify carries no payload, so there is no builder dependency. podResolver/passwords may be nil during early wiring, in which case Notify returns the corresponding sentinel.
func (*Service) Notify ¶ added in v0.27.0
Notify asks the workspace pod's agentd to re-pull its secret batch via POST /v1/resync-secrets: an empty body, the workspace-password Basic credential, and nothing else. The pod performs the v2 conditional bootstrap pull in-process and reports what it applied.
Outcome contract:
- 200 (applied | not_modified) → nil error, NotifyResult decoded.
- 429 rate_limited → nil error: the pod is rate-limiting pulls. When the 429 carries retryAfterMs, ONE deferred retry is armed (min(retryAfterMs, 2.5s); M2) and the dispatch counts as "retry_scheduled"; without retryAfterMs (or after Stop) it stays "rate_limited" — the pod resyncs under its own budget either way.
- 502 failed (pull_failed | pull_unauthorized) and every transport failure → error. Callers treat these as latency loss only; the reconcile loop retries with backoff (I3).
func (*Service) PushDevPreviewState ¶ added in v0.34.17
func (s *Service) PushDevPreviewState(ctx context.Context, userID, workspaceID string, enabled bool) error
PushDevPreviewState delivers the workspace's absolute dev-preview state to the running pod's agentd (POST /v1/dev-preview-state) so feature_status / dev_preview_url report the live toggle instead of the boot-time env snapshot (#1617). Fire-and-forget by design: the CRD remains the source of truth, a failed push costs only in-pod report latency, and the next pod build re-projects the env correctly.
func (*Service) PushUserTimezone ¶ added in v0.31.0
PushUserTimezone delivers the user's browser-reported IANA zone to a workspace pod's agentd (POST /v1/user-timezone) so get_datetime can render user-local time. Fire-and-forget by design: failures are latency-only — the next browser (re)connect re-pushes, and the pod keeps its last-known zone meanwhile.