From f7f48d57e9260f4e076e47013318714a52527b2f Mon Sep 17 00:00:00 2001 From: Ophestra Date: Wed, 15 Apr 2026 15:35:45 +0900 Subject: [PATCH] internal/pkg: pass impure job count This is cleaner than checking cpu count during cure, it is impossible to avoid impurity in both situations but this is configurable. Signed-off-by: Ophestra --- cmd/mbf/main.go | 7 ++++++- internal/pkg/pkg.go | 18 ++++++++++++++---- internal/pkg/pkg_test.go | 12 ++++++------ internal/rosa/rosa_test.go | 2 +- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/cmd/mbf/main.go b/cmd/mbf/main.go index c79a61bf..a9d9a0c8 100644 --- a/cmd/mbf/main.go +++ b/cmd/mbf/main.go @@ -72,6 +72,7 @@ func main() { var ( flagQuiet bool flagCures int + flagJobs int flagBase string flagIdle bool @@ -99,7 +100,7 @@ func main() { if flagHostAbstract { flags |= pkg.CHostAbstract } - cache, err = pkg.Open(ctx, msg, flags, flagCures, base) + cache, err = pkg.Open(ctx, msg, flags, flagCures, flagJobs, base) return }).Flag( @@ -110,6 +111,10 @@ func main() { &flagCures, "cures", command.IntFlag(0), "Maximum number of dependencies to cure at any given time", + ).Flag( + &flagJobs, + "jobs", command.IntFlag(0), + "Preferred number of jobs to run, when applicable", ).Flag( &flagBase, "d", command.StringFlag("$MBF_CACHE_DIR"), diff --git a/internal/pkg/pkg.go b/internal/pkg/pkg.go index 1ecd4b5c..b2eceb25 100644 --- a/internal/pkg/pkg.go +++ b/internal/pkg/pkg.go @@ -188,6 +188,10 @@ func (c *common) Unwrap() context.Context { return c.cache.ctx } // GetMessage returns [message.Msg] held by the underlying [Cache]. func (c *common) GetMessage() message.Msg { return c.cache.msg } +// GetJobs returns the preferred number of jobs to run, when applicable. Its +// value must not affect cure outcome. +func (c *common) GetJobs() int { return c.cache.jobs } + // GetWorkDir returns a pathname to a directory which [Artifact] is expected to // write its output to. This is not the final resting place of the [Artifact] // and this pathname should not be directly referred to in the final contents. @@ -552,6 +556,8 @@ type Cache struct { base *check.Absolute // Immutable cure options set by [Open]. flags int + // Immutable job count, when applicable. + jobs int // Artifact to [unique.Handle] of identifier cache. artifact sync.Map @@ -1818,7 +1824,7 @@ func (c *Cache) Close() { // caller-supplied value, however direct calls to [Cache.Cure] is not subject // to this limitation. // -// A cures value of 0 or lower is equivalent to the value returned by +// A cures or jobs value of 0 or lower is equivalent to the value returned by // [runtime.NumCPU]. // // A successful call to Open guarantees exclusive access to the on-filesystem @@ -1828,10 +1834,10 @@ func (c *Cache) Close() { func Open( ctx context.Context, msg message.Msg, - flags, cures int, + flags, cures, jobs int, base *check.Absolute, ) (*Cache, error) { - return open(ctx, msg, flags, cures, base, true) + return open(ctx, msg, flags, cures, jobs, base, true) } // open implements Open but allows omitting the [lockedfile] lock when called @@ -1839,13 +1845,16 @@ func Open( func open( ctx context.Context, msg message.Msg, - flags, cures int, + flags, cures, jobs int, base *check.Absolute, lock bool, ) (*Cache, error) { if cures < 1 { cures = runtime.NumCPU() } + if jobs < 1 { + jobs = runtime.NumCPU() + } for _, name := range []string{ dirIdentifier, @@ -1862,6 +1871,7 @@ func open( c := Cache{ cures: make(chan struct{}, cures), flags: flags, + jobs: jobs, msg: msg, base: base, diff --git a/internal/pkg/pkg_test.go b/internal/pkg/pkg_test.go index b2a5dfbc..387f7b31 100644 --- a/internal/pkg/pkg_test.go +++ b/internal/pkg/pkg_test.go @@ -35,7 +35,7 @@ import ( func unsafeOpen( ctx context.Context, msg message.Msg, - flags, cures int, + flags, cures, jobs int, base *check.Absolute, lock bool, ) (*pkg.Cache, error) @@ -230,7 +230,7 @@ func TestIdent(t *testing.T) { var cache *pkg.Cache if a, err := check.NewAbs(t.TempDir()); err != nil { t.Fatal(err) - } else if cache, err = pkg.Open(t.Context(), msg, 0, 0, a); err != nil { + } else if cache, err = pkg.Open(t.Context(), msg, 0, 0, 0, a); err != nil { t.Fatal(err) } t.Cleanup(cache.Close) @@ -304,7 +304,7 @@ func checkWithCache(t *testing.T, testCases []cacheTestCase) { } var scrubFunc func() error // scrub after hashing - if c, err := pkg.Open(t.Context(), msg, flags, 1<<4, base); err != nil { + if c, err := pkg.Open(t.Context(), msg, flags, 1<<4, 0, base); err != nil { t.Fatalf("Open: error = %v", err) } else { t.Cleanup(c.Close) @@ -606,7 +606,7 @@ func TestCache(t *testing.T) { if c0, err := unsafeOpen( t.Context(), message.New(nil), - 0, 0, base, false, + 0, 0, 0, base, false, ); err != nil { t.Fatalf("open: error = %v", err) } else { @@ -1263,7 +1263,7 @@ func TestNew(t *testing.T) { if _, err := pkg.Open( t.Context(), message.New(nil), - 0, 0, check.MustAbs(container.Nonexistent), + 0, 0, 0, check.MustAbs(container.Nonexistent), ); !reflect.DeepEqual(err, wantErr) { t.Errorf("Open: error = %#v, want %#v", err, wantErr) } @@ -1291,7 +1291,7 @@ func TestNew(t *testing.T) { if _, err := pkg.Open( t.Context(), message.New(nil), - 0, 0, tempDir.Append("cache"), + 0, 0, 0, tempDir.Append("cache"), ); !reflect.DeepEqual(err, wantErr) { t.Errorf("Open: error = %#v, want %#v", err, wantErr) } diff --git a/internal/rosa/rosa_test.go b/internal/rosa/rosa_test.go index fd92547c..0386aee7 100644 --- a/internal/rosa/rosa_test.go +++ b/internal/rosa/rosa_test.go @@ -60,7 +60,7 @@ func getCache(t *testing.T) *pkg.Cache { msg := message.New(log.New(os.Stderr, "rosa: ", 0)) msg.SwapVerbose(true) - if buildTestCache, err = pkg.Open(ctx, msg, 0, 0, a); err != nil { + if buildTestCache, err = pkg.Open(ctx, msg, 0, 0, 0, a); err != nil { t.Fatal(err) } }