diff --git a/cmd/cachewd/main.go b/cmd/cachewd/main.go index 89bab72..a5baa5f 100644 --- a/cmd/cachewd/main.go +++ b/cmd/cachewd/main.go @@ -13,13 +13,15 @@ import ( "github.com/block/cachew/internal/config" "github.com/block/cachew/internal/httputil" + "github.com/block/cachew/internal/jobscheduler" "github.com/block/cachew/internal/logging" ) var cli struct { - Config *os.File `hcl:"-" help:"Configuration file path." placeholder:"PATH" required:"" default:"cachew.hcl"` - Bind string `hcl:"bind" default:"127.0.0.1:8080" help:"Bind address for the server."` - LoggingConfig logging.Config `embed:"" prefix:"log-"` + Config *os.File `hcl:"-" help:"Configuration file path." placeholder:"PATH" required:"" default:"cachew.hcl"` + Bind string `hcl:"bind" default:"127.0.0.1:8080" help:"Bind address for the server."` + SchedulerConfig jobscheduler.Config `embed:"" prefix:"scheduler-"` + LoggingConfig logging.Config `embed:"" prefix:"log-"` } func main() { @@ -30,7 +32,9 @@ func main() { mux := http.NewServeMux() - err := config.Load(ctx, cli.Config, mux, parseEnvars()) + scheduler := jobscheduler.New(ctx, cli.SchedulerConfig) + + err := config.Load(ctx, cli.Config, scheduler, mux, parseEnvars()) kctx.FatalIfErrorf(err) logger.InfoContext(ctx, "Starting cachewd", slog.String("bind", cli.Bind)) diff --git a/internal/cache/remote_test.go b/internal/cache/remote_test.go index 1229f17..f08a65a 100644 --- a/internal/cache/remote_test.go +++ b/internal/cache/remote_test.go @@ -11,6 +11,7 @@ import ( "github.com/block/cachew/internal/cache" "github.com/block/cachew/internal/cache/cachetest" + "github.com/block/cachew/internal/jobscheduler" "github.com/block/cachew/internal/logging" "github.com/block/cachew/internal/strategy" ) @@ -26,7 +27,7 @@ func TestRemoteClient(t *testing.T) { t.Cleanup(func() { memCache.Close() }) mux := http.NewServeMux() - _, err = strategy.NewAPIV1(ctx, struct{}{}, memCache, mux) + _, err = strategy.NewAPIV1(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), struct{}{}, memCache, mux) assert.NoError(t, err) ts := httptest.NewServer(mux) t.Cleanup(ts.Close) diff --git a/internal/config/config.go b/internal/config/config.go index 317cb7f..fdadd31 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -12,6 +12,7 @@ import ( "github.com/alecthomas/hcl/v2" "github.com/block/cachew/internal/cache" + "github.com/block/cachew/internal/jobscheduler" "github.com/block/cachew/internal/logging" "github.com/block/cachew/internal/strategy" _ "github.com/block/cachew/internal/strategy/git" // Register git strategy @@ -35,7 +36,7 @@ func (l *loggingMux) HandleFunc(pattern string, handler func(http.ResponseWriter var _ strategy.Mux = (*loggingMux)(nil) // Load HCL configuration and uses that to construct the cache backend, and proxy strategies. -func Load(ctx context.Context, r io.Reader, mux *http.ServeMux, vars map[string]string) error { +func Load(ctx context.Context, r io.Reader, scheduler jobscheduler.Scheduler, mux *http.ServeMux, vars map[string]string) error { logger := logging.FromContext(ctx) ast, err := hcl.Parse(r) if err != nil { @@ -79,7 +80,7 @@ func Load(ctx context.Context, r io.Reader, mux *http.ServeMux, vars map[string] for _, block := range strategyCandidates { logger := logger.With("strategy", block.Name) mlog := &loggingMux{logger: logger, mux: mux} - _, err := strategy.Create(ctx, block.Name, block, cache, mlog) + _, err := strategy.Create(ctx, scheduler.WithQueuePrefix(block.Name), block.Name, block, cache, mlog) if err != nil { return errors.Errorf("%s: %w", block.Pos, err) } diff --git a/internal/jobscheduler/jobs.go b/internal/jobscheduler/jobs.go index aaf2580..03c45e7 100644 --- a/internal/jobscheduler/jobs.go +++ b/internal/jobscheduler/jobs.go @@ -26,28 +26,47 @@ type queueJob struct { func (j *queueJob) String() string { return fmt.Sprintf("job-%s-%s", j.queue, j.id) } func (j *queueJob) Run(ctx context.Context) error { return errors.WithStack(j.run(ctx)) } +// Scheduler runs background jobs concurrently across multiple serialised queues. +// +// That is, each queue can have at most one job running at a time, but multiple queues can run concurrently. +// +// Its primary role is to rate limit concurrent background tasks so that we don't DoS the host when, for example, +// generating git snapshots, GCing git repos, etc. type Scheduler interface { + // WithQueuePrefix creates a new Scheduler that prefixes all queue names with the given prefix. + // + // This is useful to avoid collisions across strategies. + WithQueuePrefix(prefix string) Scheduler + // Submit a job to the queue. + // + // Jobs run concurrently across queues, but never within a queue. Submit(queue, id string, run func(ctx context.Context) error) + // SubmitPeriodicJob submits a job to the queue that runs immediately, and then periodically after the interval. + // + // Jobs run concurrently across queues, but never within a queue. SubmitPeriodicJob(queue, id string, interval time.Duration, run func(ctx context.Context) error) } -type PrefixedScheduler struct { +type prefixedScheduler struct { prefix string scheduler Scheduler } -func (ps *PrefixedScheduler) Submit(queue, id string, run func(ctx context.Context) error) { - ps.scheduler.Submit(ps.prefix+queue, id, run) +func (p *prefixedScheduler) Submit(queue, id string, run func(ctx context.Context) error) { + p.scheduler.Submit(p.prefix+queue, id, run) } -func (ps *PrefixedScheduler) SubmitPeriodicJob(queue, id string, interval time.Duration, run func(ctx context.Context) error) { - ps.scheduler.SubmitPeriodicJob(ps.prefix+queue, id, interval, run) +func (p *prefixedScheduler) SubmitPeriodicJob(queue, id string, interval time.Duration, run func(ctx context.Context) error) { + p.scheduler.SubmitPeriodicJob(p.prefix+queue, id, interval, run) +} + +func (p *prefixedScheduler) WithQueuePrefix(prefix string) Scheduler { + return &prefixedScheduler{ + prefix: p.prefix + "-" + prefix, + scheduler: p.scheduler, + } } -// RootScheduler runs jobs from multiple queues. -// -// Its primary role is to rate limit concurrent background tasks so that we don't DoS the host when, for example, -// generating git snapshots, GCing git repos, etc. type RootScheduler struct { workAvailable chan bool lock sync.Mutex @@ -75,19 +94,13 @@ func New(ctx context.Context, config Config) Scheduler { return q } -// WithQueuePrefix creates a new Scheduler that prefixes all queue names with the given prefix. -// -// This is useful to avoid collisions across strategies. func (q *RootScheduler) WithQueuePrefix(prefix string) Scheduler { - return &PrefixedScheduler{ - prefix: prefix, + return &prefixedScheduler{ + prefix: prefix + "-", scheduler: q, } } -// Submit a job to the queue. -// -// Jobs run concurrently across queues, but never within a queue. func (q *RootScheduler) Submit(queue, id string, run func(ctx context.Context) error) { q.lock.Lock() defer q.lock.Unlock() @@ -95,9 +108,6 @@ func (q *RootScheduler) Submit(queue, id string, run func(ctx context.Context) e q.workAvailable <- true } -// SubmitPeriodicJob submits a job to the queue that runs immediately, and then periodically after the interval. -// -// Jobs run concurrently across queues, but never within a queue. func (q *RootScheduler) SubmitPeriodicJob(queue, description string, interval time.Duration, run func(ctx context.Context) error) { q.Submit(queue, description, func(ctx context.Context) error { err := run(ctx) diff --git a/internal/strategy/api.go b/internal/strategy/api.go index ee908f4..886187f 100644 --- a/internal/strategy/api.go +++ b/internal/strategy/api.go @@ -9,6 +9,7 @@ import ( "github.com/alecthomas/hcl/v2" "github.com/block/cachew/internal/cache" + "github.com/block/cachew/internal/jobscheduler" ) // ErrNotFound is returned when a strategy is not found. @@ -19,27 +20,34 @@ type Mux interface { HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) } -var registry = map[string]func(ctx context.Context, config *hcl.Block, cache cache.Cache, mux Mux) (Strategy, error){} +var registry = map[string]func(ctx context.Context, scheduler jobscheduler.Scheduler, config *hcl.Block, cache cache.Cache, mux Mux) (Strategy, error){} -type Factory[Config any, S Strategy] func(ctx context.Context, config Config, cache cache.Cache, mux Mux) (S, error) +type Factory[Config any, S Strategy] func(ctx context.Context, scheduler jobscheduler.Scheduler, config Config, cache cache.Cache, mux Mux) (S, error) // Register a new proxy strategy. func Register[Config any, S Strategy](id string, factory Factory[Config, S]) { - registry[id] = func(ctx context.Context, config *hcl.Block, cache cache.Cache, mux Mux) (Strategy, error) { + registry[id] = func(ctx context.Context, scheduler jobscheduler.Scheduler, config *hcl.Block, cache cache.Cache, mux Mux) (Strategy, error) { var cfg Config if err := hcl.UnmarshalBlock(config, &cfg, hcl.AllowExtra(false)); err != nil { return nil, errors.WithStack(err) } - return factory(ctx, cfg, cache, mux) + return factory(ctx, scheduler, cfg, cache, mux) } } // Create a new proxy strategy. // // Will return "ErrNotFound" if the strategy is not found. -func Create(ctx context.Context, name string, config *hcl.Block, cache cache.Cache, mux Mux) (Strategy, error) { +func Create( + ctx context.Context, + scheduler jobscheduler.Scheduler, + name string, + config *hcl.Block, + cache cache.Cache, + mux Mux, +) (Strategy, error) { if factory, ok := registry[name]; ok { - return errors.WithStack2(factory(ctx, config, cache, mux)) + return errors.WithStack2(factory(ctx, scheduler.WithQueuePrefix(name), config, cache, mux)) } return nil, errors.Errorf("%s: %w", name, ErrNotFound) } diff --git a/internal/strategy/apiv1.go b/internal/strategy/apiv1.go index 167f21e..5d82da3 100644 --- a/internal/strategy/apiv1.go +++ b/internal/strategy/apiv1.go @@ -12,6 +12,7 @@ import ( "time" "github.com/block/cachew/internal/cache" + "github.com/block/cachew/internal/jobscheduler" "github.com/block/cachew/internal/logging" ) @@ -27,7 +28,7 @@ type APIV1 struct { logger *slog.Logger } -func NewAPIV1(ctx context.Context, _ struct{}, cache cache.Cache, mux Mux) (*APIV1, error) { +func NewAPIV1(ctx context.Context, _ jobscheduler.Scheduler, _ struct{}, cache cache.Cache, mux Mux) (*APIV1, error) { s := &APIV1{ logger: logging.FromContext(ctx), cache: cache, diff --git a/internal/strategy/artifactory.go b/internal/strategy/artifactory.go index fea0361..d107052 100644 --- a/internal/strategy/artifactory.go +++ b/internal/strategy/artifactory.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/block/cachew/internal/cache" + "github.com/block/cachew/internal/jobscheduler" "github.com/block/cachew/internal/logging" "github.com/block/cachew/internal/strategy/handler" ) @@ -52,7 +53,7 @@ type Artifactory struct { var _ Strategy = (*Artifactory)(nil) -func NewArtifactory(ctx context.Context, config ArtifactoryConfig, cache cache.Cache, mux Mux) (*Artifactory, error) { +func NewArtifactory(ctx context.Context, _ jobscheduler.Scheduler, config ArtifactoryConfig, cache cache.Cache, mux Mux) (*Artifactory, error) { u, err := url.Parse(config.Target) if err != nil { return nil, fmt.Errorf("invalid target URL: %w", err) diff --git a/internal/strategy/artifactory_test.go b/internal/strategy/artifactory_test.go index 363c941..6ee071f 100644 --- a/internal/strategy/artifactory_test.go +++ b/internal/strategy/artifactory_test.go @@ -11,6 +11,7 @@ import ( "github.com/alecthomas/assert/v2" "github.com/block/cachew/internal/cache" + "github.com/block/cachew/internal/jobscheduler" "github.com/block/cachew/internal/logging" "github.com/block/cachew/internal/strategy" ) @@ -63,7 +64,7 @@ func setupArtifactoryTest(t *testing.T, config strategy.ArtifactoryConfig) (*moc t.Cleanup(func() { memCache.Close() }) mux := http.NewServeMux() - _, err = strategy.NewArtifactory(ctx, config, memCache, mux) + _, err = strategy.NewArtifactory(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), config, memCache, mux) assert.NoError(t, err) return mock, mux, ctx @@ -210,7 +211,7 @@ func TestArtifactoryString(t *testing.T) { defer memCache.Close() mux := http.NewServeMux() - artifactory, err := strategy.NewArtifactory(ctx, strategy.ArtifactoryConfig{ + artifactory, err := strategy.NewArtifactory(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), strategy.ArtifactoryConfig{ Target: "https://ec2.example.jfrog.io", }, memCache, mux) assert.NoError(t, err) @@ -225,7 +226,7 @@ func TestArtifactoryInvalidTargetURL(t *testing.T) { defer memCache.Close() mux := http.NewServeMux() - _, err = strategy.NewArtifactory(ctx, strategy.ArtifactoryConfig{ + _, err = strategy.NewArtifactory(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), strategy.ArtifactoryConfig{ Target: "://invalid-url", }, memCache, mux) assert.Error(t, err) diff --git a/internal/strategy/git/bundle_test.go b/internal/strategy/git/bundle_test.go index 6a1160a..fa8481c 100644 --- a/internal/strategy/git/bundle_test.go +++ b/internal/strategy/git/bundle_test.go @@ -10,6 +10,7 @@ import ( "github.com/alecthomas/assert/v2" "github.com/block/cachew/internal/cache" + "github.com/block/cachew/internal/jobscheduler" "github.com/block/cachew/internal/logging" "github.com/block/cachew/internal/strategy/git" ) @@ -22,7 +23,7 @@ func TestBundleHTTPEndpoint(t *testing.T) { assert.NoError(t, err) mux := newTestMux() - _, err = git.New(ctx, git.Config{ + _, err = git.New(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), git.Config{ MirrorRoot: tmpDir, BundleInterval: 24 * time.Hour, }, memCache, mux) @@ -98,7 +99,7 @@ func TestBundleInterval(t *testing.T) { assert.NoError(t, err) mux := newTestMux() - s, err := git.New(ctx, git.Config{ + s, err := git.New(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), git.Config{ MirrorRoot: tmpDir, BundleInterval: tt.bundleInterval, }, memCache, mux) diff --git a/internal/strategy/git/git.go b/internal/strategy/git/git.go index f4bbcd3..94c7a74 100644 --- a/internal/strategy/git/git.go +++ b/internal/strategy/git/git.go @@ -17,6 +17,7 @@ import ( "github.com/alecthomas/errors" "github.com/block/cachew/internal/cache" + "github.com/block/cachew/internal/jobscheduler" "github.com/block/cachew/internal/logging" "github.com/block/cachew/internal/strategy" ) @@ -62,7 +63,7 @@ type Strategy struct { ctx context.Context } -func New(ctx context.Context, config Config, cache cache.Cache, mux strategy.Mux) (*Strategy, error) { +func New(ctx context.Context, _ jobscheduler.Scheduler, config Config, cache cache.Cache, mux strategy.Mux) (*Strategy, error) { logger := logging.FromContext(ctx) if config.MirrorRoot == "" { diff --git a/internal/strategy/git/git_test.go b/internal/strategy/git/git_test.go index 9942a3b..35f588d 100644 --- a/internal/strategy/git/git_test.go +++ b/internal/strategy/git/git_test.go @@ -10,6 +10,7 @@ import ( "github.com/alecthomas/assert/v2" + "github.com/block/cachew/internal/jobscheduler" "github.com/block/cachew/internal/logging" "github.com/block/cachew/internal/strategy/git" ) @@ -64,7 +65,7 @@ func TestNew(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { mux := newTestMux() - s, err := git.New(ctx, tt.config, nil, mux) + s, err := git.New(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), tt.config, nil, mux) if tt.wantError != "" { assert.Error(t, err) assert.Contains(t, err.Error(), tt.wantError) @@ -144,7 +145,7 @@ func TestNewWithExistingCloneOnDisk(t *testing.T) { assert.NoError(t, err) mux := newTestMux() - s, err := git.New(ctx, git.Config{ + s, err := git.New(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), git.Config{ MirrorRoot: tmpDir, FetchInterval: 15, }, nil, mux) @@ -167,7 +168,7 @@ func TestIntegrationWithMockUpstream(t *testing.T) { // Create strategy - it will register handlers mux := newTestMux() - _, err := git.New(ctx, git.Config{ + _, err := git.New(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), git.Config{ MirrorRoot: tmpDir, FetchInterval: 15, }, nil, mux) diff --git a/internal/strategy/git/integration_test.go b/internal/strategy/git/integration_test.go index a33bc80..f453b2c 100644 --- a/internal/strategy/git/integration_test.go +++ b/internal/strategy/git/integration_test.go @@ -16,6 +16,7 @@ import ( "github.com/alecthomas/assert/v2" + "github.com/block/cachew/internal/jobscheduler" "github.com/block/cachew/internal/logging" "github.com/block/cachew/internal/strategy/git" ) @@ -53,7 +54,7 @@ func TestIntegrationGitCloneViaProxy(t *testing.T) { // Create the git strategy mux := http.NewServeMux() - strategy, err := git.New(ctx, git.Config{ + strategy, err := git.New(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), git.Config{ MirrorRoot: clonesDir, FetchInterval: 15, }, nil, mux) @@ -131,7 +132,7 @@ func TestIntegrationGitFetchViaProxy(t *testing.T) { assert.NoError(t, err) mux := http.NewServeMux() - _, err = git.New(ctx, git.Config{ + _, err = git.New(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), git.Config{ MirrorRoot: clonesDir, FetchInterval: 15, }, nil, mux) @@ -210,7 +211,7 @@ func TestIntegrationPushForwardsToUpstream(t *testing.T) { defer upstreamServer.Close() mux := http.NewServeMux() - _, err = git.New(ctx, git.Config{ + _, err = git.New(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), git.Config{ MirrorRoot: clonesDir, FetchInterval: 15, }, nil, mux) diff --git a/internal/strategy/github_releases.go b/internal/strategy/github_releases.go index 7874712..2819261 100644 --- a/internal/strategy/github_releases.go +++ b/internal/strategy/github_releases.go @@ -12,6 +12,7 @@ import ( "github.com/block/cachew/internal/cache" "github.com/block/cachew/internal/httputil" + "github.com/block/cachew/internal/jobscheduler" "github.com/block/cachew/internal/logging" "github.com/block/cachew/internal/strategy/handler" ) @@ -33,7 +34,7 @@ type GitHubReleases struct { } // NewGitHubReleases creates a [Strategy] that fetches private (and public) release binaries from GitHub. -func NewGitHubReleases(ctx context.Context, config GitHubReleasesConfig, cache cache.Cache, mux Mux) (*GitHubReleases, error) { +func NewGitHubReleases(ctx context.Context, _ jobscheduler.Scheduler, config GitHubReleasesConfig, cache cache.Cache, mux Mux) (*GitHubReleases, error) { s := &GitHubReleases{ config: config, cache: cache, diff --git a/internal/strategy/github_releases_test.go b/internal/strategy/github_releases_test.go index 7518a04..c570f63 100644 --- a/internal/strategy/github_releases_test.go +++ b/internal/strategy/github_releases_test.go @@ -14,6 +14,7 @@ import ( "github.com/alecthomas/assert/v2" "github.com/block/cachew/internal/cache" + "github.com/block/cachew/internal/jobscheduler" "github.com/block/cachew/internal/logging" "github.com/block/cachew/internal/strategy" ) @@ -126,7 +127,7 @@ func setupTest(t *testing.T, config strategy.GitHubReleasesConfig) (*mockGitHubS t.Cleanup(func() { memCache.Close() }) mux := http.NewServeMux() - _, err = strategy.NewGitHubReleases(ctx, config, memCache, mux) + _, err = strategy.NewGitHubReleases(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), config, memCache, mux) assert.NoError(t, err) return mock, mux, ctx @@ -241,7 +242,7 @@ func TestGitHubReleasesNoToken(t *testing.T) { defer memCache.Close() mux := http.NewServeMux() - gh, err := strategy.NewGitHubReleases(ctx, strategy.GitHubReleasesConfig{}, memCache, mux) + gh, err := strategy.NewGitHubReleases(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), strategy.GitHubReleasesConfig{}, memCache, mux) assert.NoError(t, err) assert.Equal(t, "github-releases", gh.String()) } @@ -253,7 +254,7 @@ func TestGitHubReleasesString(t *testing.T) { defer memCache.Close() mux := http.NewServeMux() - gh, err := strategy.NewGitHubReleases(ctx, strategy.GitHubReleasesConfig{ + gh, err := strategy.NewGitHubReleases(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), strategy.GitHubReleasesConfig{ Token: "test-token", }, memCache, mux) assert.NoError(t, err) diff --git a/internal/strategy/host.go b/internal/strategy/host.go index 31fedb2..b5ee874 100644 --- a/internal/strategy/host.go +++ b/internal/strategy/host.go @@ -8,6 +8,7 @@ import ( "net/url" "github.com/block/cachew/internal/cache" + "github.com/block/cachew/internal/jobscheduler" "github.com/block/cachew/internal/logging" "github.com/block/cachew/internal/strategy/handler" ) @@ -40,7 +41,7 @@ type Host struct { var _ Strategy = (*Host)(nil) -func NewHost(ctx context.Context, config HostConfig, cache cache.Cache, mux Mux) (*Host, error) { +func NewHost(ctx context.Context, _ jobscheduler.Scheduler, config HostConfig, cache cache.Cache, mux Mux) (*Host, error) { u, err := url.Parse(config.Target) if err != nil { return nil, fmt.Errorf("invalid target URL: %w", err) diff --git a/internal/strategy/host_test.go b/internal/strategy/host_test.go index 1f8442b..44bb48c 100644 --- a/internal/strategy/host_test.go +++ b/internal/strategy/host_test.go @@ -12,6 +12,7 @@ import ( "github.com/alecthomas/assert/v2" "github.com/block/cachew/internal/cache" + "github.com/block/cachew/internal/jobscheduler" "github.com/block/cachew/internal/logging" "github.com/block/cachew/internal/strategy" ) @@ -31,7 +32,7 @@ func TestHostCaching(t *testing.T) { defer memCache.Close() mux := http.NewServeMux() - _, err = strategy.NewHost(ctx, strategy.HostConfig{Target: backend.URL}, memCache, mux) + _, err = strategy.NewHost(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), strategy.HostConfig{Target: backend.URL}, memCache, mux) assert.NoError(t, err) // Request path must include the host prefix from the target URL @@ -68,7 +69,7 @@ func TestHostNonOKStatus(t *testing.T) { defer memCache.Close() mux := http.NewServeMux() - _, err = strategy.NewHost(ctx, strategy.HostConfig{Target: backend.URL}, memCache, mux) + _, err = strategy.NewHost(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), strategy.HostConfig{Target: backend.URL}, memCache, mux) assert.NoError(t, err) // Request path must include the host prefix from the target URL @@ -94,7 +95,7 @@ func TestHostInvalidTargetURL(t *testing.T) { defer memCache.Close() mux := http.NewServeMux() - _, err = strategy.NewHost(ctx, strategy.HostConfig{Target: "://invalid"}, memCache, mux) + _, err = strategy.NewHost(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), strategy.HostConfig{Target: "://invalid"}, memCache, mux) assert.Error(t, err) } @@ -105,7 +106,7 @@ func TestHostString(t *testing.T) { defer memCache.Close() mux := http.NewServeMux() - host, err := strategy.NewHost(ctx, strategy.HostConfig{Target: "https://example.com/prefix"}, memCache, mux) + host, err := strategy.NewHost(ctx, jobscheduler.New(ctx, jobscheduler.Config{}), strategy.HostConfig{Target: "https://example.com/prefix"}, memCache, mux) assert.NoError(t, err) assert.Equal(t, "host:example.com/prefix", host.String())