Skip to content

Commit c3af5a1

Browse files
authored
Expose the deployment identifier to the application. (#726)
This was a feature requested by one of our users so that they can distinct between multiple deployments of the same application.
1 parent 2eb6066 commit c3af5a1

File tree

12 files changed

+294
-29
lines changed

12 files changed

+294
-29
lines changed

.github/workflows/go.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,11 @@ jobs:
8181
uses: actions/cache@v3
8282
with:
8383
path: ~/go/bin/staticcheck
84-
key: staticcheck-v0.4.3
84+
key: staticcheck-v0.4.6
8585
if: ${{ matrix.command == 'lint' }}
8686

8787
- name: Install linter
88-
run: go install honnef.co/go/tools/cmd/[email protected].3
88+
run: go install honnef.co/go/tools/cmd/[email protected].6
8989
if: ${{ matrix.command == 'lint' }}
9090

9191
- name: Build the weaver binary

dev/build_and_test

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ function cmd_vet() {
5454

5555
function cmd_lint() {
5656
if ! exists staticcheck; then
57-
printf "staticcheck not found; install via\ngo install honnef.co/go/tools/cmd/[email protected].3\n" >&2
57+
printf "staticcheck not found; install via\ngo install honnef.co/go/tools/cmd/[email protected].6\n" >&2
5858
exit 1
5959
fi
6060

fill.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
func init() {
2828
// See internal/weaver/types.go.
2929
weaver.SetLogger = setLogger
30+
weaver.SetWeaverInfo = setWeaverInfo
3031
weaver.HasRefs = hasRefs
3132
weaver.FillRefs = fillRefs
3233
weaver.HasListeners = hasListeners
@@ -39,12 +40,22 @@ func init() {
3940
func setLogger(v any, logger *slog.Logger) error {
4041
x, ok := v.(interface{ setLogger(*slog.Logger) })
4142
if !ok {
42-
return fmt.Errorf("FillLogger: %T does not implement weaver.Implements", v)
43+
return fmt.Errorf("setLogger: %T does not implement weaver.Implements", v)
4344
}
4445
x.setLogger(logger)
4546
return nil
4647
}
4748

49+
// See internal/weaver/types.go.
50+
func setWeaverInfo(impl any, info *weaver.WeaverInfo) error {
51+
x, ok := impl.(interface{ setWeaverInfo(*weaver.WeaverInfo) })
52+
if !ok {
53+
return fmt.Errorf("setWeaverInfo: %T does not implement weaver.Implements", impl)
54+
}
55+
x.setWeaverInfo(info)
56+
return nil
57+
}
58+
4859
// See internal/weaver/types.go.
4960
func hasRefs(impl any) bool {
5061
p := reflect.ValueOf(impl)

godeps.txt

+1
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ github.com/ServiceWeaver/weaver/internal/sim
390390
github.com/ServiceWeaver/weaver/runtime/codegen
391391
github.com/ServiceWeaver/weaver/runtime/logging
392392
github.com/ServiceWeaver/weaver/runtime/protos
393+
github.com/google/uuid
393394
go.opentelemetry.io/otel/codes
394395
go.opentelemetry.io/otel/trace
395396
golang.org/x/exp/maps

internal/sim/executor.go

+21
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/ServiceWeaver/weaver/runtime"
3131
"github.com/ServiceWeaver/weaver/runtime/codegen"
3232
"github.com/ServiceWeaver/weaver/runtime/protos"
33+
"github.com/google/uuid"
3334
"golang.org/x/sync/errgroup"
3435
)
3536

@@ -286,6 +287,15 @@ func (e *executor) reset(workload Workload, fakes map[reflect.Type]any, ops []*o
286287
e.nextTraceID = 1
287288
e.nextSpanID = 1
288289

290+
// Pick a deterministic deployment ID.
291+
depID, err := newUUID(e.rand)
292+
if err != nil {
293+
return err
294+
}
295+
weaverInfo := &weaver.WeaverInfo{
296+
DeploymentID: depID.String(),
297+
}
298+
289299
// Fill ref fields inside the workload struct.
290300
if err := weaver.FillRefs(workload, func(t reflect.Type) (any, error) {
291301
return e.getIntf(t, "op", 0)
@@ -326,6 +336,11 @@ func (e *executor) reset(workload Workload, fakes map[reflect.Type]any, ops []*o
326336
return err
327337
}
328338

339+
// Set application runtime information.
340+
if err := weaver.SetWeaverInfo(obj, weaverInfo); err != nil {
341+
return err
342+
}
343+
329344
// Fill ref fields.
330345
if e.info.hasRefs[reg.Iface] {
331346
if err := weaver.FillRefs(obj, func(t reflect.Type) (any, error) {
@@ -741,3 +756,9 @@ func returnError(component reflect.Type, method string, err error) []reflect.Val
741756
returns[n-1] = reflect.ValueOf(err)
742757
return returns
743758
}
759+
760+
func newUUID(r *rand.Rand) (uuid.UUID, error) {
761+
var bytes [16]byte
762+
r.Read(bytes[:])
763+
return uuid.FromBytes(bytes[:])
764+
}

internal/testdeployer/components.go

+12
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ type c interface {
4040
C(context.Context, int) (int, error)
4141
}
4242

43+
type d interface {
44+
D(context.Context) (string, error)
45+
}
46+
4347
type aimpl struct {
4448
weaver.Implements[a]
4549
lis weaver.Listener //lint:ignore U1000 used in remoteweavelet_test.go
@@ -55,6 +59,10 @@ type cimpl struct {
5559
weaver.Implements[c]
5660
}
5761

62+
type dimpl struct {
63+
weaver.Implements[d]
64+
}
65+
5866
func (a *aimpl) A(ctx context.Context, x int) (int, error) {
5967
a.Logger(ctx).Debug("A")
6068
return a.b.Get().B(ctx, x)
@@ -72,3 +80,7 @@ func (c *cimpl) C(ctx context.Context, x int) (int, error) {
7280
c_calls.Inc()
7381
return x, nil
7482
}
83+
84+
func (d *dimpl) D(ctx context.Context) (string, error) {
85+
return d.Weaver().DeploymentID, nil
86+
}

internal/testdeployer/remoteweavelet_test.go

+31-14
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ var (
4848
componenta = "github.com/ServiceWeaver/weaver/internal/testdeployer/a"
4949
componentb = "github.com/ServiceWeaver/weaver/internal/testdeployer/b"
5050
componentc = "github.com/ServiceWeaver/weaver/internal/testdeployer/c"
51+
componentd = "github.com/ServiceWeaver/weaver/internal/testdeployer/d"
5152
colocated = map[string][]string{"1": {componenta, componentb, componentc}}
5253
)
5354

@@ -125,9 +126,10 @@ func spawn(ctx context.Context, info *protos.WeaveletArgs, handler envelope.Enve
125126
// deployer is a simple testing deployer that spawns all weavelets in the
126127
// current process.
127128
type deployer struct {
128-
t *testing.T // underlying unit test
129-
ctx context.Context // context used to spawn weavelets
130-
cancel context.CancelFunc // shuts down the deployer and all weavelets
129+
t *testing.T // underlying unit test
130+
ctx context.Context // context used to spawn weavelets
131+
cancel context.CancelFunc // shuts down the deployer and all weavelets
132+
info *protos.WeaveletArgs
131133
logger *logging.TestLogger // logger
132134
threads *errgroup.Group // background threads
133135
placement map[string][]string // weavelet -> components
@@ -194,6 +196,7 @@ func deployWithInfo(t *testing.T, ctx context.Context, placement map[string][]st
194196
threads, ctx := errgroup.WithContext(ctx)
195197
d := &deployer{
196198
t: t,
199+
info: protomsg.Clone(info),
197200
ctx: ctx,
198201
cancel: cancel,
199202
logger: logging.NewTestLogger(t, testing.Verbose()),
@@ -209,7 +212,7 @@ func deployWithInfo(t *testing.T, ctx context.Context, placement map[string][]st
209212
// Spawn the weavelets.
210213
tmpDir := t.TempDir()
211214
for name := range placement {
212-
info := protomsg.Clone(info)
215+
info := d.info
213216
info.Id = uuid.New().String()
214217
weavelet, err := spawn(ctx, info, d, logger, tmpDir)
215218
if err != nil {
@@ -324,20 +327,34 @@ func (d *deployer) VerifyServerCertificate(context.Context, *protos.VerifyServer
324327
}
325328

326329
// testComponents tests that the components spawned by d are working properly.
327-
func testComponents(d *deployer) {
328-
d.t.Helper()
329-
const want = 42
330-
for _, name := range d.placedAt[componenta] {
331-
x, err := d.weavelets[name].wlet.GetIntf(reflection.Type[a]())
330+
func testComponents(dep *deployer) {
331+
dep.t.Helper()
332+
for _, name := range dep.placedAt[componenta] {
333+
x, err := dep.weavelets[name].wlet.GetIntf(reflection.Type[a]())
332334
if err != nil {
333-
d.t.Fatal(err)
335+
dep.t.Fatal(err)
334336
}
335-
got, err := x.(a).A(d.ctx, want)
337+
const want = 42
338+
got, err := x.(a).A(dep.ctx, want)
336339
if err != nil {
337-
d.t.Fatal(err)
340+
dep.t.Fatal(err)
341+
}
342+
if got != want {
343+
dep.t.Fatalf("A(%d): got %d, want %d", want, got, want)
344+
}
345+
}
346+
for _, name := range dep.placedAt[componentd] {
347+
x, err := dep.weavelets[name].wlet.GetIntf(reflection.Type[d]())
348+
if err != nil {
349+
dep.t.Fatal(err)
350+
}
351+
got, err := x.(d).D(dep.ctx)
352+
if err != nil {
353+
dep.t.Fatal(err)
338354
}
355+
want := dep.info.DeploymentId
339356
if got != want {
340-
d.t.Fatalf("A(%d): got %d, want %d", want, got, want)
357+
dep.t.Fatalf("D(): got %s, want %s", got, want)
341358
}
342359
}
343360
}
@@ -799,7 +816,7 @@ func TestMetrics(t *testing.T) {
799816
t.Fatal(err)
800817
}
801818
if got != want {
802-
t.Fatalf("A(%d): got %d, want %d", want, got, want)
819+
t.Fatalf("C(%d): got %d, want %d", want, got, want)
803820
}
804821
}
805822

0 commit comments

Comments
 (0)