diff --git a/modules/mesh-build-go/buildstep/pull_bus.go b/modules/mesh-build-go/buildstep/pull_bus.go index 8633ed77b..20c0528be 100644 --- a/modules/mesh-build-go/buildstep/pull_bus.go +++ b/modules/mesh-build-go/buildstep/pull_bus.go @@ -93,7 +93,8 @@ func DeclareAskWorkers(ctx context.Context, js jetstream.JetStream, language str for _, kind := range sdkstep.AskKinds { worker, _ := sdkstep.AskWorker(language, kind) subject, _ := sdkstep.AskSubject(language, kind) - if _, err := js.CreateOrUpdateConsumer(ctx, stream, jetstream.ConsumerConfig{Durable: worker, FilterSubject: subject, + // Both forms of the accept subject: main's and the asker's, `.` (design 47 G §600). + if _, err := js.CreateOrUpdateConsumer(ctx, stream, jetstream.ConsumerConfig{Durable: worker, FilterSubjects: []string{subject, subject + ".*"}, AckPolicy: jetstream.AckExplicitPolicy, AckWait: ackWait, MaxDeliver: 5}); err != nil { return fmt.Errorf("the worker %s: %w", worker, err) } diff --git a/modules/mesh-build-go/buildstep/pull_integration_test.go b/modules/mesh-build-go/buildstep/pull_integration_test.go index 63bfc2df2..d6f043a6f 100644 --- a/modules/mesh-build-go/buildstep/pull_integration_test.go +++ b/modules/mesh-build-go/buildstep/pull_integration_test.go @@ -196,3 +196,32 @@ func TestAnAskThatMetTheNetworkIsGivenAgainAndADroppedOneIsEnded(t *testing.T) { } func contains(s, sub string) bool { return strings.Contains(s, sub) } + +// Design 47 G §600: the seat's worker takes an ask put on either form of the accept subject, main's and the asker's. +func TestTheWorkerTakesBothFormsOfTheAcceptSubject(t *testing.T) { + js := askBus(t, 30*time.Second) + stream, _ := sdkstep.AskStream(sdkstep.AskGo) + worker, _ := sdkstep.AskWorker(sdkstep.AskGo, sdkstep.AskDelivery) + main, _ := sdkstep.AskSubject(sdkstep.AskGo, sdkstep.AskDelivery) + for _, subject := range []string{main, main + ".builder"} { + if _, err := js.Publish(context.Background(), subject, []byte("{}")); err != nil { + t.Fatal(err) + } + } + c, err := js.Consumer(context.Background(), stream, worker) + if err != nil { + t.Fatal(err) + } + batch, err := c.Fetch(2, jetstream.FetchMaxWait(3*time.Second)) + if err != nil { + t.Fatal(err) + } + var got []string + for m := range batch.Messages() { + got = append(got, m.Subject()) + _ = m.Ack() + } + if len(got) != 2 { + t.Errorf("the worker took %v, want both forms of %s", got, main) + } +} diff --git a/modules/mesh-build-node/cmd/mesh-build-node/fetch.go b/modules/mesh-build-node/cmd/mesh-build-node/fetch.go index 8d96b6641..79828d1e3 100644 --- a/modules/mesh-build-node/cmd/mesh-build-node/fetch.go +++ b/modules/mesh-build-node/cmd/mesh-build-node/fetch.go @@ -260,7 +260,7 @@ func (m *Module) typeScriptModules(ctx context.Context, tree string) (dirs []str return dirs, packages, nil } -// ownDependencies are the package.json's dependencies beyond the SDK and beyond what is build-time: the types and +// ownDependencies are the package.json's dependencies beyond the mesh's own packages (@novox/mesh-*, design 47 G A-72) and beyond what is build-time: the types and // typescript, which the toolchain carries (dependencies.go:49-70). Sorted; none for a module without a package.json. func ownDependencies(dir string) (names []string, pkg map[string]any, err error) { raw, err := os.ReadFile(filepath.Join(dir, "package.json")) @@ -275,7 +275,7 @@ func ownDependencies(dir string) (names []string, pkg map[string]any, err error) } deps, _ := pkg["dependencies"].(map[string]any) for name := range deps { - if name != sdkPackage && name != "typescript" && !strings.HasPrefix(name, "@types/") { + if name != sdkPackage && !strings.HasPrefix(name, "@novox/mesh-") && name != "typescript" && !strings.HasPrefix(name, "@types/") { names = append(names, name) } } diff --git a/modules/mesh-build-node/cmd/mesh-build-node/fetch_test.go b/modules/mesh-build-node/cmd/mesh-build-node/fetch_test.go index 76bda1a28..d88060097 100644 --- a/modules/mesh-build-node/cmd/mesh-build-node/fetch_test.go +++ b/modules/mesh-build-node/cmd/mesh-build-node/fetch_test.go @@ -96,6 +96,20 @@ func TestAModuleNamingOnlyTheSdkAndTypesInstallsNothing(t *testing.T) { } } +// 47/G A-72: a module naming another @novox/mesh-* package beside the SDK has no package beyond the SDK, so it installs +// nothing and is not refused for want of a lock. +func TestAMeshPackageIsNotBeyondTheSdk(t *testing.T) { + m, f := fetchMachine(t, typeScriptModule(`{"dependencies":{"@novox/mesh-sdk":"^0.1.6","@novox/mesh-tools":"^0.1.6"}}`), nil) + out, err := m.fetch(context.Background(), fetchArgs) + if err != nil { + t.Fatal(err) + } + r := out.(FetchResult) + if len(npmCalls(f)) != 0 || len(r.Installed) != 0 || len(r.Refused) != 0 { + t.Errorf("result = %+v, npm calls %d, want nothing installed and nothing refused", r, len(npmCalls(f))) + } +} + // 1489/AC2: a module naming lodash with a lock gets npm ci --omit=dev --ignore-scripts (fake runner), its install put // at its node_modules without the SDK and without any copy of it; without a lock the step fails naming the directory. func TestAModuleNamingLodashWithALockIsInstalledWithoutTheSdkAndWithoutALockFails(t *testing.T) {