chore: executor_test: reduce test execution time (#1876)

Removes 5-second wait in autobuild.executor unit tests:

- Adds a write-only channel to Executor and plumbs through to unit tests
- Modifies runOnce to return an executor.RunStats struct and write to statsCh if not nil
This commit is contained in:
Cian Johnston
2022-05-30 20:23:36 +01:00
committed by GitHub
parent ae4b2d88cd
commit e02ef6f228
3 changed files with 181 additions and 128 deletions
@@ -17,10 +17,18 @@ import (
// Executor automatically starts or stops workspaces.
type Executor struct {
ctx context.Context
db database.Store
log slog.Logger
tick <-chan time.Time
ctx context.Context
db database.Store
log slog.Logger
tick <-chan time.Time
statsCh chan<- Stats
}
// Stats contains information about one run of Executor.
type Stats struct {
Transitions map[uuid.UUID]database.WorkspaceTransition
Elapsed time.Duration
Error error
}
// New returns a new autobuild executor.
@@ -34,22 +42,42 @@ func New(ctx context.Context, db database.Store, log slog.Logger, tick <-chan ti
return le
}
// WithStatsChannel will cause Executor to push a RunStats to ch after
// every tick.
func (e *Executor) WithStatsChannel(ch chan<- Stats) *Executor {
e.statsCh = ch
return e
}
// Run will cause executor to start or stop workspaces on every
// tick from its channel. It will stop when its context is Done, or when
// its channel is closed.
func (e *Executor) Run() {
go func() {
for t := range e.tick {
if err := e.runOnce(t); err != nil {
e.log.Error(e.ctx, "error running once", slog.Error(err))
stats := e.runOnce(t)
if stats.Error != nil {
e.log.Error(e.ctx, "error running once", slog.Error(stats.Error))
}
if e.statsCh != nil {
e.statsCh <- stats
}
e.log.Debug(e.ctx, "run stats", slog.F("elapsed", stats.Elapsed), slog.F("transitions", stats.Transitions))
}
}()
}
func (e *Executor) runOnce(t time.Time) error {
func (e *Executor) runOnce(t time.Time) Stats {
var err error
stats := Stats{
Transitions: make(map[uuid.UUID]database.WorkspaceTransition),
}
defer func() {
stats.Elapsed = time.Since(t)
stats.Error = err
}()
currentTick := t.Truncate(time.Minute)
return e.db.InTx(func(db database.Store) error {
err = e.db.InTx(func(db database.Store) error {
// TTL is set at the workspace level, and deadline at the workspace build level.
// When a workspace build is created, its deadline initially starts at zero.
// When provisionerd successfully completes a provision job, the deadline is
@@ -146,6 +174,7 @@ func (e *Executor) runOnce(t time.Time) error {
slog.F("transition", validTransition),
)
stats.Transitions[ws.ID] = validTransition
if err := build(e.ctx, db, ws, validTransition, priorHistory, priorJob); err != nil {
e.log.Error(e.ctx, "unable to transition workspace",
slog.F("workspace_id", ws.ID),
@@ -156,6 +185,7 @@ func (e *Executor) runOnce(t time.Time) error {
}
return nil
})
return stats
}
// TODO(cian): this function duplicates most of api.postWorkspaceBuilds. Refactor.