feat(selfupdate): defer self-replacement until response flushed
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
package selfupdate_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/shcizo/package-updater/internal/discovery"
|
||||
"github.com/shcizo/package-updater/internal/selfupdate"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type recExec struct {
|
||||
mu sync.Mutex
|
||||
called bool
|
||||
at time.Time
|
||||
}
|
||||
|
||||
func (r *recExec) Execute(_ context.Context, _ discovery.Job) error {
|
||||
r.mu.Lock()
|
||||
r.called = true
|
||||
r.at = time.Now()
|
||||
r.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestIsSelf(t *testing.T) {
|
||||
require.True(t, selfupdate.IsSelf(
|
||||
discovery.Job{Project: "package-updater", Service: "package-updater"},
|
||||
"package-updater",
|
||||
))
|
||||
require.False(t, selfupdate.IsSelf(
|
||||
discovery.Job{Project: "other", Service: "web"},
|
||||
"package-updater",
|
||||
))
|
||||
}
|
||||
|
||||
func TestWrap_DefersSelf(t *testing.T) {
|
||||
inner := &recExec{}
|
||||
wrapped := selfupdate.Wrap(inner, "package-updater", 30*time.Millisecond)
|
||||
|
||||
flushed := make(chan time.Time, 1)
|
||||
flush := func() { flushed <- time.Now() }
|
||||
|
||||
job := discovery.Job{Project: "package-updater", Service: "package-updater"}
|
||||
require.NoError(t, wrapped.ExecuteWithFlush(context.Background(), job, flush))
|
||||
|
||||
flushAt := <-flushed
|
||||
inner.mu.Lock()
|
||||
require.True(t, inner.called)
|
||||
require.True(t, inner.at.After(flushAt))
|
||||
inner.mu.Unlock()
|
||||
}
|
||||
|
||||
func TestWrap_NormalJobIsImmediate(t *testing.T) {
|
||||
inner := &recExec{}
|
||||
wrapped := selfupdate.Wrap(inner, "package-updater", 30*time.Millisecond)
|
||||
|
||||
flushed := make(chan time.Time, 1)
|
||||
flush := func() { flushed <- time.Now() }
|
||||
|
||||
job := discovery.Job{Project: "other", Service: "web"}
|
||||
require.NoError(t, wrapped.ExecuteWithFlush(context.Background(), job, flush))
|
||||
|
||||
inner.mu.Lock()
|
||||
require.True(t, inner.called)
|
||||
inner.mu.Unlock()
|
||||
select {
|
||||
case <-flushed:
|
||||
t.Fatal("flush should not be called for non-self jobs")
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrap_PropagatesError(t *testing.T) {
|
||||
wrapped := selfupdate.Wrap(failExec{}, "x", 1*time.Millisecond)
|
||||
err := wrapped.ExecuteWithFlush(context.Background(), discovery.Job{Project: "other"}, func() {})
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
type failExec struct{}
|
||||
|
||||
func (failExec) Execute(_ context.Context, _ discovery.Job) error {
|
||||
return errors.New("boom")
|
||||
}
|
||||
Reference in New Issue
Block a user