diff --git a/cmd/ateapi/internal/controlapi/crash.go b/cmd/ateapi/internal/controlapi/crash.go index 485235006..f09b3e865 100644 --- a/cmd/ateapi/internal/controlapi/crash.go +++ b/cmd/ateapi/internal/controlapi/crash.go @@ -28,25 +28,25 @@ import ( // maybeCrashActor inspects err returned by an atelet RPC, it crashes // the actor if the err carries the actorCrashed=true metadata directive. -func maybeCrashActor(ctx context.Context, st store.Interface, atespace, actorID string, err error, wrapMsg string) error { +func maybeCrashActor(ctx context.Context, st store.Interface, atespace, actorName string, err error, wrapMsg string) error { if err == nil { return nil } if ateerrors.ActorCrashRequested(err) { slog.ErrorContext(ctx, "Setting Actor to crashed due to error", slog.Any("error", err)) - if cerr := crashActor(ctx, st, atespace, actorID); cerr != nil { + if cerr := crashActor(ctx, st, atespace, actorName); cerr != nil { slog.ErrorContext(ctx, "Failed to crash actor", slog.Any("cerr", cerr)) return cerr } - return status.Errorf(codes.DataLoss, "actor %s crashed", actorID) + return status.Errorf(codes.DataLoss, "actor %s crashed", actorName) } return fmt.Errorf("%s: %w", wrapMsg, err) } // crashActor moves the actor to CRASHED state. -func crashActor(ctx context.Context, st store.Interface, atespace, actorID string) error { - actor, err := st.GetActor(ctx, atespace, actorID) +func crashActor(ctx context.Context, st store.Interface, atespace, actorName string) error { + actor, err := st.GetActor(ctx, atespace, actorName) if err != nil { return fmt.Errorf("while loading actor to crash: %w", err) } @@ -59,7 +59,7 @@ func crashActor(ctx context.Context, st store.Interface, atespace, actorID strin // we must preserve the Actor's assigned node VM in order // to support `ate actor dump` command. // (https://github.com/agent-substrate/substrate/issues/119) - if err := st.UpdateActor(ctx, actor, actor.GetVersion()); err != nil { + if _, err := st.UpdateActor(ctx, actor, actor.GetMetadata().GetVersion()); err != nil { return fmt.Errorf("while marking actor crashed: %w", err) } diff --git a/cmd/ateapi/internal/controlapi/crash_test.go b/cmd/ateapi/internal/controlapi/crash_test.go index ece0acebf..89dbe4784 100644 --- a/cmd/ateapi/internal/controlapi/crash_test.go +++ b/cmd/ateapi/internal/controlapi/crash_test.go @@ -30,11 +30,10 @@ import ( // seedActor stores a running actor with all worker-binding fields populated, so // tests can assert they are cleared when the actor crashes. -func seedActor(t *testing.T, ctx context.Context, st store.Interface, atespace, id string) { +func seedActor(t *testing.T, ctx context.Context, st store.Interface, atespace, actorName string) { t.Helper() - if err := st.CreateActor(ctx, &ateapipb.Actor{ - ActorId: id, - Atespace: atespace, + if _, err := st.CreateActor(ctx, &ateapipb.Actor{ + Metadata: &ateapipb.ResourceMetadata{Name: actorName, Atespace: atespace}, Status: ateapipb.Actor_STATUS_RUNNING, AteomPodNamespace: "ns", AteomPodName: "pod", @@ -47,11 +46,11 @@ func seedActor(t *testing.T, ctx context.Context, st store.Interface, atespace, } // assertCrashed reloads the actor and verifies it is CRASHED. -func assertCrashed(t *testing.T, ctx context.Context, st store.Interface, atespace, id string) { +func assertCrashed(t *testing.T, ctx context.Context, st store.Interface, atespace, actorName string) { t.Helper() - got, err := st.GetActor(ctx, atespace, id) + got, err := st.GetActor(ctx, atespace, actorName) if err != nil { - t.Fatalf("GetActor(%q, %q) = %v, want nil", atespace, id, err) + t.Fatalf("GetActor(%q, %q) = %v, want nil", atespace, actorName, err) } if got.GetStatus() != ateapipb.Actor_STATUS_CRASHED { t.Errorf("status = %v, want %v", got.GetStatus(), ateapipb.Actor_STATUS_CRASHED) @@ -60,8 +59,8 @@ func assertCrashed(t *testing.T, ctx context.Context, st store.Interface, atespa func TestCrashActor(t *testing.T) { const ( - atespace = "team-a" - actorID = "actor-1" + atespace = "team-a" + actorName = "actor-1" ) tests := []struct { @@ -77,7 +76,7 @@ func TestCrashActor(t *testing.T) { if err != nil { t.Fatalf("crashActor() = %v, want nil", err) } - assertCrashed(t, ctx, st, atespace, actorID) + assertCrashed(t, ctx, st, atespace, actorName) }, }, { @@ -104,10 +103,10 @@ func TestCrashActor(t *testing.T) { defer cleanup() if tt.seed { - seedActor(t, ctx, st, atespace, actorID) + seedActor(t, ctx, st, atespace, actorName) } - err := crashActor(ctx, st, atespace, actorID) + err := crashActor(ctx, st, atespace, actorName) tt.check(t, ctx, st, err) }) } @@ -115,9 +114,9 @@ func TestCrashActor(t *testing.T) { func TestMaybeCrashActor(t *testing.T) { const ( - atespace = "team-a" - actorID = "actor-1" - wrapMsg = "calling atelet" + atespace = "team-a" + actorName = "actor-1" + wrapMsg = "calling atelet" ) crashErr := ateerrors.NewGRPCError(context.Background(), codes.NotFound, ateerrors.ReasonTerminalFileSystemError, ateerrors.ActorCrashedMetadata(), errors.New("boom")) @@ -154,7 +153,7 @@ func TestMaybeCrashActor(t *testing.T) { if got := status.Code(err); got != codes.DataLoss { t.Errorf("status code = %v, want %v", got, codes.DataLoss) } - assertCrashed(t, ctx, st, atespace, actorID) + assertCrashed(t, ctx, st, atespace, actorName) }, }, { @@ -188,7 +187,7 @@ func TestMaybeCrashActor(t *testing.T) { t.Errorf("maybeCrashActor() error = %q, want prefix %q", err, wrapMsg) } // The actor must not have been crashed. - got, gerr := st.GetActor(ctx, atespace, actorID) + got, gerr := st.GetActor(ctx, atespace, actorName) if gerr != nil { t.Fatalf("GetActor() = %v, want nil", gerr) } @@ -212,7 +211,7 @@ func TestMaybeCrashActor(t *testing.T) { t.Errorf("maybeCrashActor() error = %q, want prefix %q", err, wrapMsg) } // The actor must not have been crashed. - got, gerr := st.GetActor(ctx, atespace, actorID) + got, gerr := st.GetActor(ctx, atespace, actorName) if gerr != nil { t.Fatalf("GetActor() = %v, want nil", gerr) } @@ -230,10 +229,10 @@ func TestMaybeCrashActor(t *testing.T) { defer cleanup() if tt.seed { - seedActor(t, ctx, st, atespace, actorID) + seedActor(t, ctx, st, atespace, actorName) } - err := maybeCrashActor(ctx, st, atespace, actorID, tt.err, wrapMsg) + err := maybeCrashActor(ctx, st, atespace, actorName, tt.err, wrapMsg) tt.check(t, ctx, st, err) }) } diff --git a/cmd/ateapi/internal/controlapi/create_actor.go b/cmd/ateapi/internal/controlapi/create_actor.go index 8ccf885cf..0700da688 100644 --- a/cmd/ateapi/internal/controlapi/create_actor.go +++ b/cmd/ateapi/internal/controlapi/create_actor.go @@ -50,31 +50,27 @@ func (s *Service) CreateActor(ctx context.Context, req *ateapipb.CreateActorRequ return nil, status.Errorf(codes.FailedPrecondition, "Atespace %s not found", req.GetActorRef().GetAtespace()) } - id := req.GetActorRef().GetName() + name := req.GetActorRef().GetName() actor := &ateapipb.Actor{ - ActorId: id, - Version: 1, + Metadata: &ateapipb.ResourceMetadata{ + Atespace: req.GetActorRef().GetAtespace(), + Name: name, + }, Status: ateapipb.Actor_STATUS_SUSPENDED, ActorTemplateNamespace: req.GetActorTemplateNamespace(), ActorTemplateName: req.GetActorTemplateName(), WorkerSelector: req.GetWorkerSelector(), - Atespace: req.GetActorRef().GetAtespace(), } - err = s.persistence.CreateActor(ctx, actor) + stored, err := s.persistence.CreateActor(ctx, actor) if err != nil { if errors.Is(err, store.ErrAlreadyExists) { - return nil, status.Errorf(codes.AlreadyExists, "Actor %s already exists", id) + return nil, status.Errorf(codes.AlreadyExists, "Actor %s already exists", name) } return nil, fmt.Errorf("while recording actor: %w", err) } - storedActor, err := s.persistence.GetActor(ctx, req.GetActorRef().GetAtespace(), id) - if err != nil { - return nil, fmt.Errorf("while fetching recorded actor from DB: %w", err) - } - return &ateapipb.CreateActorResponse{ - Actor: storedActor, + Actor: stored, }, nil } diff --git a/cmd/ateapi/internal/controlapi/create_atespace.go b/cmd/ateapi/internal/controlapi/create_atespace.go index 6522c6084..303159e36 100644 --- a/cmd/ateapi/internal/controlapi/create_atespace.go +++ b/cmd/ateapi/internal/controlapi/create_atespace.go @@ -31,15 +31,18 @@ func (s *Service) CreateAtespace(ctx context.Context, req *ateapipb.CreateAtespa return nil, err } - atespace := &ateapipb.Atespace{Name: req.GetName()} - if err := s.persistence.CreateAtespace(ctx, atespace); err != nil { + atespace := &ateapipb.Atespace{ + Metadata: &ateapipb.ResourceMetadata{Name: req.GetName()}, + } + stored, err := s.persistence.CreateAtespace(ctx, atespace) + if err != nil { if errors.Is(err, store.ErrAlreadyExists) { return nil, status.Errorf(codes.AlreadyExists, "Atespace %s already exists", req.GetName()) } return nil, fmt.Errorf("while recording atespace: %w", err) } - return &ateapipb.CreateAtespaceResponse{Atespace: atespace}, nil + return &ateapipb.CreateAtespaceResponse{Atespace: stored}, nil } func validateCreateAtespaceRequest(req *ateapipb.CreateAtespaceRequest) error { diff --git a/cmd/ateapi/internal/controlapi/functional_test.go b/cmd/ateapi/internal/controlapi/functional_test.go index 5c238f6cf..7e3022ab8 100644 --- a/cmd/ateapi/internal/controlapi/functional_test.go +++ b/cmd/ateapi/internal/controlapi/functional_test.go @@ -64,6 +64,12 @@ var ( const testAtespace = "test-atespace" +var ( + ignoreUID = protocmp.IgnoreFields(&ateapipb.ResourceMetadata{}, "uid") + ignoreVersion = protocmp.IgnoreFields(&ateapipb.ResourceMetadata{}, "version") + ignoreTimestamps = protocmp.IgnoreFields(&ateapipb.ResourceMetadata{}, "create_time", "update_time") +) + func TestMain(m *testing.M) { binaryAssetsDirectory, err := envtestbins.BinaryAssetsDir() if err != nil { @@ -703,17 +709,28 @@ func TestCreateActor_Success(t *testing.T) { want := &ateapipb.CreateActorResponse{ Actor: &ateapipb.Actor{ - ActorId: "id1", - Version: 1, + Metadata: &ateapipb.ResourceMetadata{Name: "id1", Atespace: testAtespace, Version: 1}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", Status: ateapipb.Actor_STATUS_SUSPENDED, WorkerSelector: &ateapipb.Selector{MatchLabels: map[string]string{"tier": "free"}}, - Atespace: testAtespace, }, } - if diff := cmp.Diff(want, createResp, protocmp.Transform()); diff != "" { + // The diff below ignores the server-assigned uid/timestamps (non-deterministic), + // so assert they are populated separately. + md := createResp.GetActor().GetMetadata() + if md.GetUid() == "" { + t.Errorf("CreateActor response missing server-assigned uid") + } + if md.GetCreateTime() == nil { + t.Errorf("CreateActor response missing create_time") + } + if md.GetUpdateTime() == nil { + t.Errorf("CreateActor response missing update_time") + } + + if diff := cmp.Diff(want, createResp, protocmp.Transform(), ignoreUID, ignoreTimestamps); diff != "" { t.Errorf("CreateActor response mismatch (-want +got):\n%s", diff) } } @@ -765,8 +782,10 @@ func TestGetActor_Found(t *testing.T) { createTemplate(t, tc, ns) + name := "id1" + createResp, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: "id1"}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", }) @@ -774,10 +793,8 @@ func TestGetActor_Found(t *testing.T) { t.Fatalf("CreateActor failed: %v", err) } - id := createResp.GetActor().GetActorId() - getResp, err := tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err != nil { t.Fatalf("GetActor failed: %v", err) @@ -854,7 +871,7 @@ func TestListActors(t *testing.T) { opts := []cmp.Option{ protocmp.Transform(), cmpopts.SortSlices(func(a, b *ateapipb.Actor) bool { - return a.ActorId < b.ActorId + return a.GetMetadata().GetName() < b.GetMetadata().GetName() }), } @@ -875,14 +892,14 @@ func TestListActors_ByAtespace(t *testing.T) { createAtespace(t, tc, "team-a") createAtespace(t, tc, "team-b") - create := func(atespace, id string) *ateapipb.Actor { + create := func(atespace, name string) *ateapipb.Actor { resp, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: atespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: atespace, Name: name}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", }) if err != nil { - t.Fatalf("CreateActor(%s, atespace=%q) failed: %v", id, atespace, err) + t.Fatalf("CreateActor(%s, atespace=%q) failed: %v", name, atespace, err) } return resp.GetActor() } @@ -892,7 +909,7 @@ func TestListActors_ByAtespace(t *testing.T) { sortByID := []cmp.Option{ protocmp.Transform(), - cmpopts.SortSlices(func(a, b *ateapipb.Actor) bool { return a.ActorId < b.ActorId }), + cmpopts.SortSlices(func(a, b *ateapipb.Actor) bool { return a.GetMetadata().GetName() < b.GetMetadata().GetName() }), } // List scoped to team-a returns only its actors. @@ -932,13 +949,13 @@ func TestListActors_AllAtespaces(t *testing.T) { createAtespace(t, tc, "team-a") createAtespace(t, tc, "team-b") - create := func(atespace, id string) { + create := func(atespace, name string) { if _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: atespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: atespace, Name: name}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", }); err != nil { - t.Fatalf("CreateActor(%s, atespace=%q) failed: %v", id, atespace, err) + t.Fatalf("CreateActor(%s, atespace=%q) failed: %v", name, atespace, err) } } create("team-a", "id1") @@ -951,7 +968,7 @@ func TestListActors_AllAtespaces(t *testing.T) { } got := map[string]string{} for _, a := range resp.GetActors() { - got[a.GetActorId()] = a.GetAtespace() + got[a.GetMetadata().GetName()] = a.GetMetadata().GetAtespace() } if got["id1"] != "team-a" { t.Errorf("ListActors(all): got[id1]=%q, want team-a", got["id1"]) @@ -972,7 +989,7 @@ func TestListActors_Pagination(t *testing.T) { var want []*ateapipb.Actor for i := 0; i < 5; i++ { resp, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: fmt.Sprintf("id%d", i)}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: fmt.Sprintf("name%d", i)}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", }) @@ -1009,7 +1026,7 @@ func TestListActors_Pagination(t *testing.T) { opts := []cmp.Option{ protocmp.Transform(), cmpopts.SortSlices(func(a, b *ateapipb.Actor) bool { - return a.ActorId < b.ActorId + return a.GetMetadata().GetName() < b.GetMetadata().GetName() }), } @@ -1106,18 +1123,18 @@ func TestResumeActor(t *testing.T) { createWorkerPod(t, tc, ns, "worker-1", "node1", "pool1") + name := "id1" _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: "id1"}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", }) if err != nil { t.Fatalf("CreateActor failed: %v", err) } - id := "id1" _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err != nil { t.Fatalf("ResumeActor failed: %v", err) @@ -1128,15 +1145,14 @@ func TestResumeActor(t *testing.T) { } getResp, err := tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err != nil { t.Fatalf("GetActor failed: %v", err) } want := &ateapipb.GetActorResponse{ Actor: &ateapipb.Actor{ - ActorId: id, - Atespace: testAtespace, + Metadata: &ateapipb.ResourceMetadata{Name: name, Atespace: testAtespace}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", Status: ateapipb.Actor_STATUS_RUNNING, @@ -1146,7 +1162,7 @@ func TestResumeActor(t *testing.T) { WorkerPoolName: "pool1", }, } - if diff := cmp.Diff(want, getResp, protocmp.Transform(), protocmp.IgnoreFields(&ateapipb.Actor{}, "version"), protocmp.IgnoreFields(&ateapipb.Actor{}, "ateom_pod_uid")); diff != "" { + if diff := cmp.Diff(want, getResp, protocmp.Transform(), ignoreUID, ignoreVersion, ignoreTimestamps, protocmp.IgnoreFields(&ateapipb.Actor{}, "ateom_pod_uid")); diff != "" { t.Errorf("GetActor response mismatch (-want +got):\n%s", diff) } @@ -1176,7 +1192,7 @@ func TestResumeActor(t *testing.T) { Name: "tmpl1", }, Actor: &ateapipb.ActorRef{ - Name: id, + Name: name, Atespace: testAtespace, }, }, @@ -1296,10 +1312,10 @@ func TestResumeActor_NoWorkers(t *testing.T) { t.Fatalf("CreateActor failed: %v", err) } - id := createResp.GetActor().GetActorId() + name := createResp.GetActor().GetMetadata().GetName() _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) assertGrpcError(t, err, codes.FailedPrecondition, "no free workers available") } @@ -1417,28 +1433,28 @@ func TestResumeActor_Reentrancy(t *testing.T) { // Create Worker Pod createWorkerPod(t, tc, ns, "worker-1", "node1", "pool1") + name := "id1" _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: "id1"}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", }) if err != nil { t.Fatalf("CreateActor failed: %v", err) } - id := "id1" // STEP 1: Make Atelet FAIL on Restore! tc.fakeAtelet.FailRestore = fmt.Errorf("mock atelet failure") _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err == nil { t.Fatalf("expected ResumeActor to fail due to atelet error") } // Verify actor state is RESUMING in Redis! - actor, err := tc.persistence.GetActor(context.Background(), testAtespace, id) + actor, err := tc.persistence.GetActor(context.Background(), testAtespace, name) if err != nil { t.Fatalf("failed to get actor from store: %v", err) } @@ -1451,7 +1467,7 @@ func TestResumeActor_Reentrancy(t *testing.T) { tc.fakeAtelet.RestoreCalled = false // reset for verification _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err != nil { t.Fatalf("ResumeActor failed on retry: %v", err) @@ -1462,7 +1478,7 @@ func TestResumeActor_Reentrancy(t *testing.T) { } // Verify actor state is RUNNING! - actor, err = tc.persistence.GetActor(context.Background(), testAtespace, id) + actor, err = tc.persistence.GetActor(context.Background(), testAtespace, name) if err != nil { t.Fatalf("failed to get actor from store: %v", err) } @@ -1489,20 +1505,20 @@ func TestSuspendActor(t *testing.T) { createTemplate(t, tc, ns) createWorkerPod(t, tc, ns, "worker-1", "node1", "pool1") + name := "id1" _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: "id1"}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", }) if err != nil { t.Fatalf("CreateActor failed: %v", err) } - id := "id1" // Resume first to make it running _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err != nil { t.Fatalf("ResumeActor failed: %v", err) @@ -1510,7 +1526,7 @@ func TestSuspendActor(t *testing.T) { // Suspend _, err = tc.client.SuspendActor(context.Background(), &ateapipb.SuspendActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err != nil { t.Fatalf("SuspendActor failed: %v", err) @@ -1521,22 +1537,21 @@ func TestSuspendActor(t *testing.T) { } getResp, err := tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err != nil { t.Fatalf("GetActor failed: %v", err) } want := &ateapipb.GetActorResponse{ Actor: &ateapipb.Actor{ - ActorId: id, - Atespace: testAtespace, + Metadata: &ateapipb.ResourceMetadata{Name: name, Atespace: testAtespace}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", Status: ateapipb.Actor_STATUS_SUSPENDED, LatestSnapshotInfo: &ateapipb.SnapshotInfo{ Data: &ateapipb.SnapshotInfo_External{ External: &ateapipb.ExternalSnapshotInfo{ - SnapshotUriPrefix: fmt.Sprintf("gs://fake-fake-fake/%s/", id), + SnapshotUriPrefix: fmt.Sprintf("gs://fake-fake-fake/%s/", name), }, }, }, @@ -1545,7 +1560,9 @@ func TestSuspendActor(t *testing.T) { if diff := cmp.Diff(want, getResp, protocmp.Transform(), - protocmp.IgnoreFields(&ateapipb.Actor{}, "version"), + ignoreUID, + ignoreVersion, + ignoreTimestamps, protocmp.IgnoreFields(&ateapipb.Actor{}, "ateom_pod_uid"), protocmp.FilterField(&ateapipb.ExternalSnapshotInfo{}, "snapshot_uri_prefix", cmp.Comparer(func(x, y string) bool { return strings.HasPrefix(y, x) @@ -1574,19 +1591,19 @@ func TestPauseActor(t *testing.T) { createWorkerPod(t, tc, ns, "worker-1", "node1", "pool1") + name := "id1" _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: "id1"}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", }) if err != nil { t.Fatalf("CreateActor failed: %v", err) } - id := "id1" // Resume first to make it running _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err != nil { t.Fatalf("ResumeActor failed: %v", err) @@ -1594,7 +1611,7 @@ func TestPauseActor(t *testing.T) { // Pause _, err = tc.client.PauseActor(context.Background(), &ateapipb.PauseActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err != nil { t.Fatalf("PauseActor failed: %v", err) @@ -1605,22 +1622,21 @@ func TestPauseActor(t *testing.T) { } getResp, err := tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err != nil { t.Fatalf("GetActor failed: %v", err) } want := &ateapipb.GetActorResponse{ Actor: &ateapipb.Actor{ - ActorId: id, - Atespace: testAtespace, + Metadata: &ateapipb.ResourceMetadata{Name: name, Atespace: testAtespace}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", Status: ateapipb.Actor_STATUS_PAUSED, LatestSnapshotInfo: &ateapipb.SnapshotInfo{ Data: &ateapipb.SnapshotInfo_Local{ Local: &ateapipb.LocalSnapshotInfo{ - SnapshotPrefix: "id1", + SnapshotPrefix: name, NodeVmsWithLocalSnapshots: []string{"node1"}, }, }, @@ -1630,7 +1646,9 @@ func TestPauseActor(t *testing.T) { if diff := cmp.Diff(want, getResp, protocmp.Transform(), - protocmp.IgnoreFields(&ateapipb.Actor{}, "version"), + ignoreUID, + ignoreVersion, + ignoreTimestamps, protocmp.IgnoreFields(&ateapipb.Actor{}, "ateom_pod_uid"), protocmp.FilterField(&ateapipb.LocalSnapshotInfo{}, "snapshot_prefix", cmp.Comparer(func(x, y string) bool { return strings.HasPrefix(y, x) @@ -1672,9 +1690,7 @@ func TestUpdateActor_Success(t *testing.T) { } wantActor := &ateapipb.Actor{ - ActorId: "id1", - Version: 2, - Atespace: testAtespace, + Metadata: &ateapipb.ResourceMetadata{Name: "id1", Atespace: testAtespace, Version: 2}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", Status: ateapipb.Actor_STATUS_SUSPENDED, @@ -1683,7 +1699,7 @@ func TestUpdateActor_Success(t *testing.T) { }, } wantUpdateResp := &ateapipb.UpdateActorResponse{Actor: wantActor} - if diff := cmp.Diff(wantUpdateResp, updateResp, protocmp.Transform()); diff != "" { + if diff := cmp.Diff(wantUpdateResp, updateResp, protocmp.Transform(), ignoreUID, ignoreTimestamps); diff != "" { t.Errorf("UpdateActor response mismatch (-want +got):\n%s", diff) } @@ -1692,7 +1708,7 @@ func TestUpdateActor_Success(t *testing.T) { t.Fatalf("GetActor failed: %v", err) } wantGetResp := &ateapipb.GetActorResponse{Actor: wantActor} - if diff := cmp.Diff(wantGetResp, getResp, protocmp.Transform()); diff != "" { + if diff := cmp.Diff(wantGetResp, getResp, protocmp.Transform(), ignoreUID, ignoreTimestamps); diff != "" { t.Errorf("GetActor response mismatch after UpdateActor (-want +got):\n%s", diff) } } @@ -1733,9 +1749,9 @@ func TestResumeActor_ReleasesStaleWorkerWhenPoolBecomesIneligible(t *testing.T) createWorkerPod(t, tc, ns, "worker-a", "node1", "pool-a") createWorkerPod(t, tc, ns, "worker-b", "node1", "pool-b") - id := "id1" + name := "id1" _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", WorkerSelector: &ateapipb.Selector{MatchLabels: map[string]string{"tier": "a"}}, @@ -1745,24 +1761,24 @@ func TestResumeActor_ReleasesStaleWorkerWhenPoolBecomesIneligible(t *testing.T) } tc.fakeAtelet.FailRun = fmt.Errorf("mock atelet failure") - _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}}) + _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}}) if err == nil { t.Fatalf("expected first ResumeActor (onto worker-a) to fail") } tc.fakeAtelet.FailRun = nil if _, err := tc.client.UpdateActor(context.Background(), &ateapipb.UpdateActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, WorkerSelector: &ateapipb.Selector{MatchLabels: map[string]string{"tier": "b"}}, }); err != nil { t.Fatalf("UpdateActor failed: %v", err) } - if _, err := tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}}); err != nil { + if _, err := tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}}); err != nil { t.Fatalf("second ResumeActor failed: %v", err) } - getResp, err := tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}}) + getResp, err := tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}}) if err != nil { t.Fatalf("GetActor failed: %v", err) } @@ -1792,13 +1808,13 @@ func TestResumeActor_ReleasesStaleWorkerWhenPoolBecomesIneligible(t *testing.T) } case "pool-b": if wass := w.Assignment; wass == nil { - t.Errorf("expected worker-b to be claimed by %q, got nil assignment", id) + t.Errorf("expected worker-b to be claimed by %q, got nil assignment", name) } else { if wact := wass.Actor; wact == nil { - t.Errorf("expected worker-b to be claimed by %q, got nil assignment.actor", id) + t.Errorf("expected worker-b to be claimed by %q, got nil assignment.actor", name) } else { - if got := wact.Name; got != id { - t.Errorf("expected worker-b to be claimed by %q, got actor_id=%q", id, got) + if got := wact.Name; got != name { + t.Errorf("expected worker-b to be claimed by %q, got actor_id=%q", name, got) } } } @@ -1833,9 +1849,9 @@ func TestUpdateActor_ReassignsPoolAcrossSuspendResume(t *testing.T) { createWorkerPod(t, tc, ns, "worker-a", "node1", "pool-a") createWorkerPod(t, tc, ns, "worker-b", "node1", "pool-b") - id := "id1" + name := "id1" _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", WorkerSelector: &ateapipb.Selector{ @@ -1846,11 +1862,11 @@ func TestUpdateActor_ReassignsPoolAcrossSuspendResume(t *testing.T) { t.Fatalf("CreateActor failed: %v", err) } - if _, err := tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}}); err != nil { + if _, err := tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}}); err != nil { t.Fatalf("first ResumeActor failed: %v", err) } - getResp, err := tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}}) + getResp, err := tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}}) if err != nil { t.Fatalf("GetActor failed: %v", err) } @@ -1862,7 +1878,7 @@ func TestUpdateActor_ReassignsPoolAcrossSuspendResume(t *testing.T) { } if _, err := tc.client.UpdateActor(context.Background(), &ateapipb.UpdateActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, WorkerSelector: &ateapipb.Selector{ MatchLabels: map[string]string{"tier": "b"}, }, @@ -1870,14 +1886,14 @@ func TestUpdateActor_ReassignsPoolAcrossSuspendResume(t *testing.T) { t.Fatalf("UpdateActor failed: %v", err) } - if _, err := tc.client.SuspendActor(context.Background(), &ateapipb.SuspendActorRequest{ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}}); err != nil { + if _, err := tc.client.SuspendActor(context.Background(), &ateapipb.SuspendActorRequest{ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}}); err != nil { t.Fatalf("SuspendActor failed: %v", err) } - if _, err := tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}}); err != nil { + if _, err := tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}}); err != nil { t.Fatalf("second ResumeActor failed: %v", err) } - getResp, err = tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}}) + getResp, err = tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}}) if err != nil { t.Fatalf("GetActor failed: %v", err) } @@ -2284,15 +2300,15 @@ func TestResumeActor_LockConflict(t *testing.T) { createWorkerPod(t, tc, ns, "worker-1", "node1", "pool1") + name := "id1" _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: "id1"}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", }) if err != nil { t.Fatalf("CreateActor failed: %v", err) } - id := "id1" // Set a delay on the fake Atelet to hold the lock tc.fakeAtelet.RestoreDelay = 1 * time.Second @@ -2301,7 +2317,7 @@ func TestResumeActor_LockConflict(t *testing.T) { errChan := make(chan error, 1) go func() { _, err := tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) errChan <- err }() @@ -2311,7 +2327,7 @@ func TestResumeActor_LockConflict(t *testing.T) { // Launch Request B (should fail due to lock conflict) _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) assertGrpcError(t, err, codes.Aborted, "another operation is in progress for this actor") @@ -2331,22 +2347,22 @@ func TestResumeActor_DanglingWorker(t *testing.T) { // 1. Create Worker Pod A createWorkerPod(t, tc, ns, "worker-a", "node1", "pool1") + name := "id1" _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: "id1"}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", }) if err != nil { t.Fatalf("CreateActor failed: %v", err) } - id := "id1" // 2. Configure fake Atelet to FAIL on Restore! tc.fakeAtelet.FailRestore = fmt.Errorf("mock atelet failure") // 3. Call ResumeActor -> Expect failure _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err == nil { t.Fatalf("expected ResumeActor to fail due to atelet error") @@ -2354,7 +2370,7 @@ func TestResumeActor_DanglingWorker(t *testing.T) { // Verify actor state is RESUMING with worker A assigned getResp, err := tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err != nil { t.Fatalf("GetActor failed: %v", err) @@ -2378,7 +2394,7 @@ func TestResumeActor_DanglingWorker(t *testing.T) { // 8. Call ResumeActor again -> Expect success and picking Worker B! _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err != nil { t.Fatalf("ResumeActor failed on retry: %v", err) @@ -2389,7 +2405,7 @@ func TestResumeActor_DanglingWorker(t *testing.T) { } // Verify actor state is RUNNING with worker B assigned - actor, err = tc.persistence.GetActor(context.Background(), testAtespace, id) + actor, err = tc.persistence.GetActor(context.Background(), testAtespace, name) if err != nil { t.Fatalf("failed to get actor from store: %v", err) } @@ -2411,19 +2427,19 @@ func TestSuspendActor_DanglingWorker(t *testing.T) { // 1. Create Worker Pod createWorkerPod(t, tc, ns, "worker-1", "node1", "pool1") + name := "id1" _, err := tc.client.CreateActor(context.Background(), &ateapipb.CreateActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: "id1"}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl1", }) if err != nil { t.Fatalf("CreateActor failed: %v", err) } - id := "id1" // Resume first to make it running _, err = tc.client.ResumeActor(context.Background(), &ateapipb.ResumeActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err != nil { t.Fatalf("ResumeActor failed: %v", err) @@ -2435,11 +2451,11 @@ func TestSuspendActor_DanglingWorker(t *testing.T) { actors, _, _ := tc.persistence.ListActors(context.Background(), testAtespace, maxPageSize, "") t.Logf("Actors in Redis before Suspend: %d", len(actors)) for _, a := range actors { - t.Logf(" Actor: %s/%s/%s", a.GetActorTemplateNamespace(), a.GetActorTemplateName(), a.GetActorId()) + t.Logf(" Actor: %s/%s/%s", a.GetActorTemplateNamespace(), a.GetActorTemplateName(), a.GetMetadata().GetName()) } _, err = tc.client.SuspendActor(context.Background(), &ateapipb.SuspendActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err != nil { t.Fatalf("SuspendActor failed: %v", err) @@ -2447,7 +2463,7 @@ func TestSuspendActor_DanglingWorker(t *testing.T) { // 4. Verify it becomes SUSPENDED in Redis getResp, err := tc.client.GetActor(context.Background(), &ateapipb.GetActorRequest{ - ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: id}, + ActorRef: &ateapipb.ActorRef{Atespace: testAtespace, Name: name}, }) if err != nil { t.Fatalf("GetActor failed: %v", err) @@ -2594,8 +2610,8 @@ func TestCreateAtespace_Success(t *testing.T) { t.Fatalf("CreateAtespace failed: %v", err) } got := resp.GetAtespace() - if got.GetName() != "team-a" { - t.Errorf("Name = %q, want team-a", got.GetName()) + if got.GetMetadata().GetName() != "team-a" { + t.Errorf("Name = %q, want team-a", got.GetMetadata().GetName()) } // An actor can now be created into the new atespace. @@ -2681,7 +2697,7 @@ func TestListAtespaces(t *testing.T) { } got := map[string]bool{} for _, a := range resp.GetAtespaces() { - got[a.GetName()] = true + got[a.GetMetadata().GetName()] = true } // setupTest seeds testAtespace; team-a and team-b were created above. for _, n := range []string{testAtespace, "team-a", "team-b"} { diff --git a/cmd/ateapi/internal/controlapi/syncer.go b/cmd/ateapi/internal/controlapi/syncer.go index c1611740a..82854f826 100644 --- a/cmd/ateapi/internal/controlapi/syncer.go +++ b/cmd/ateapi/internal/controlapi/syncer.go @@ -229,7 +229,7 @@ func (s *WorkerPoolSyncer) releaseActorOnDeadWorker(ctx context.Context, namespa actor.AteomPodIp = "" actor.InProgressSnapshot = "" actor.WorkerPoolName = "" - if err := s.persistence.UpdateActor(ctx, actor, actor.GetVersion()); err != nil && !errors.Is(err, store.ErrPersistenceRetry) { + if _, err := s.persistence.UpdateActor(ctx, actor, actor.GetMetadata().GetVersion()); err != nil && !errors.Is(err, store.ErrPersistenceRetry) { return err } return nil diff --git a/cmd/ateapi/internal/controlapi/syncer_test.go b/cmd/ateapi/internal/controlapi/syncer_test.go index 15723e668..96e6e9f8b 100644 --- a/cmd/ateapi/internal/controlapi/syncer_test.go +++ b/cmd/ateapi/internal/controlapi/syncer_test.go @@ -235,9 +235,9 @@ func TestSyncer_DeleteBoundWorker_ClearsActor(t *testing.T) { }); err != nil { t.Fatalf("worker row not materialised: %v", err) } - actorID := "actor-orphan" - if err := persistence.CreateActor(ctx, &ateapipb.Actor{ - ActorId: actorID, Atespace: "team-orphan", ActorTemplateNamespace: ns, ActorTemplateName: "tmpl", + actorName := "actor-orphan" + if _, err := persistence.CreateActor(ctx, &ateapipb.Actor{ + Metadata: &ateapipb.ResourceMetadata{Name: actorName, Atespace: "team-orphan"}, ActorTemplateNamespace: ns, ActorTemplateName: "tmpl", Status: ateapipb.Actor_STATUS_RUNNING, AteomPodNamespace: ns, AteomPodName: pod, AteomPodIp: ip, InProgressSnapshot: "gs://snapshots/partial", @@ -258,7 +258,7 @@ func TestSyncer_DeleteBoundWorker_ClearsActor(t *testing.T) { Name: "tmpl", }, Actor: &ateapipb.ActorRef{ - Name: actorID, + Name: actorName, Atespace: "team-orphan", }, } @@ -271,7 +271,7 @@ func TestSyncer_DeleteBoundWorker_ClearsActor(t *testing.T) { } var got *ateapipb.Actor if err := wait.PollUntilContextTimeout(ctx, 50*time.Millisecond, 2*time.Second, true, func(c context.Context) (bool, error) { - a, gerr := persistence.GetActor(c, "team-orphan", actorID) + a, gerr := persistence.GetActor(c, "team-orphan", actorName) if gerr != nil { return false, gerr } diff --git a/cmd/ateapi/internal/controlapi/update_actor.go b/cmd/ateapi/internal/controlapi/update_actor.go index 3fe84259c..81d5678de 100644 --- a/cmd/ateapi/internal/controlapi/update_actor.go +++ b/cmd/ateapi/internal/controlapi/update_actor.go @@ -41,14 +41,15 @@ func (s *Service) UpdateActor(ctx context.Context, req *ateapipb.UpdateActorRequ } actor.WorkerSelector = req.GetWorkerSelector() - if err := s.persistence.UpdateActor(ctx, actor, actor.GetVersion()); err != nil { + updated, err := s.persistence.UpdateActor(ctx, actor, actor.GetMetadata().GetVersion()) + if err != nil { if errors.Is(err, store.ErrPersistenceRetry) { return nil, status.Error(codes.Aborted, "concurrent update conflict, please retry") } return nil, fmt.Errorf("while updating actor: %w", err) } - return &ateapipb.UpdateActorResponse{Actor: actor}, nil + return &ateapipb.UpdateActorResponse{Actor: updated}, nil } func validateUpdateActorRequest(req *ateapipb.UpdateActorRequest) error { diff --git a/cmd/ateapi/internal/controlapi/workflow.go b/cmd/ateapi/internal/controlapi/workflow.go index 8f8f4a227..5c193f992 100644 --- a/cmd/ateapi/internal/controlapi/workflow.go +++ b/cmd/ateapi/internal/controlapi/workflow.go @@ -148,17 +148,17 @@ func NewActorWorkflow( } // ResumeActor executes the workflow to resume a suspended actor. Idempotent. -func (w *ActorWorkflow) ResumeActor(ctx context.Context, atespace, id string, boot bool) (*ateapipb.Actor, error) { +func (w *ActorWorkflow) ResumeActor(ctx context.Context, atespace, name string, boot bool) (*ateapipb.Actor, error) { input := &ResumeInput{ - ActorID: id, - Atespace: atespace, - Boot: boot, + ActorName: name, + Atespace: atespace, + Boot: boot, } state := &ResumeState{} // Acquire lock and get the timeout context for the workflow // Lock TTL is 30 seconds, with 2 seconds padding for workflow timeout - ctx, releaseLock, err := w.acquireActorLock(ctx, id, 30*time.Second, 2*time.Second) + ctx, releaseLock, err := w.acquireActorLock(ctx, name, 30*time.Second, 2*time.Second) if err != nil { return nil, err } @@ -179,16 +179,16 @@ func (w *ActorWorkflow) ResumeActor(ctx context.Context, atespace, id string, bo } // SuspendActor executes the workflow to suspend a running actor. Idempotent. -func (w *ActorWorkflow) SuspendActor(ctx context.Context, atespace, id string) (*ateapipb.Actor, error) { +func (w *ActorWorkflow) SuspendActor(ctx context.Context, atespace, name string) (*ateapipb.Actor, error) { input := &SuspendInput{ - ActorID: id, - Atespace: atespace, + ActorName: name, + Atespace: atespace, } state := &SuspendState{} // Acquire lock and get the timeout context for the workflow // Lock TTL is 30 seconds, with 2 seconds padding for workflow timeout - ctx, releaseLock, err := w.acquireActorLock(ctx, id, 30*time.Second, 2*time.Second) + ctx, releaseLock, err := w.acquireActorLock(ctx, name, 30*time.Second, 2*time.Second) if err != nil { return nil, err } @@ -209,16 +209,16 @@ func (w *ActorWorkflow) SuspendActor(ctx context.Context, atespace, id string) ( } // PauseActor executes the workflow to pause a running actor. Idempotent. -func (w *ActorWorkflow) PauseActor(ctx context.Context, atespace, id string) (*ateapipb.Actor, error) { +func (w *ActorWorkflow) PauseActor(ctx context.Context, atespace, name string) (*ateapipb.Actor, error) { input := &PauseInput{ - ActorID: id, - Atespace: atespace, + ActorName: name, + Atespace: atespace, } state := &PauseState{} // Acquire lock and get the timeout context for the workflow // Lock TTL is 30 seconds, with 2 seconds padding for workflow timeout - ctx, releaseLock, err := w.acquireActorLock(ctx, id, 30*time.Second, 2*time.Second) + ctx, releaseLock, err := w.acquireActorLock(ctx, name, 30*time.Second, 2*time.Second) if err != nil { return nil, err } @@ -238,8 +238,8 @@ func (w *ActorWorkflow) PauseActor(ctx context.Context, atespace, id string) (*a return state.Actor, nil } -func (w *ActorWorkflow) acquireActorLock(ctx context.Context, id string, ttl time.Duration, padding time.Duration) (context.Context, func(), error) { - lockKey := "lock:actor:" + id +func (w *ActorWorkflow) acquireActorLock(ctx context.Context, name string, ttl time.Duration, padding time.Duration) (context.Context, func(), error) { + lockKey := "lock:actor:" + name lockValue := uuid.New().String() // Create a child context for the workflow that expires BEFORE the lock diff --git a/cmd/ateapi/internal/controlapi/workflow_pause.go b/cmd/ateapi/internal/controlapi/workflow_pause.go index 36b5cf5c9..14c28ca5f 100644 --- a/cmd/ateapi/internal/controlapi/workflow_pause.go +++ b/cmd/ateapi/internal/controlapi/workflow_pause.go @@ -32,8 +32,8 @@ import ( // PauseInput holds the immutable parameters requested by the client. type PauseInput struct { - ActorID string - Atespace string + ActorName string + Atespace string } // PauseState holds the mutable state loaded and modified during execution. @@ -53,7 +53,7 @@ func (s *LoadActorForPauseStep) IsComplete(ctx context.Context, input *PauseInpu return false, nil } func (s *LoadActorForPauseStep) Execute(ctx context.Context, input *PauseInput, state *PauseState) error { - actor, err := s.store.GetActor(ctx, input.Atespace, input.ActorID) + actor, err := s.store.GetActor(ctx, input.Atespace, input.ActorName) if err != nil { return err } @@ -85,8 +85,13 @@ func (s *MarkPausingStep) Execute(ctx context.Context, input *PauseInput, state } state.Actor.Status = ateapipb.Actor_STATUS_PAUSING - state.Actor.InProgressSnapshot = fmt.Sprintf("%s-%s-%s", state.Actor.GetActorId(), time.Now().Format(time.RFC3339), rand.Text()) - return s.store.UpdateActor(ctx, state.Actor, state.Actor.GetVersion()) + state.Actor.InProgressSnapshot = fmt.Sprintf("%s-%s-%s", state.Actor.GetMetadata().GetName(), time.Now().Format(time.RFC3339), rand.Text()) + updatedActor, err := s.store.UpdateActor(ctx, state.Actor, state.Actor.GetMetadata().GetVersion()) + if err != nil { + return err + } + state.Actor = updatedActor + return nil } func (s *MarkPausingStep) RetryBackoff() *wait.Backoff { return nil } @@ -103,7 +108,7 @@ func (s *CallAteletPauseStep) IsComplete(ctx context.Context, input *PauseInput, } func (s *CallAteletPauseStep) Execute(ctx context.Context, input *PauseInput, state *PauseState) error { if state.Actor.GetAteomPodNamespace() == "" || state.Actor.GetAteomPodName() == "" { - if err := crashActor(ctx, s.store, state.Actor.Atespace, state.Actor.ActorId); err != nil { + if err := crashActor(ctx, s.store, state.Actor.GetMetadata().GetAtespace(), state.Actor.GetMetadata().GetName()); err != nil { slog.Error("Failed to crash actor", slog.String("err", err.Error())) } return fmt.Errorf("actor is CRASHED because it was in PAUSING state but has no active worker") @@ -126,8 +131,8 @@ func (s *CallAteletPauseStep) Execute(ctx context.Context, input *PauseInput, st // into the snapshot manifest. req := &ateletpb.CheckpointRequest{ TargetAteomUid: state.Actor.GetAteomPodUid(), - Atespace: state.Actor.GetAtespace(), - ActorId: state.Actor.GetActorId(), + Atespace: state.Actor.GetMetadata().GetAtespace(), + ActorId: state.Actor.GetMetadata().GetName(), ActorTemplateNamespace: state.Actor.GetActorTemplateNamespace(), ActorTemplateName: state.Actor.GetActorTemplateName(), Spec: workloadSpec, @@ -141,7 +146,7 @@ func (s *CallAteletPauseStep) Execute(ctx context.Context, input *PauseInput, st } _, err = client.Checkpoint(ctx, req) - return maybeCrashActor(ctx, s.store, input.Atespace, input.ActorID, err, "while checkpointing workload") + return maybeCrashActor(ctx, s.store, input.Atespace, input.ActorName, err, "while checkpointing workload") } func (s *CallAteletPauseStep) RetryBackoff() *wait.Backoff { return nil } @@ -156,7 +161,7 @@ func (s *FinalizePausedStep) IsComplete(ctx context.Context, input *PauseInput, return state.Actor.GetStatus() == ateapipb.Actor_STATUS_PAUSED && state.Actor.GetAteomPodNamespace() == "", nil } func (s *FinalizePausedStep) Execute(ctx context.Context, input *PauseInput, state *PauseState) error { - latestActor, err := s.store.GetActor(ctx, input.Atespace, input.ActorID) + latestActor, err := s.store.GetActor(ctx, input.Atespace, input.ActorName) if err != nil { return err } @@ -181,7 +186,7 @@ func (s *FinalizePausedStep) Execute(ctx context.Context, input *PauseInput, sta // Only free it if it still belongs to us if wass := worker.Assignment; wass != nil { - if wass.Actor.Name == input.ActorID { + if wass.Actor.Name == input.ActorName { worker.Assignment = nil err = s.store.UpdateWorker(ctx, worker, worker.Version) if err != nil { @@ -192,14 +197,14 @@ func (s *FinalizePausedStep) Execute(ctx context.Context, input *PauseInput, sta } // 2. Safely clear ActiveWorker now that the worker object in DB is freed - latestActor, err = s.store.GetActor(ctx, input.Atespace, input.ActorID) + latestActor, err = s.store.GetActor(ctx, input.Atespace, input.ActorName) if err != nil { return err } latestActor.Status = ateapipb.Actor_STATUS_PAUSED // TODO(dberkov) - what if we still don't know the node name? Maybe move to CRASHED status? if nodeName == "" { - slog.Warn("Node name not found during finalize pause", "actor", input.ActorID) + slog.Warn("Node name not found during finalize pause", "actor", input.ActorName) } // TODO(dberkov) - what if InProgressSnapshot is empty? That shouldn't be possible. if latestActor.InProgressSnapshot != "" { @@ -217,10 +222,11 @@ func (s *FinalizePausedStep) Execute(ctx context.Context, input *PauseInput, sta latestActor.AteomPodName = "" latestActor.AteomPodIp = "" latestActor.WorkerPoolName = "" - err = s.store.UpdateActor(ctx, latestActor, latestActor.GetVersion()) + updatedActor, err := s.store.UpdateActor(ctx, latestActor, latestActor.GetMetadata().GetVersion()) if err != nil { return err } + latestActor = updatedActor } state.Actor = latestActor diff --git a/cmd/ateapi/internal/controlapi/workflow_resume.go b/cmd/ateapi/internal/controlapi/workflow_resume.go index 8a81612dd..7cd768ac4 100644 --- a/cmd/ateapi/internal/controlapi/workflow_resume.go +++ b/cmd/ateapi/internal/controlapi/workflow_resume.go @@ -40,9 +40,9 @@ import ( // ResumeInput holds the immutable parameters requested by the client. type ResumeInput struct { - ActorID string - Atespace string - Boot bool + ActorName string + Atespace string + Boot bool } // ResumeState holds the mutable state loaded and modified during execution. @@ -62,10 +62,10 @@ func (s *LoadActorForResumeStep) IsComplete(ctx context.Context, input *ResumeIn return false, nil } func (s *LoadActorForResumeStep) Execute(ctx context.Context, input *ResumeInput, state *ResumeState) error { - actor, err := s.store.GetActor(ctx, input.Atespace, input.ActorID) + actor, err := s.store.GetActor(ctx, input.Atespace, input.ActorName) if err != nil { if errors.Is(err, store.ErrNotFound) { - return status.Errorf(codes.NotFound, "Actor %s not found", input.ActorID) + return status.Errorf(codes.NotFound, "Actor %s not found", input.ActorName) } return fmt.Errorf("while getting actor from DB: %w", err) } @@ -132,7 +132,7 @@ func (s *AssignWorkerStep) Execute(ctx context.Context, input *ResumeInput, stat if worker.Assignment == nil { continue } - if worker.Assignment.Actor.Name != input.ActorID { + if worker.Assignment.Actor.Name != input.ActorName { continue } eligible, err := isWorkerEligibleForActor(worker, state.ActorTemplate.Spec.SandboxClass, state.ActorTemplate.Spec.WorkerSelector, state.Actor.GetWorkerSelector()) @@ -175,8 +175,8 @@ func (s *AssignWorkerStep) Execute(ctx context.Context, input *ResumeInput, stat Name: state.Actor.GetActorTemplateName(), }, Actor: &ateapipb.ActorRef{ - Name: input.ActorID, - Atespace: state.Actor.GetAtespace(), + Name: input.ActorName, + Atespace: state.Actor.GetMetadata().GetAtespace(), }, } @@ -191,9 +191,11 @@ func (s *AssignWorkerStep) Execute(ctx context.Context, input *ResumeInput, stat state.Actor.AteomPodUid = assignedWorker.GetWorkerPodUid() state.Actor.WorkerPoolName = assignedWorker.GetWorkerPool() - if err := s.store.UpdateActor(ctx, state.Actor, state.Actor.GetVersion()); err != nil { + updatedActor, err := s.store.UpdateActor(ctx, state.Actor, state.Actor.GetMetadata().GetVersion()) + if err != nil { return err } + state.Actor = updatedActor return nil } @@ -269,8 +271,8 @@ func (s *CallAteletRestoreStep) Execute(ctx context.Context, input *ResumeInput, req := &ateletpb.RestoreRequest{ TargetAteomUid: state.Actor.GetAteomPodUid(), - Atespace: state.Actor.GetAtespace(), - ActorId: state.Actor.GetActorId(), + Atespace: state.Actor.GetMetadata().GetAtespace(), + ActorId: state.Actor.GetMetadata().GetName(), ActorTemplateNamespace: state.Actor.GetActorTemplateNamespace(), ActorTemplateName: state.Actor.GetActorTemplateName(), Spec: workloadSpec, @@ -297,7 +299,7 @@ func (s *CallAteletRestoreStep) Execute(ctx context.Context, input *ResumeInput, } _, err = client.Restore(ctx, req) - return maybeCrashActor(ctx, s.store, input.Atespace, input.ActorID, err, "while restoring workload") + return maybeCrashActor(ctx, s.store, input.Atespace, input.ActorName, err, "while restoring workload") } else if state.ActorTemplate.Status.GoldenSnapshot != "" && !input.Boot { slog.InfoContext(ctx, "Actor has no snapshot; ActorTemplate has golden snapshot; Restoring from golden snapshot") @@ -305,8 +307,8 @@ func (s *CallAteletRestoreStep) Execute(ctx context.Context, input *ResumeInput, req := &ateletpb.RestoreRequest{ TargetAteomUid: state.Actor.GetAteomPodUid(), - Atespace: state.Actor.GetAtespace(), - ActorId: state.Actor.GetActorId(), + Atespace: state.Actor.GetMetadata().GetAtespace(), + ActorId: state.Actor.GetMetadata().GetName(), ActorTemplateNamespace: state.Actor.GetActorTemplateNamespace(), ActorTemplateName: state.Actor.GetActorTemplateName(), Spec: workloadSpec, @@ -319,7 +321,7 @@ func (s *CallAteletRestoreStep) Execute(ctx context.Context, input *ResumeInput, Scope: toAteletSnapshotScope(state.ActorTemplate.Spec.SnapshotsConfig.OnCommit), } _, err = client.Restore(ctx, req) - return maybeCrashActor(ctx, s.store, input.Atespace, input.ActorID, err, "while creating workload from golden snapshot") + return maybeCrashActor(ctx, s.store, input.Atespace, input.ActorName, err, "while creating workload from golden snapshot") } else { slog.InfoContext(ctx, "Actor has no snapshot; ActorTemplate has no golden snapshot; Booting from ActorTemplate spec") @@ -333,15 +335,15 @@ func (s *CallAteletRestoreStep) Execute(ctx context.Context, input *ResumeInput, req := &ateletpb.RunRequest{ TargetAteomUid: state.Actor.GetAteomPodUid(), - Atespace: state.Actor.GetAtespace(), - ActorId: state.Actor.GetActorId(), + Atespace: state.Actor.GetMetadata().GetAtespace(), + ActorId: state.Actor.GetMetadata().GetName(), ActorTemplateNamespace: state.Actor.GetActorTemplateNamespace(), ActorTemplateName: state.Actor.GetActorTemplateName(), SandboxAssets: sandboxAssets, Spec: workloadSpec, } _, err = client.Run(ctx, req) - return maybeCrashActor(ctx, s.store, input.Atespace, input.ActorID, err, "while creating workload from spec") + return maybeCrashActor(ctx, s.store, input.Atespace, input.ActorName, err, "while creating workload from spec") } // Unreachable } @@ -357,17 +359,18 @@ func (s *FinalizeRunningStep) IsComplete(ctx context.Context, input *ResumeInput return state.Actor.GetStatus() == ateapipb.Actor_STATUS_RUNNING, nil } func (s *FinalizeRunningStep) Execute(ctx context.Context, input *ResumeInput, state *ResumeState) error { - latestActor, err := s.store.GetActor(ctx, input.Atespace, input.ActorID) + latestActor, err := s.store.GetActor(ctx, input.Atespace, input.ActorName) if err != nil { return err } latestActor.Status = ateapipb.Actor_STATUS_RUNNING - err = s.store.UpdateActor(ctx, latestActor, latestActor.GetVersion()) - if err == nil { - state.Actor = latestActor + updatedActor, err := s.store.UpdateActor(ctx, latestActor, latestActor.GetMetadata().GetVersion()) + if err != nil { + return err } - return err + state.Actor = updatedActor + return nil } func (s *FinalizeRunningStep) RetryBackoff() *wait.Backoff { return nil } diff --git a/cmd/ateapi/internal/controlapi/workflow_suspend.go b/cmd/ateapi/internal/controlapi/workflow_suspend.go index 1306ceabf..cacb8c307 100644 --- a/cmd/ateapi/internal/controlapi/workflow_suspend.go +++ b/cmd/ateapi/internal/controlapi/workflow_suspend.go @@ -33,8 +33,8 @@ import ( // SuspendInput holds the immutable parameters requested by the client. type SuspendInput struct { - ActorID string - Atespace string + ActorName string + Atespace string } // SuspendState holds the mutable state loaded and modified during execution. @@ -54,7 +54,7 @@ func (s *LoadActorForSuspendStep) IsComplete(ctx context.Context, input *Suspend return false, nil } func (s *LoadActorForSuspendStep) Execute(ctx context.Context, input *SuspendInput, state *SuspendState) error { - actor, err := s.store.GetActor(ctx, input.Atespace, input.ActorID) + actor, err := s.store.GetActor(ctx, input.Atespace, input.ActorName) if err != nil { return err } @@ -87,8 +87,13 @@ func (s *MarkSuspendingStep) Execute(ctx context.Context, input *SuspendInput, s state.Actor.Status = ateapipb.Actor_STATUS_SUSPENDING snapshotID := time.Now().Format(time.RFC3339) + "-" + rand.Text() - state.Actor.InProgressSnapshot = strings.TrimSuffix(state.ActorTemplate.Spec.SnapshotsConfig.Location, "/") + "/" + input.ActorID + "/" + snapshotID - return s.store.UpdateActor(ctx, state.Actor, state.Actor.GetVersion()) + state.Actor.InProgressSnapshot = strings.TrimSuffix(state.ActorTemplate.Spec.SnapshotsConfig.Location, "/") + "/" + input.ActorName + "/" + snapshotID + updatedActor, err := s.store.UpdateActor(ctx, state.Actor, state.Actor.GetMetadata().GetVersion()) + if err != nil { + return err + } + state.Actor = updatedActor + return nil } func (s *MarkSuspendingStep) RetryBackoff() *wait.Backoff { return nil } @@ -105,7 +110,7 @@ func (s *CallAteletSuspendStep) IsComplete(ctx context.Context, input *SuspendIn } func (s *CallAteletSuspendStep) Execute(ctx context.Context, input *SuspendInput, state *SuspendState) error { if state.Actor.GetAteomPodNamespace() == "" || state.Actor.GetAteomPodName() == "" { - if err := crashActor(ctx, s.store, state.Actor.Atespace, state.Actor.ActorId); err != nil { + if err := crashActor(ctx, s.store, state.Actor.GetMetadata().GetAtespace(), state.Actor.GetMetadata().GetName()); err != nil { slog.Error("Failed to crash actor", slog.String("err", err.Error())) } return fmt.Errorf("actor is CRASHED because it was in SUSPENDING state but has no active worker") @@ -128,8 +133,8 @@ func (s *CallAteletSuspendStep) Execute(ctx context.Context, input *SuspendInput // into the snapshot manifest. req := &ateletpb.CheckpointRequest{ TargetAteomUid: state.Actor.GetAteomPodUid(), - Atespace: state.Actor.GetAtespace(), - ActorId: state.Actor.GetActorId(), + Atespace: state.Actor.GetMetadata().GetAtespace(), + ActorId: state.Actor.GetMetadata().GetName(), ActorTemplateNamespace: state.Actor.GetActorTemplateNamespace(), ActorTemplateName: state.Actor.GetActorTemplateName(), Spec: workloadSpec, @@ -143,7 +148,7 @@ func (s *CallAteletSuspendStep) Execute(ctx context.Context, input *SuspendInput } _, err = client.Checkpoint(ctx, req) - return maybeCrashActor(ctx, s.store, input.Atespace, input.ActorID, err, "while checkpointing workload") + return maybeCrashActor(ctx, s.store, input.Atespace, input.ActorName, err, "while checkpointing workload") } func (s *CallAteletSuspendStep) RetryBackoff() *wait.Backoff { return nil } @@ -158,7 +163,7 @@ func (s *FinalizeSuspendedStep) IsComplete(ctx context.Context, input *SuspendIn return state.Actor.GetStatus() == ateapipb.Actor_STATUS_SUSPENDED && state.Actor.GetAteomPodNamespace() == "", nil } func (s *FinalizeSuspendedStep) Execute(ctx context.Context, input *SuspendInput, state *SuspendState) error { - latestActor, err := s.store.GetActor(ctx, input.Atespace, input.ActorID) + latestActor, err := s.store.GetActor(ctx, input.Atespace, input.ActorName) if err != nil { return err } @@ -179,7 +184,7 @@ func (s *FinalizeSuspendedStep) Execute(ctx context.Context, input *SuspendInput } else { // Only free it if it still belongs to us if wass := worker.Assignment; wass != nil { - if wass.Actor.Name == input.ActorID { + if wass.Actor.Name == input.ActorName { worker.Assignment = nil err = s.store.UpdateWorker(ctx, worker, worker.Version) if err != nil { @@ -190,7 +195,7 @@ func (s *FinalizeSuspendedStep) Execute(ctx context.Context, input *SuspendInput } // 2. Safely clear ActiveWorker now that the worker object in DB is freed - latestActor, err = s.store.GetActor(ctx, input.Atespace, input.ActorID) + latestActor, err = s.store.GetActor(ctx, input.Atespace, input.ActorName) if err != nil { return err } @@ -209,10 +214,11 @@ func (s *FinalizeSuspendedStep) Execute(ctx context.Context, input *SuspendInput latestActor.AteomPodName = "" latestActor.AteomPodIp = "" latestActor.WorkerPoolName = "" - err = s.store.UpdateActor(ctx, latestActor, latestActor.GetVersion()) + updatedActor, err := s.store.UpdateActor(ctx, latestActor, latestActor.GetMetadata().GetVersion()) if err != nil { return err } + latestActor = updatedActor } state.Actor = latestActor diff --git a/cmd/ateapi/internal/store/ateredis/ateredis.go b/cmd/ateapi/internal/store/ateredis/ateredis.go index 82877c387..98b921983 100644 --- a/cmd/ateapi/internal/store/ateredis/ateredis.go +++ b/cmd/ateapi/internal/store/ateredis/ateredis.go @@ -15,7 +15,7 @@ // Package ateredis is an ate storage backend built on Redis. // // Actors are stored in keys of the form -// `actor::`. They are +// `actor::`. They are // stored as DBActor JSON-serialized objects, which lets us manipulate them from // Redis lua. // @@ -55,9 +55,11 @@ import ( "github.com/agent-substrate/substrate/cmd/ateapi/internal/store" "github.com/agent-substrate/substrate/pkg/proto/ateapipb" + "github.com/google/uuid" "github.com/redis/go-redis/v9" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" ) type workerPubSubMsg struct { @@ -86,8 +88,8 @@ func NewPersistence(redisClient *redis.ClusterClient) *Persistence { } } -func actorDBKey(atespace, id string) string { - return "actor:" + atespace + ":" + id +func actorDBKey(atespace, name string) string { + return "actor:" + atespace + ":" + name } // actorScanPattern returns the SCAN match pattern for listing actors. An empty @@ -104,20 +106,25 @@ func atespaceDBKey(name string) string { return "atespace:" + name } -func (s *Persistence) CreateAtespace(ctx context.Context, atespace *ateapipb.Atespace) error { - dbKey := atespaceDBKey(atespace.GetName()) - dbBytes, err := protojson.Marshal(atespace) +func (s *Persistence) CreateAtespace(ctx context.Context, atespace *ateapipb.Atespace) (*ateapipb.Atespace, error) { + dbKey := atespaceDBKey(atespace.GetMetadata().GetName()) + + dbAtespace := proto.Clone(atespace).(*ateapipb.Atespace) + // Atespace is global-scoped: identity is the name alone (atespace stays empty). + dbAtespace.Metadata = newCreateMetadata("", atespace.GetMetadata().GetName()) + + dbBytes, err := protojson.Marshal(dbAtespace) if err != nil { - return fmt.Errorf("in protojson.Marshal: %w", err) + return nil, fmt.Errorf("in protojson.Marshal: %w", err) } ok, err := s.rdb.SetNX(ctx, dbKey, dbBytes, 0).Result() if err != nil { - return fmt.Errorf("while executing redis set: %w", err) + return nil, fmt.Errorf("while executing redis set: %w", err) } if !ok { - return store.ErrAlreadyExists + return nil, store.ErrAlreadyExists } - return nil + return dbAtespace, nil } func (s *Persistence) GetAtespace(ctx context.Context, name string) (*ateapipb.Atespace, error) { @@ -133,7 +140,7 @@ func (s *Persistence) GetAtespace(ctx context.Context, name string) (*ateapipb.A if err := protojson.Unmarshal(dbBytes, atespace); err != nil { return nil, fmt.Errorf("while unmarshaling atespace: %w", err) } - if atespace.GetName() != name { + if atespace.GetMetadata().GetName() != name { return nil, fmt.Errorf("(impossible) mismatch between stored name and key %q", dbKey) } return atespace, nil @@ -313,8 +320,8 @@ func (s *Persistence) DebugClearAll(ctx context.Context) error { return err } -func (s *Persistence) GetActor(ctx context.Context, atespace, id string) (*ateapipb.Actor, error) { - dbKey := actorDBKey(atespace, id) +func (s *Persistence) GetActor(ctx context.Context, atespace, name string) (*ateapipb.Actor, error) { + dbKey := actorDBKey(atespace, name) dbActorBytes, err := s.rdb.Get(ctx, dbKey).Bytes() if err != nil { @@ -329,35 +336,35 @@ func (s *Persistence) GetActor(ctx context.Context, atespace, id string) (*ateap return nil, fmt.Errorf("while unmarshaling actor: %w", err) } - if actor.GetActorId() != id || actor.GetAtespace() != atespace { - return nil, fmt.Errorf("(impossible) mismatch between stored id/atespace and key") + if actor.GetMetadata().GetName() != name || actor.GetMetadata().GetAtespace() != atespace { + return nil, fmt.Errorf("(impossible) mismatch between stored name/atespace and key") } return actor, nil } -func (s *Persistence) CreateActor(ctx context.Context, actor *ateapipb.Actor) error { - dbKey := actorDBKey(actor.GetAtespace(), actor.GetActorId()) +func (s *Persistence) CreateActor(ctx context.Context, actor *ateapipb.Actor) (*ateapipb.Actor, error) { + dbKey := actorDBKey(actor.GetMetadata().GetAtespace(), actor.GetMetadata().GetName()) - // Clone because we will update the version field, and we don't want to - // stomp the caller's copy. + // Clone so we don't stomp the caller's copy, then attach fresh server-owned + // metadata carrying the caller-specified identity. dbActor := proto.Clone(actor).(*ateapipb.Actor) - dbActor.Version = 1 + dbActor.Metadata = newCreateMetadata(actor.GetMetadata().GetAtespace(), actor.GetMetadata().GetName()) dbActorBytes, err := protojson.Marshal(dbActor) if err != nil { - return fmt.Errorf("in protojson.Marshal: %w", err) + return nil, fmt.Errorf("in protojson.Marshal: %w", err) } ok, err := s.rdb.SetNX(ctx, dbKey, dbActorBytes, 0).Result() if err != nil { - return fmt.Errorf("while executing redis set: %w", err) + return nil, fmt.Errorf("while executing redis set: %w", err) } if !ok { - return store.ErrAlreadyExists + return nil, store.ErrAlreadyExists } - return nil + return dbActor, nil } func (s *Persistence) CreateWorker(ctx context.Context, worker *ateapipb.Worker) error { @@ -481,8 +488,8 @@ func (s *Persistence) DeleteWorker(ctx context.Context, namespace, pool, pod str return nil } -func (s *Persistence) DeleteActor(ctx context.Context, atespace, id string) error { - dbKey := actorDBKey(atespace, id) +func (s *Persistence) DeleteActor(ctx context.Context, atespace, name string) error { + dbKey := actorDBKey(atespace, name) err := s.rdb.Watch(ctx, func(tx *redis.Tx) error { currentVal, err := tx.Get(ctx, dbKey).Bytes() if err != nil { @@ -519,8 +526,8 @@ func (s *Persistence) DeleteActor(ctx context.Context, atespace, id string) erro return nil } -func (s *Persistence) UpdateActor(ctx context.Context, actor *ateapipb.Actor, expectedVersion int64) error { - dbKey := actorDBKey(actor.GetAtespace(), actor.GetActorId()) +func (s *Persistence) UpdateActor(ctx context.Context, actor *ateapipb.Actor, expectedVersion int64) (*ateapipb.Actor, error) { + dbKey := actorDBKey(actor.GetMetadata().GetAtespace(), actor.GetMetadata().GetName()) // Clone because we will update the version field, and we don't want to // stomp the caller's copy. @@ -540,14 +547,13 @@ func (s *Persistence) UpdateActor(ctx context.Context, actor *ateapipb.Actor, ex return fmt.Errorf("in protojson.Unmarshal: %w", err) } - if currentActor.GetVersion() != expectedVersion { + if currentActor.GetMetadata().GetVersion() != expectedVersion { return store.ErrPersistenceRetry } - dbActor.Version = currentActor.GetVersion() + 1 - if currentActor.GetActorId() != dbActor.GetActorId() { - return fmt.Errorf("actor_id is immutable") + if currentActor.GetMetadata().GetName() != dbActor.GetMetadata().GetName() { + return fmt.Errorf("name is immutable") } - if currentActor.GetAtespace() != dbActor.GetAtespace() { + if currentActor.GetMetadata().GetAtespace() != dbActor.GetMetadata().GetAtespace() { return fmt.Errorf("atespace is immutable") } if currentActor.GetActorTemplateNamespace() != dbActor.GetActorTemplateNamespace() { @@ -556,6 +562,8 @@ func (s *Persistence) UpdateActor(ctx context.Context, actor *ateapipb.Actor, ex if currentActor.GetActorTemplateName() != dbActor.GetActorTemplateName() { return fmt.Errorf("actor_template_name is immutable") } + // The stored metadata is authoritative; derive the next metadata from it. + dbActor.Metadata = newUpdateMetadata(currentActor.GetMetadata()) newVal, err := protojson.Marshal(dbActor) if err != nil { @@ -571,13 +579,14 @@ func (s *Persistence) UpdateActor(ctx context.Context, actor *ateapipb.Actor, ex if err != nil { if errors.Is(err, store.ErrPersistenceRetry) || errors.Is(err, redis.TxFailedErr) { - return store.ErrPersistenceRetry + return nil, store.ErrPersistenceRetry } - return fmt.Errorf("while executing update actor transaction: %w", err) + return nil, fmt.Errorf("while executing update actor transaction: %w", err) } - actor.Version = dbActor.Version - return nil + // dbActor is the persisted state (advanced version and update_time). The + // caller's input is left unmodified. + return dbActor, nil } func (s *Persistence) ListWorkers(ctx context.Context) ([]*ateapipb.Worker, error) { @@ -818,3 +827,22 @@ func (s *Persistence) ReleaseLock(ctx context.Context, key string, value string) } return nil } + +func newCreateMetadata(atespace, name string) *ateapipb.ResourceMetadata { + now := timestamppb.Now() + return &ateapipb.ResourceMetadata{ + Atespace: atespace, + Name: name, + Uid: uuid.NewString(), + Version: 1, + CreateTime: now, + UpdateTime: now, + } +} + +func newUpdateMetadata(current *ateapipb.ResourceMetadata) *ateapipb.ResourceMetadata { + next := proto.Clone(current).(*ateapipb.ResourceMetadata) + next.Version = current.GetVersion() + 1 + next.UpdateTime = timestamppb.Now() + return next +} diff --git a/cmd/ateapi/internal/store/ateredis/ateredis_test.go b/cmd/ateapi/internal/store/ateredis/ateredis_test.go index dad25c3ad..06faba93a 100644 --- a/cmd/ateapi/internal/store/ateredis/ateredis_test.go +++ b/cmd/ateapi/internal/store/ateredis/ateredis_test.go @@ -47,11 +47,24 @@ func setupTest(t *testing.T) (*miniredis.Miniredis, *Persistence, context.Contex return mr, &Persistence{rdb: rdb}, context.Background() } +// testAtespace is the atespace used by tests that create a single actor. Actors +// are atespace-scoped, so a real atespace must always be part of their identity. +const testAtespace = "test-atespace" + +// Atomic cmp options to skip individual server-owned ResourceMetadata fields in +// proto diffs. Compose the ones a given assertion needs — e.g. ignore uid and +// timestamps but keep version when the test asserts a specific version. +var ( + ignoreUID = protocmp.IgnoreFields(&ateapipb.ResourceMetadata{}, "uid") + ignoreVersion = protocmp.IgnoreFields(&ateapipb.ResourceMetadata{}, "version") + ignoreTimestamps = protocmp.IgnoreFields(&ateapipb.ResourceMetadata{}, "create_time", "update_time") +) + func TestGetActor_NotFound(t *testing.T) { mr, s, ctx := setupTest(t) defer mr.Close() - _, err := s.GetActor(ctx, "", "non-existent") + _, err := s.GetActor(ctx, testAtespace, "non-existent") if !errors.Is(err, store.ErrNotFound) { t.Errorf("expected ErrNotFound, got %v", err) } @@ -62,27 +75,47 @@ func TestCreateActor_Success(t *testing.T) { defer mr.Close() actor := &ateapipb.Actor{ - ActorId: "session-1", + Metadata: &ateapipb.ResourceMetadata{Name: "session-1", Atespace: testAtespace}, ActorTemplateNamespace: "default", ActorTemplateName: "test-template", Status: ateapipb.Actor_STATUS_SUSPENDED, } - err := s.CreateActor(ctx, actor) + created, err := s.CreateActor(ctx, actor) if err != nil { t.Fatalf("CreateActor failed: %v", err) } - got, err := s.GetActor(ctx, actor.GetAtespace(), actor.ActorId) + // CreateActor returns the stored resource with server-assigned metadata. + if created.GetMetadata().GetUid() == "" { + t.Errorf("CreateActor returned empty uid; want server-assigned uid") + } + if created.GetMetadata().GetVersion() != 1 { + t.Errorf("CreateActor returned version %d, want 1", created.GetMetadata().GetVersion()) + } + if created.GetMetadata().GetCreateTime() == nil || created.GetMetadata().GetUpdateTime() == nil { + t.Errorf("CreateActor returned unset create/update time") + } + + // The input must not be mutated. + if actor.GetMetadata().GetUid() != "" || actor.GetMetadata().GetVersion() != 0 { + t.Errorf("CreateActor must not mutate its input, got metadata %v", actor.GetMetadata()) + } + + // The returned resource is exactly what GetActor reads back. + got, err := s.GetActor(ctx, actor.GetMetadata().GetAtespace(), actor.GetMetadata().GetName()) if err != nil { t.Fatalf("GetActor failed: %v", err) } + if diff := cmp.Diff(created, got, protocmp.Transform()); diff != "" { + t.Errorf("CreateActor return does not match stored state (-created +got):\n%s", diff) + } + // Structurally: the input fields plus server-assigned metadata. expected := proto.Clone(actor).(*ateapipb.Actor) - expected.Version = 1 - - if diff := cmp.Diff(expected, got, protocmp.Transform()); diff != "" { - t.Errorf("GetActor returned unexpected actor (-want +got):\n%s", diff) + expected.Metadata.Version = 1 + if diff := cmp.Diff(expected, created, protocmp.Transform(), ignoreUID, ignoreTimestamps); diff != "" { + t.Errorf("CreateActor returned unexpected actor (-want +got):\n%s", diff) } } @@ -91,18 +124,18 @@ func TestCreateActor_AlreadyExists(t *testing.T) { defer mr.Close() actor := &ateapipb.Actor{ - ActorId: "session-1", + Metadata: &ateapipb.ResourceMetadata{Name: "session-1", Atespace: testAtespace}, ActorTemplateNamespace: "default", ActorTemplateName: "test-template", Status: ateapipb.Actor_STATUS_SUSPENDED, } - err := s.CreateActor(ctx, actor) + _, err := s.CreateActor(ctx, actor) if err != nil { t.Fatalf("CreateActor failed: %v", err) } - err = s.CreateActor(ctx, actor) + _, err = s.CreateActor(ctx, actor) if err == nil { t.Errorf("expected error creating existing actor, got nil") } @@ -113,38 +146,51 @@ func TestUpdateActor_Success(t *testing.T) { defer mr.Close() actor := &ateapipb.Actor{ - ActorId: "session-1", + Metadata: &ateapipb.ResourceMetadata{Name: "session-1", Atespace: testAtespace}, ActorTemplateNamespace: "default", ActorTemplateName: "test-template", Status: ateapipb.Actor_STATUS_SUSPENDED, } - err := s.CreateActor(ctx, actor) + created, err := s.CreateActor(ctx, actor) if err != nil { t.Fatalf("CreateActor failed: %v", err) } - actor.Status = ateapipb.Actor_STATUS_RUNNING - actor.Version = 1 - - err = s.UpdateActor(ctx, actor, 1) + toUpdate := proto.Clone(created).(*ateapipb.Actor) + toUpdate.Status = ateapipb.Actor_STATUS_RUNNING + updated, err := s.UpdateActor(ctx, toUpdate, created.GetMetadata().GetVersion()) if err != nil { t.Fatalf("UpdateActor failed: %v", err) } - if actor.Version != 2 { - t.Errorf("expected actor.Version to be updated to 2, got %d", actor.Version) + // UpdateActor returns the stored resource: the mutation applied and version + // advanced, with uid and create_time preserved from creation. + if updated.GetStatus() != ateapipb.Actor_STATUS_RUNNING { + t.Errorf("UpdateActor returned status %v, want RUNNING", updated.GetStatus()) + } + if updated.GetMetadata().GetVersion() != 2 { + t.Errorf("UpdateActor returned version %d, want 2", updated.GetMetadata().GetVersion()) + } + if updated.GetMetadata().GetUid() != created.GetMetadata().GetUid() { + t.Errorf("uid changed on update: got %q, want %q", updated.GetMetadata().GetUid(), created.GetMetadata().GetUid()) + } + if !updated.GetMetadata().GetCreateTime().AsTime().Equal(created.GetMetadata().GetCreateTime().AsTime()) { + t.Errorf("create_time changed on update: got %v, want %v", updated.GetMetadata().GetCreateTime().AsTime(), created.GetMetadata().GetCreateTime().AsTime()) + } + + // The input must not be mutated. + if toUpdate.GetMetadata().GetVersion() != created.GetMetadata().GetVersion() { + t.Errorf("UpdateActor must not mutate its input; version changed to %d", toUpdate.GetMetadata().GetVersion()) } - updated, err := s.GetActor(ctx, actor.GetAtespace(), actor.ActorId) + // The returned resource is exactly what GetActor reads back. + got, err := s.GetActor(ctx, actor.GetMetadata().GetAtespace(), actor.GetMetadata().GetName()) if err != nil { t.Fatalf("GetActor failed: %v", err) } - - expected := proto.Clone(actor).(*ateapipb.Actor) - - if diff := cmp.Diff(expected, updated, protocmp.Transform()); diff != "" { - t.Errorf("UpdateActor yielded unexpected state in DB (-want +got):\n%s", diff) + if diff := cmp.Diff(updated, got, protocmp.Transform()); diff != "" { + t.Errorf("UpdateActor return does not match stored state (-updated +got):\n%s", diff) } } @@ -153,39 +199,39 @@ func TestUpdateActor_Conflict(t *testing.T) { defer mr.Close() actor := &ateapipb.Actor{ - ActorId: "session-1", + Metadata: &ateapipb.ResourceMetadata{Name: "session-1", Atespace: testAtespace}, ActorTemplateNamespace: "default", ActorTemplateName: "test-template", Status: ateapipb.Actor_STATUS_SUSPENDED, } - err := s.CreateActor(ctx, actor) + _, err := s.CreateActor(ctx, actor) if err != nil { t.Fatalf("CreateActor failed: %v", err) } // Fetch instance 1 - actor1, err := s.GetActor(ctx, actor.GetAtespace(), actor.ActorId) + actor1, err := s.GetActor(ctx, actor.GetMetadata().GetAtespace(), actor.GetMetadata().GetName()) if err != nil { t.Fatalf("GetActor failed: %v", err) } // Fetch instance 2 (stale after actor1 updates) - actor2, err := s.GetActor(ctx, actor.GetAtespace(), actor.ActorId) + actor2, err := s.GetActor(ctx, actor.GetMetadata().GetAtespace(), actor.GetMetadata().GetName()) if err != nil { t.Fatalf("GetActor failed: %v", err) } // Update instance 1 actor1.Status = ateapipb.Actor_STATUS_RUNNING - err = s.UpdateActor(ctx, actor1, actor1.GetVersion()) + _, err = s.UpdateActor(ctx, actor1, actor1.GetMetadata().GetVersion()) if err != nil { t.Fatalf("UpdateActor failed: %v", err) } // Try to update instance 2 (which has stale version) actor2.Status = ateapipb.Actor_STATUS_SUSPENDED - err = s.UpdateActor(ctx, actor2, actor2.GetVersion()) + _, err = s.UpdateActor(ctx, actor2, actor2.GetMetadata().GetVersion()) if !errors.Is(err, store.ErrPersistenceRetry) { t.Errorf("expected ErrPersistenceRetry, got %v", err) } @@ -358,17 +404,17 @@ func TestDeleteActor(t *testing.T) { defer mr.Close() actor := &ateapipb.Actor{ - ActorId: "session-1", + Metadata: &ateapipb.ResourceMetadata{Name: "session-1", Atespace: testAtespace}, ActorTemplateNamespace: "default", ActorTemplateName: "test-template", Status: tt.status, } - if err := s.CreateActor(ctx, actor); err != nil { + if _, err := s.CreateActor(ctx, actor); err != nil { t.Fatalf("CreateActor failed: %v", err) } - err := s.DeleteActor(ctx, "", "session-1") + err := s.DeleteActor(ctx, testAtespace, "session-1") if tt.wantErr != nil { if !errors.Is(err, tt.wantErr) { t.Errorf("DeleteActor: expected %v, got %v", tt.wantErr, err) @@ -379,7 +425,7 @@ func TestDeleteActor(t *testing.T) { t.Fatalf("DeleteActor failed: %v", err) } - if _, err := s.GetActor(ctx, "", "session-1"); !errors.Is(err, store.ErrNotFound) { + if _, err := s.GetActor(ctx, testAtespace, "session-1"); !errors.Is(err, store.ErrNotFound) { t.Errorf("expected ErrNotFound after delete, got %v", err) } }) @@ -390,7 +436,7 @@ func TestDeleteActor_NotFound(t *testing.T) { mr, s, ctx := setupTest(t) defer mr.Close() - err := s.DeleteActor(ctx, "", "non-existent") + err := s.DeleteActor(ctx, testAtespace, "non-existent") if !errors.Is(err, store.ErrNotFound) { t.Errorf("expected ErrNotFound deleting non-existent actor, got %v", err) } @@ -447,7 +493,7 @@ func TestListActors(t *testing.T) { actor1 := &ateapipb.Actor{ - ActorId: "id1", + Metadata: &ateapipb.ResourceMetadata{Name: "id1", Atespace: testAtespace}, ActorTemplateNamespace: "ns1", ActorTemplateName: "tmpl1", Status: ateapipb.Actor_STATUS_SUSPENDED, @@ -460,7 +506,7 @@ func TestListActors(t *testing.T) { }, } actor2 := &ateapipb.Actor{ - ActorId: "id2", + Metadata: &ateapipb.ResourceMetadata{Name: "id2", Atespace: testAtespace}, ActorTemplateNamespace: "ns1", ActorTemplateName: "tmpl1", Status: ateapipb.Actor_STATUS_SUSPENDED, @@ -473,10 +519,10 @@ func TestListActors(t *testing.T) { }, } - if err := s.CreateActor(ctx, actor1); err != nil { + if _, err := s.CreateActor(ctx, actor1); err != nil { t.Fatalf("failed to create actor1: %v", err) } - if err := s.CreateActor(ctx, actor2); err != nil { + if _, err := s.CreateActor(ctx, actor2); err != nil { t.Fatalf("failed to create actor2: %v", err) } @@ -492,10 +538,10 @@ func TestListActors(t *testing.T) { found1 := false found2 := false for _, a := range actors { - if a.GetActorId() == "id1" { + if a.GetMetadata().GetName() == "id1" { found1 = true } - if a.GetActorId() == "id2" { + if a.GetMetadata().GetName() == "id2" { found2 = true } } @@ -601,12 +647,12 @@ func TestListActors_Pagination(t *testing.T) { for i := 0; i < 5; i++ { actor := &ateapipb.Actor{ - ActorId: fmt.Sprintf("id%d", i), + Metadata: &ateapipb.ResourceMetadata{Name: fmt.Sprintf("name%d", i), Atespace: testAtespace}, ActorTemplateNamespace: "ns1", ActorTemplateName: "tmpl1", Status: ateapipb.Actor_STATUS_SUSPENDED, } - if err := s.CreateActor(ctx, actor); err != nil { + if _, err := s.CreateActor(ctx, actor); err != nil { t.Fatalf("failed to create actor %d: %v", i, err) } } @@ -633,10 +679,10 @@ func TestListActors_Pagination(t *testing.T) { seen := make(map[string]bool) for _, a := range allActors { - if seen[a.ActorId] { - t.Errorf("duplicate actor found in paginated results: %s", a.ActorId) + if seen[a.GetMetadata().GetName()] { + t.Errorf("duplicate actor found in paginated results: %s", a.GetMetadata().GetName()) } - seen[a.ActorId] = true + seen[a.GetMetadata().GetName()] = true } } @@ -841,10 +887,9 @@ func TestListActors_ScopedByAtespace(t *testing.T) { mr, s, ctx := setupTest(t) defer mr.Close() - mkActor := func(atespace, id string) *ateapipb.Actor { + mkActor := func(atespace, name string) *ateapipb.Actor { return &ateapipb.Actor{ - ActorId: id, - Atespace: atespace, + Metadata: &ateapipb.ResourceMetadata{Name: name, Atespace: atespace}, ActorTemplateNamespace: "ns1", ActorTemplateName: "tmpl1", Status: ateapipb.Actor_STATUS_SUSPENDED, @@ -855,8 +900,8 @@ func TestListActors_ScopedByAtespace(t *testing.T) { mkActor("team-a", "a2"), mkActor("team-b", "b1"), } { - if err := s.CreateActor(ctx, a); err != nil { - t.Fatalf("CreateActor(%s/%s) failed: %v", a.GetAtespace(), a.GetActorId(), err) + if _, err := s.CreateActor(ctx, a); err != nil { + t.Fatalf("CreateActor(%s/%s) failed: %v", a.GetMetadata().GetAtespace(), a.GetMetadata().GetName(), err) } } @@ -865,7 +910,7 @@ func TestListActors_ScopedByAtespace(t *testing.T) { if err != nil { t.Fatalf("ListActors(team-a) failed: %v", err) } - if got := actorIDSet(teamA); !got["a1"] || !got["a2"] || got["b1"] || len(got) != 2 { + if got := actorNameSet(teamA); !got["a1"] || !got["a2"] || got["b1"] || len(got) != 2 { t.Errorf("ListActors(team-a) = %v, want exactly {a1, a2}", got) } @@ -873,7 +918,7 @@ func TestListActors_ScopedByAtespace(t *testing.T) { if err != nil { t.Fatalf("ListActors(team-b) failed: %v", err) } - if got := actorIDSet(teamB); !got["b1"] || got["a1"] || len(got) != 1 { + if got := actorNameSet(teamB); !got["b1"] || got["a1"] || len(got) != 1 { t.Errorf("ListActors(team-b) = %v, want exactly {b1}", got) } @@ -882,7 +927,7 @@ func TestListActors_ScopedByAtespace(t *testing.T) { if err != nil { t.Fatalf("ListActors(all) failed: %v", err) } - if got := actorIDSet(all); !got["a1"] || !got["a2"] || !got["b1"] || len(got) != 3 { + if got := actorNameSet(all); !got["a1"] || !got["a2"] || !got["b1"] || len(got) != 3 { t.Errorf("ListActors(all) = %v, want exactly {a1, a2, b1}", got) } @@ -898,16 +943,16 @@ func TestListActors_ScopedByAtespace(t *testing.T) { } } -func actorIDSet(actors []*ateapipb.Actor) map[string]bool { +func actorNameSet(actors []*ateapipb.Actor) map[string]bool { set := make(map[string]bool, len(actors)) for _, a := range actors { - set[a.GetActorId()] = true + set[a.GetMetadata().GetName()] = true } return set } func newTestAtespace(name string) *ateapipb.Atespace { - return &ateapipb.Atespace{Name: name} + return &ateapipb.Atespace{Metadata: &ateapipb.ResourceMetadata{Name: name}} } func TestCreateAtespace_Success(t *testing.T) { @@ -915,15 +960,31 @@ func TestCreateAtespace_Success(t *testing.T) { defer mr.Close() want := newTestAtespace("team-a") - if err := s.CreateAtespace(ctx, want); err != nil { + created, err := s.CreateAtespace(ctx, want) + if err != nil { t.Fatalf("CreateAtespace failed: %v", err) } + + // CreateAtespace returns the stored resource with server-assigned metadata. + if created.GetMetadata().GetUid() == "" { + t.Errorf("CreateAtespace returned empty uid; want server-assigned uid") + } + if created.GetMetadata().GetVersion() != 1 { + t.Errorf("CreateAtespace returned version %d, want 1", created.GetMetadata().GetVersion()) + } + + // The returned resource is exactly what GetAtespace reads back. got, err := s.GetAtespace(ctx, "team-a") if err != nil { t.Fatalf("GetAtespace failed: %v", err) } - if diff := cmp.Diff(want, got, protocmp.Transform()); diff != "" { - t.Errorf("round-trip mismatch (-want +got):\n%s", diff) + if diff := cmp.Diff(created, got, protocmp.Transform()); diff != "" { + t.Errorf("CreateAtespace return does not match stored state (-created +got):\n%s", diff) + } + + // want is the pre-create input; the server stamps uid, version, and timestamps. + if diff := cmp.Diff(want, created, protocmp.Transform(), ignoreUID, ignoreTimestamps, ignoreVersion); diff != "" { + t.Errorf("CreateAtespace returned unexpected atespace (-want +got):\n%s", diff) } } @@ -931,10 +992,10 @@ func TestCreateAtespace_AlreadyExists(t *testing.T) { mr, s, ctx := setupTest(t) defer mr.Close() - if err := s.CreateAtespace(ctx, newTestAtespace("team-a")); err != nil { + if _, err := s.CreateAtespace(ctx, newTestAtespace("team-a")); err != nil { t.Fatalf("first CreateAtespace failed: %v", err) } - if err := s.CreateAtespace(ctx, newTestAtespace("team-a")); !errors.Is(err, store.ErrAlreadyExists) { + if _, err := s.CreateAtespace(ctx, newTestAtespace("team-a")); !errors.Is(err, store.ErrAlreadyExists) { t.Errorf("expected ErrAlreadyExists, got %v", err) } } @@ -955,7 +1016,7 @@ func TestAtespaceExists(t *testing.T) { if ok, err := s.AtespaceExists(ctx, "team-a"); err != nil || ok { t.Fatalf("AtespaceExists before create = (%v, %v), want (false, nil)", ok, err) } - if err := s.CreateAtespace(ctx, newTestAtespace("team-a")); err != nil { + if _, err := s.CreateAtespace(ctx, newTestAtespace("team-a")); err != nil { t.Fatalf("CreateAtespace failed: %v", err) } if ok, err := s.AtespaceExists(ctx, "team-a"); err != nil || !ok { @@ -969,7 +1030,7 @@ func TestListAtespaces(t *testing.T) { names := []string{"team-a", "team-b", "team-c"} for _, n := range names { - if err := s.CreateAtespace(ctx, newTestAtespace(n)); err != nil { + if _, err := s.CreateAtespace(ctx, newTestAtespace(n)); err != nil { t.Fatalf("CreateAtespace(%s) failed: %v", n, err) } } @@ -982,7 +1043,7 @@ func TestListAtespaces(t *testing.T) { } gotNames := map[string]bool{} for _, a := range got { - gotNames[a.GetName()] = true + gotNames[a.GetMetadata().GetName()] = true } for _, n := range names { if !gotNames[n] { @@ -1008,7 +1069,7 @@ func TestDeleteAtespace_Empty(t *testing.T) { mr, s, ctx := setupTest(t) defer mr.Close() - if err := s.CreateAtespace(ctx, newTestAtespace("team-a")); err != nil { + if _, err := s.CreateAtespace(ctx, newTestAtespace("team-a")); err != nil { t.Fatalf("CreateAtespace failed: %v", err) } if err := s.DeleteAtespace(ctx, "team-a"); err != nil { @@ -1032,10 +1093,10 @@ func TestDeleteAtespace_NonEmpty_Rejected(t *testing.T) { mr, s, ctx := setupTest(t) defer mr.Close() - if err := s.CreateAtespace(ctx, newTestAtespace("team-a")); err != nil { + if _, err := s.CreateAtespace(ctx, newTestAtespace("team-a")); err != nil { t.Fatalf("CreateAtespace failed: %v", err) } - if err := s.CreateActor(ctx, &ateapipb.Actor{ActorId: "id1", Atespace: "team-a", Status: ateapipb.Actor_STATUS_SUSPENDED}); err != nil { + if _, err := s.CreateActor(ctx, &ateapipb.Actor{Metadata: &ateapipb.ResourceMetadata{Name: "id1", Atespace: "team-a"}, Status: ateapipb.Actor_STATUS_SUSPENDED}); err != nil { t.Fatalf("CreateActor failed: %v", err) } if err := s.DeleteAtespace(ctx, "team-a"); !errors.Is(err, store.ErrFailedPrecondition) { @@ -1051,10 +1112,10 @@ func TestDeleteAtespace_EmptyAfterActorsRemoved(t *testing.T) { mr, s, ctx := setupTest(t) defer mr.Close() - if err := s.CreateAtespace(ctx, newTestAtespace("team-a")); err != nil { + if _, err := s.CreateAtespace(ctx, newTestAtespace("team-a")); err != nil { t.Fatalf("CreateAtespace failed: %v", err) } - if err := s.CreateActor(ctx, &ateapipb.Actor{ActorId: "id1", Atespace: "team-a", Status: ateapipb.Actor_STATUS_SUSPENDED}); err != nil { + if _, err := s.CreateActor(ctx, &ateapipb.Actor{Metadata: &ateapipb.ResourceMetadata{Name: "id1", Atespace: "team-a"}, Status: ateapipb.Actor_STATUS_SUSPENDED}); err != nil { t.Fatalf("CreateActor failed: %v", err) } if err := s.DeleteAtespace(ctx, "team-a"); !errors.Is(err, store.ErrFailedPrecondition) { @@ -1072,14 +1133,14 @@ func TestDeleteAtespace_EmptyWhileOtherAtespaceNonEmpty(t *testing.T) { mr, s, ctx := setupTest(t) defer mr.Close() - if err := s.CreateAtespace(ctx, newTestAtespace("team-a")); err != nil { + if _, err := s.CreateAtespace(ctx, newTestAtespace("team-a")); err != nil { t.Fatalf("CreateAtespace(team-a) failed: %v", err) } - if err := s.CreateAtespace(ctx, newTestAtespace("team-b")); err != nil { + if _, err := s.CreateAtespace(ctx, newTestAtespace("team-b")); err != nil { t.Fatalf("CreateAtespace(team-b) failed: %v", err) } // Actor lives ONLY in team-b. - if err := s.CreateActor(ctx, &ateapipb.Actor{ActorId: "id1", Atespace: "team-b", Status: ateapipb.Actor_STATUS_SUSPENDED}); err != nil { + if _, err := s.CreateActor(ctx, &ateapipb.Actor{Metadata: &ateapipb.ResourceMetadata{Name: "id1", Atespace: "team-b"}, Status: ateapipb.Actor_STATUS_SUSPENDED}); err != nil { t.Fatalf("CreateActor failed: %v", err) } diff --git a/cmd/ateapi/internal/store/store.go b/cmd/ateapi/internal/store/store.go index 5de4bdc30..70eb49cbe 100644 --- a/cmd/ateapi/internal/store/store.go +++ b/cmd/ateapi/internal/store/store.go @@ -39,24 +39,30 @@ var ( // Interface defines the contract for the persistence layer storing actor state. type Interface interface { - // Fetches an actor by (atespace, id). Returns ErrNotFound if missing. - GetActor(ctx context.Context, atespace, id string) (*ateapipb.Actor, error) + // Fetches an actor by (atespace, name). Returns ErrNotFound if missing. + GetActor(ctx context.Context, atespace, name string) (*ateapipb.Actor, error) - // Stores a new actor in suspended state. Returns ErrAlreadyExists if key is taken. - CreateActor(ctx context.Context, actor *ateapipb.Actor) error + // Stores a new actor in suspended state and returns the stored resource with + // server-assigned metadata (uid, version, timestamps). The input is not + // mutated. Returns ErrAlreadyExists if key is taken. + CreateActor(ctx context.Context, actor *ateapipb.Actor) (*ateapipb.Actor, error) - // Updates actor state with optimistic concurrency check. Returns ErrNotFound if missing, or ErrPersistenceRetry on version mismatch. - UpdateActor(ctx context.Context, actor *ateapipb.Actor, expectedVersion int64) error + // Updates actor state with optimistic concurrency check and returns the stored + // resource with advanced metadata (version, update_time). The input is not + // mutated. Returns ErrNotFound if missing, or ErrPersistenceRetry on version mismatch. + UpdateActor(ctx context.Context, actor *ateapipb.Actor, expectedVersion int64) (*ateapipb.Actor, error) // Removes an actor. Returns ErrNotFound if missing, or ErrFailedPrecondition if not suspended. - DeleteActor(ctx context.Context, atespace, id string) error + DeleteActor(ctx context.Context, atespace, name string) error // Lists actors in the given atespace (scoped scan), or across ALL atespaces if atespace is // empty. Returns a page of actors and a next page token. ListActors(ctx context.Context, atespace string, pageSize int32, pageToken string) ([]*ateapipb.Actor, string, error) - // Stores a new atespace. Returns ErrAlreadyExists if the name is taken. - CreateAtespace(ctx context.Context, atespace *ateapipb.Atespace) error + // Stores a new atespace and returns the stored resource with server-assigned + // metadata (uid, version, timestamps). The input is not mutated. Returns + // ErrAlreadyExists if the name is taken. + CreateAtespace(ctx context.Context, atespace *ateapipb.Atespace) (*ateapipb.Atespace, error) // Fetches an atespace by name. Returns ErrNotFound if missing. GetAtespace(ctx context.Context, name string) (*ateapipb.Atespace, error) diff --git a/cmd/atenet/internal/router/resumer_test.go b/cmd/atenet/internal/router/resumer_test.go index 061023d58..5a73438fb 100644 --- a/cmd/atenet/internal/router/resumer_test.go +++ b/cmd/atenet/internal/router/resumer_test.go @@ -50,7 +50,7 @@ func TestActorResumer_ResumeActor(t *testing.T) { resumeCalled++ return &ateapipb.ResumeActorResponse{ Actor: &ateapipb.Actor{ - ActorId: testActorID, + Metadata: &ateapipb.ResourceMetadata{Name: testActorID}, Status: ateapipb.Actor_STATUS_RUNNING, AteomPodIp: expectedIP, }, @@ -81,7 +81,7 @@ func TestActorResumer_ResumeActor(t *testing.T) { } return &ateapipb.ResumeActorResponse{ Actor: &ateapipb.Actor{ - ActorId: testActorID, + Metadata: &ateapipb.ResourceMetadata{Name: testActorID}, Status: ateapipb.Actor_STATUS_RUNNING, AteomPodIp: expectedIP, }, @@ -128,7 +128,7 @@ func TestActorResumer_ResumeActor(t *testing.T) { time.Sleep(20 * time.Millisecond) return &ateapipb.ResumeActorResponse{ Actor: &ateapipb.Actor{ - ActorId: testActorID, + Metadata: &ateapipb.ResourceMetadata{Name: testActorID}, Status: ateapipb.Actor_STATUS_RUNNING, AteomPodIp: expectedIP, }, diff --git a/cmd/kubectl-ate/internal/cmd/logs_actors_test.go b/cmd/kubectl-ate/internal/cmd/logs_actors_test.go index e7ec18de3..9e4c94444 100644 --- a/cmd/kubectl-ate/internal/cmd/logs_actors_test.go +++ b/cmd/kubectl-ate/internal/cmd/logs_actors_test.go @@ -192,7 +192,7 @@ func TestLogsActorRunner_Run_OneShotSuccess(t *testing.T) { } return &ateapipb.GetActorResponse{ Actor: &ateapipb.Actor{ - ActorId: actorID, + Metadata: &ateapipb.ResourceMetadata{Name: actorID}, AteomPodName: podName, AteomPodNamespace: namespace, Status: ateapipb.Actor_STATUS_RUNNING, @@ -246,8 +246,8 @@ func TestLogsActorRunner_Run_OneShot_ActorNotRunning(t *testing.T) { GetActorFunc: func(ctx context.Context, in *ateapipb.GetActorRequest, opts ...grpc.CallOption) (*ateapipb.GetActorResponse, error) { return &ateapipb.GetActorResponse{ Actor: &ateapipb.Actor{ - ActorId: actorID, - Status: ateapipb.Actor_STATUS_SUSPENDED, // not running + Metadata: &ateapipb.ResourceMetadata{Name: actorID}, + Status: ateapipb.Actor_STATUS_SUSPENDED, // not running }, }, nil }, @@ -301,8 +301,8 @@ func TestLogsActorRunner_Run_Follow_SuspendedToRunning(t *testing.T) { // First call: suspended return &ateapipb.GetActorResponse{ Actor: &ateapipb.Actor{ - ActorId: actorID, - Status: ateapipb.Actor_STATUS_SUSPENDED, + Metadata: &ateapipb.ResourceMetadata{Name: actorID}, + Status: ateapipb.Actor_STATUS_SUSPENDED, }, }, nil } @@ -310,7 +310,7 @@ func TestLogsActorRunner_Run_Follow_SuspendedToRunning(t *testing.T) { // Subsequent calls: running return &ateapipb.GetActorResponse{ Actor: &ateapipb.Actor{ - ActorId: actorID, + Metadata: &ateapipb.ResourceMetadata{Name: actorID}, AteomPodName: podName, AteomPodNamespace: namespace, Status: ateapipb.Actor_STATUS_RUNNING, @@ -437,7 +437,7 @@ func TestLogsActorRunner_Run_Follow_ActorMigration(t *testing.T) { // 1. Initial call for stream 1: pod-1 return &ateapipb.GetActorResponse{ Actor: &ateapipb.Actor{ - ActorId: actorID, + Metadata: &ateapipb.ResourceMetadata{Name: actorID}, AteomPodName: "pod-1", AteomPodNamespace: "ns", Status: ateapipb.Actor_STATUS_RUNNING, @@ -455,7 +455,7 @@ func TestLogsActorRunner_Run_Follow_ActorMigration(t *testing.T) { return &ateapipb.GetActorResponse{ Actor: &ateapipb.Actor{ - ActorId: actorID, + Metadata: &ateapipb.ResourceMetadata{Name: actorID}, AteomPodName: "pod-2", AteomPodNamespace: "ns", Status: ateapipb.Actor_STATUS_RUNNING, @@ -550,7 +550,7 @@ func TestLogsActorRunner_Run_Follow_ActorSuspendedMidStream(t *testing.T) { if getActorCalls == 1 { return &ateapipb.GetActorResponse{ Actor: &ateapipb.Actor{ - ActorId: actorID, + Metadata: &ateapipb.ResourceMetadata{Name: actorID}, AteomPodName: "pod-1", AteomPodNamespace: "ns", Status: ateapipb.Actor_STATUS_RUNNING, @@ -568,8 +568,8 @@ func TestLogsActorRunner_Run_Follow_ActorSuspendedMidStream(t *testing.T) { } return &ateapipb.GetActorResponse{ Actor: &ateapipb.Actor{ - ActorId: actorID, - Status: ateapipb.Actor_STATUS_SUSPENDED, + Metadata: &ateapipb.ResourceMetadata{Name: actorID}, + Status: ateapipb.Actor_STATUS_SUSPENDED, }, }, nil } @@ -578,8 +578,8 @@ func TestLogsActorRunner_Run_Follow_ActorSuspendedMidStream(t *testing.T) { if getActorCalls == 3 { return &ateapipb.GetActorResponse{ Actor: &ateapipb.Actor{ - ActorId: actorID, - Status: ateapipb.Actor_STATUS_SUSPENDED, + Metadata: &ateapipb.ResourceMetadata{Name: actorID}, + Status: ateapipb.Actor_STATUS_SUSPENDED, }, }, nil } @@ -587,7 +587,7 @@ func TestLogsActorRunner_Run_Follow_ActorSuspendedMidStream(t *testing.T) { // 4. Subsequent loop reconnection call: running again on pod-1 return &ateapipb.GetActorResponse{ Actor: &ateapipb.Actor{ - ActorId: actorID, + Metadata: &ateapipb.ResourceMetadata{Name: actorID}, AteomPodName: "pod-1", AteomPodNamespace: "ns", Status: ateapipb.Actor_STATUS_RUNNING, diff --git a/cmd/kubectl-ate/internal/printer/printer.go b/cmd/kubectl-ate/internal/printer/printer.go index 3cb330a52..a276c2135 100644 --- a/cmd/kubectl-ate/internal/printer/printer.go +++ b/cmd/kubectl-ate/internal/printer/printer.go @@ -36,7 +36,7 @@ func PrintActors(actors []*ateapipb.Actor, format string) error { func sortActors(actors []*ateapipb.Actor) { slices.SortFunc(actors, func(a, b *ateapipb.Actor) int { - if c := cmp.Compare(a.GetAtespace(), b.GetAtespace()); c != 0 { + if c := cmp.Compare(a.GetMetadata().GetAtespace(), b.GetMetadata().GetAtespace()); c != 0 { return c } if c := cmp.Compare(a.GetActorTemplateNamespace(), b.GetActorTemplateNamespace()); c != 0 { @@ -45,7 +45,7 @@ func sortActors(actors []*ateapipb.Actor) { if c := cmp.Compare(a.GetActorTemplateName(), b.GetActorTemplateName()); c != 0 { return c } - return cmp.Compare(a.GetActorId(), b.GetActorId()) + return cmp.Compare(a.GetMetadata().GetName(), b.GetMetadata().GetName()) }) } @@ -59,10 +59,10 @@ func PrintActorsTo(out io.Writer, actors []*ateapipb.Actor, format string) error w := tabwriter.NewWriter(out, 0, 0, 3, ' ', 0) fmt.Fprintln(w, "ATESPACE\tTEMPLATE NS\tTEMPLATE\tID\tSTATUS\tATEOM POD\tATEOM IP\tVERSION") for _, actor := range actors { - atespace := actor.GetAtespace() + atespace := actor.GetMetadata().GetAtespace() ns := actor.GetActorTemplateNamespace() tmpl := actor.GetActorTemplateName() - id := actor.GetActorId() + id := actor.GetMetadata().GetName() status := actor.GetStatus().String() worker := "" @@ -70,7 +70,7 @@ func PrintActorsTo(out io.Writer, actors []*ateapipb.Actor, format string) error worker = actor.GetAteomPodNamespace() + "/" + actor.GetAteomPodName() } - version := actor.GetVersion() + version := actor.GetMetadata().GetVersion() fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%d\n", atespace, ns, tmpl, id, status, worker, actor.GetAteomPodIp(), version) } return w.Flush() @@ -138,7 +138,7 @@ func PrintAtespaces(atespaces []*ateapipb.Atespace, format string) error { func sortAtespaces(atespaces []*ateapipb.Atespace) { slices.SortFunc(atespaces, func(a, b *ateapipb.Atespace) int { - return cmp.Compare(a.GetName(), b.GetName()) + return cmp.Compare(a.GetMetadata().GetName(), b.GetMetadata().GetName()) }) } @@ -152,7 +152,7 @@ func PrintAtespacesTo(out io.Writer, atespaces []*ateapipb.Atespace, format stri w := tabwriter.NewWriter(out, 0, 0, 3, ' ', 0) fmt.Fprintln(w, "NAME") for _, a := range atespaces { - fmt.Fprintf(w, "%s\n", a.GetName()) + fmt.Fprintf(w, "%s\n", a.GetMetadata().GetName()) } return w.Flush() default: diff --git a/cmd/kubectl-ate/internal/printer/printer_test.go b/cmd/kubectl-ate/internal/printer/printer_test.go index ba859017a..05220270f 100644 --- a/cmd/kubectl-ate/internal/printer/printer_test.go +++ b/cmd/kubectl-ate/internal/printer/printer_test.go @@ -26,12 +26,10 @@ func TestPrintActorsTo_Table(t *testing.T) { var buf bytes.Buffer actors := []*ateapipb.Actor{ { - ActorId: "id-1", - Atespace: "team-a", + Metadata: &ateapipb.ResourceMetadata{Name: "id-1", Atespace: "team-a", Version: 2}, ActorTemplateNamespace: "default", ActorTemplateName: "template-1", Status: ateapipb.Actor_STATUS_RUNNING, - Version: 2, AteomPodNamespace: "worker-ns", AteomPodName: "pod-1", AteomPodIp: "1.2.3.4", @@ -55,8 +53,7 @@ func TestPrintActorsTo_JSON(t *testing.T) { var buf bytes.Buffer actors := []*ateapipb.Actor{ { - ActorId: "id-1", - Version: 2, + Metadata: &ateapipb.ResourceMetadata{Name: "id-1", Version: 2}, }, } @@ -68,8 +65,10 @@ func TestPrintActorsTo_JSON(t *testing.T) { expected := `{ "actors": [ { - "actorId": "id-1", - "version": "2" + "metadata": { + "name": "id-1", + "version": "2" + } } ] } @@ -83,8 +82,7 @@ func TestPrintActorsTo_YAML(t *testing.T) { var buf bytes.Buffer actors := []*ateapipb.Actor{ { - ActorId: "id-1", - Version: 2, + Metadata: &ateapipb.ResourceMetadata{Name: "id-1", Version: 2}, }, } @@ -94,8 +92,9 @@ func TestPrintActorsTo_YAML(t *testing.T) { output := buf.String() expected := `actors: -- actorId: id-1 - version: "2" +- metadata: + name: id-1 + version: "2" ` if diff := cmp.Diff(expected, output); diff != "" { t.Errorf("output mismatch (-want +got):\n%s", diff) @@ -106,22 +105,19 @@ func TestPrintActorsTo_Table_Sorted(t *testing.T) { var buf bytes.Buffer actors := []*ateapipb.Actor{ { - ActorId: "zebra", - Atespace: "team-b", + Metadata: &ateapipb.ResourceMetadata{Name: "zebra", Atespace: "team-b"}, ActorTemplateNamespace: "default", ActorTemplateName: "template-1", Status: ateapipb.Actor_STATUS_SUSPENDED, }, { - ActorId: "alpha", - Atespace: "team-a", + Metadata: &ateapipb.ResourceMetadata{Name: "alpha", Atespace: "team-a"}, ActorTemplateNamespace: "default", ActorTemplateName: "template-1", Status: ateapipb.Actor_STATUS_RUNNING, }, { - ActorId: "beta", - Atespace: "team-a", + Metadata: &ateapipb.ResourceMetadata{Name: "beta", Atespace: "team-a"}, ActorTemplateNamespace: "other", ActorTemplateName: "template-2", Status: ateapipb.Actor_STATUS_SUSPENDED, @@ -251,7 +247,7 @@ func TestPrintWorkersTo_Invalid(t *testing.T) { func TestPrintAtespacesTo_Table(t *testing.T) { var buf bytes.Buffer atespaces := []*ateapipb.Atespace{ - {Name: "team-a"}, + {Metadata: &ateapipb.ResourceMetadata{Name: "team-a"}}, } if err := PrintAtespacesTo(&buf, atespaces, "table"); err != nil { @@ -269,7 +265,7 @@ team-a func TestPrintAtespacesTo_JSON(t *testing.T) { var buf bytes.Buffer atespaces := []*ateapipb.Atespace{ - {Name: "team-a"}, + {Metadata: &ateapipb.ResourceMetadata{Name: "team-a"}}, } if err := PrintAtespacesTo(&buf, atespaces, "json"); err != nil { @@ -279,7 +275,9 @@ func TestPrintAtespacesTo_JSON(t *testing.T) { expected := `{ "atespaces": [ { - "name": "team-a" + "metadata": { + "name": "team-a" + } } ] } @@ -292,7 +290,7 @@ func TestPrintAtespacesTo_JSON(t *testing.T) { func TestPrintAtespacesTo_YAML(t *testing.T) { var buf bytes.Buffer atespaces := []*ateapipb.Atespace{ - {Name: "team-a"}, + {Metadata: &ateapipb.ResourceMetadata{Name: "team-a"}}, } if err := PrintAtespacesTo(&buf, atespaces, "yaml"); err != nil { @@ -300,7 +298,8 @@ func TestPrintAtespacesTo_YAML(t *testing.T) { } expected := `atespaces: -- name: team-a +- metadata: + name: team-a ` if diff := cmp.Diff(expected, buf.String()); diff != "" { t.Errorf("output mismatch (-want +got):\n%s", diff) @@ -310,9 +309,9 @@ func TestPrintAtespacesTo_YAML(t *testing.T) { func TestPrintAtespacesTo_Table_Sorted(t *testing.T) { var buf bytes.Buffer atespaces := []*ateapipb.Atespace{ - {Name: "team-c"}, - {Name: "team-a"}, - {Name: "team-b"}, + {Metadata: &ateapipb.ResourceMetadata{Name: "team-c"}}, + {Metadata: &ateapipb.ResourceMetadata{Name: "team-a"}}, + {Metadata: &ateapipb.ResourceMetadata{Name: "team-b"}}, } if err := PrintAtespacesTo(&buf, atespaces, "table"); err != nil { diff --git a/demos/claude-code-multiplex/ui/server.go b/demos/claude-code-multiplex/ui/server.go index 9e01a66d3..0164e4246 100644 --- a/demos/claude-code-multiplex/ui/server.go +++ b/demos/claude-code-multiplex/ui/server.go @@ -245,7 +245,7 @@ func listActorNames(ctx context.Context) []string { } names := make([]string, 0, len(resp.GetActors())) for _, a := range resp.GetActors() { - if id := a.GetActorId(); id != "" { + if id := a.GetMetadata().GetName(); id != "" { names = append(names, id) } } @@ -431,7 +431,7 @@ func handleActors(w http.ResponseWriter, r *http.Request) { } actors = append(actors, actorSummary{ Kind: "Actor", - Name: a.GetActorId(), + Name: a.GetMetadata().GetName(), Phase: actorStatusString(a.GetStatus()), Message: msg, }) diff --git a/internal/e2e/suites/demo/demo_test.go b/internal/e2e/suites/demo/demo_test.go index 32f079fc3..d4089a8b4 100644 --- a/internal/e2e/suites/demo/demo_test.go +++ b/internal/e2e/suites/demo/demo_test.go @@ -164,7 +164,7 @@ func TestDurableDirLifecycle(t *testing.T) { if err != nil { t.Fatalf("failed to create Actor: %v", err) } - t.Logf("Successfully created Actor: %s", createResp.GetActor().GetActorId()) + t.Logf("Successfully created Actor: %s", createResp.GetActor().GetMetadata().GetName()) defer func() { clients.SubstrateAPI.DeleteActor(ctx, &ateapipb.DeleteActorRequest{ ActorRef: &ateapipb.ActorRef{Atespace: demoAtespace, Name: actorID}, @@ -266,7 +266,7 @@ func createActor(ctx context.Context, t *testing.T, clients *e2e.Clients, nsObj if err != nil { t.Fatalf("failed to create Actor: %v", err) } - t.Logf("Successfully created Actor: %s", createResp.GetActor().GetActorId()) + t.Logf("Successfully created Actor: %s", createResp.GetActor().GetMetadata().GetName()) defer func() { clients.SubstrateAPI.DeleteActor(ctx, &ateapipb.DeleteActorRequest{ ActorRef: &ateapipb.ActorRef{Atespace: demoAtespace, Name: actorID}, @@ -280,7 +280,7 @@ func createActor(ctx context.Context, t *testing.T, clients *e2e.Clients, nsObj var myActors []*ateapipb.Actor for _, actor := range listResp.GetActors() { - if actor.GetActorTemplateNamespace() == nsObj.Name && actor.GetActorId() == actorID { + if actor.GetActorTemplateNamespace() == nsObj.Name && actor.GetMetadata().GetName() == actorID { myActors = append(myActors, actor) } } @@ -291,8 +291,8 @@ func createActor(ctx context.Context, t *testing.T, clients *e2e.Clients, nsObj } actor := myActors[0] - if actor.GetActorId() != actorID { - t.Errorf("expected actor ID %s, got %s", actorID, actor.GetActorId()) + if actor.GetMetadata().GetName() != actorID { + t.Errorf("expected actor ID %s, got %s", actorID, actor.GetMetadata().GetName()) } if actor.GetActorTemplateName() != at.Name { t.Errorf("expected actor template name %s, got %s", at.Name, actor.GetActorTemplateName()) diff --git a/pkg/proto/ateapipb/ateapi.pb.go b/pkg/proto/ateapipb/ateapi.pb.go index 1406adf5b..cb5707881 100644 --- a/pkg/proto/ateapipb/ateapi.pb.go +++ b/pkg/proto/ateapipb/ateapi.pb.go @@ -25,6 +25,7 @@ package ateapipb import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" unsafe "unsafe" @@ -98,7 +99,7 @@ func (x Actor_Status) Number() protoreflect.EnumNumber { // Deprecated: Use Actor_Status.Descriptor instead. func (Actor_Status) EnumDescriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{4, 0} + return file_ateapi_proto_rawDescGZIP(), []int{5, 0} } type ExternalSnapshotInfo struct { @@ -326,41 +327,132 @@ func (x *Selector) GetMatchLabels() map[string]string { return nil } +// ResourceMetadata holds the common fields carried by every Substrate resource. +type ResourceMetadata struct { + state protoimpl.MessageState `protogen:"open.v1"` + // atespace is the namespace the resource belongs to. Empty for global-scoped + // resources. Caller-specified at creation and immutable thereafter. + Atespace string `protobuf:"bytes,1,opt,name=atespace,proto3" json:"atespace,omitempty"` + // name is the resource's name, unique within its atespace (or globally, for + // global-scoped resources). Caller-specified at creation and immutable thereafter. + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + // uid is a server-assigned, globally unique identifier for this resource. + // Immutable throughout the lifecycle of the resource. + Uid string `protobuf:"bytes,3,opt,name=uid,proto3" json:"uid,omitempty"` + // version is increased on every mutation. + Version int64 `protobuf:"varint,4,opt,name=version,proto3" json:"version,omitempty"` + // create_time is the time the resource was created. + CreateTime *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty"` + // update_time is the time the resource was last updated. + UpdateTime *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceMetadata) Reset() { + *x = ResourceMetadata{} + mi := &file_ateapi_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceMetadata) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceMetadata) ProtoMessage() {} + +func (x *ResourceMetadata) ProtoReflect() protoreflect.Message { + mi := &file_ateapi_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResourceMetadata.ProtoReflect.Descriptor instead. +func (*ResourceMetadata) Descriptor() ([]byte, []int) { + return file_ateapi_proto_rawDescGZIP(), []int{4} +} + +func (x *ResourceMetadata) GetAtespace() string { + if x != nil { + return x.Atespace + } + return "" +} + +func (x *ResourceMetadata) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ResourceMetadata) GetUid() string { + if x != nil { + return x.Uid + } + return "" +} + +func (x *ResourceMetadata) GetVersion() int64 { + if x != nil { + return x.Version + } + return 0 +} + +func (x *ResourceMetadata) GetCreateTime() *timestamppb.Timestamp { + if x != nil { + return x.CreateTime + } + return nil +} + +func (x *ResourceMetadata) GetUpdateTime() *timestamppb.Timestamp { + if x != nil { + return x.UpdateTime + } + return nil +} + type Actor struct { - state protoimpl.MessageState `protogen:"open.v1"` - ActorId string `protobuf:"bytes,1,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"` - Version int64 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` - ActorTemplateNamespace string `protobuf:"bytes,3,opt,name=actor_template_namespace,json=actorTemplateNamespace,proto3" json:"actor_template_namespace,omitempty"` - ActorTemplateName string `protobuf:"bytes,4,opt,name=actor_template_name,json=actorTemplateName,proto3" json:"actor_template_name,omitempty"` - Status Actor_Status `protobuf:"varint,5,opt,name=status,proto3,enum=ateapi.Actor_Status" json:"status,omitempty"` - AteomPodNamespace string `protobuf:"bytes,6,opt,name=ateom_pod_namespace,json=ateomPodNamespace,proto3" json:"ateom_pod_namespace,omitempty"` - AteomPodName string `protobuf:"bytes,7,opt,name=ateom_pod_name,json=ateomPodName,proto3" json:"ateom_pod_name,omitempty"` - AteomPodIp string `protobuf:"bytes,8,opt,name=ateom_pod_ip,json=ateomPodIp,proto3" json:"ateom_pod_ip,omitempty"` - InProgressSnapshot string `protobuf:"bytes,10,opt,name=in_progress_snapshot,json=inProgressSnapshot,proto3" json:"in_progress_snapshot,omitempty"` - AteomPodUid string `protobuf:"bytes,11,opt,name=ateom_pod_uid,json=ateomPodUid,proto3" json:"ateom_pod_uid,omitempty"` - LatestSnapshotInfo *SnapshotInfo `protobuf:"bytes,12,opt,name=latest_snapshot_info,json=latestSnapshotInfo,proto3" json:"latest_snapshot_info,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // Common resource metadata: atespace, name, uid, version, timestamps. + Metadata *ResourceMetadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` + ActorTemplateNamespace string `protobuf:"bytes,2,opt,name=actor_template_namespace,json=actorTemplateNamespace,proto3" json:"actor_template_namespace,omitempty"` + ActorTemplateName string `protobuf:"bytes,3,opt,name=actor_template_name,json=actorTemplateName,proto3" json:"actor_template_name,omitempty"` + Status Actor_Status `protobuf:"varint,4,opt,name=status,proto3,enum=ateapi.Actor_Status" json:"status,omitempty"` + AteomPodNamespace string `protobuf:"bytes,5,opt,name=ateom_pod_namespace,json=ateomPodNamespace,proto3" json:"ateom_pod_namespace,omitempty"` + AteomPodName string `protobuf:"bytes,6,opt,name=ateom_pod_name,json=ateomPodName,proto3" json:"ateom_pod_name,omitempty"` + AteomPodIp string `protobuf:"bytes,7,opt,name=ateom_pod_ip,json=ateomPodIp,proto3" json:"ateom_pod_ip,omitempty"` + InProgressSnapshot string `protobuf:"bytes,8,opt,name=in_progress_snapshot,json=inProgressSnapshot,proto3" json:"in_progress_snapshot,omitempty"` + AteomPodUid string `protobuf:"bytes,9,opt,name=ateom_pod_uid,json=ateomPodUid,proto3" json:"ateom_pod_uid,omitempty"` + LatestSnapshotInfo *SnapshotInfo `protobuf:"bytes,10,opt,name=latest_snapshot_info,json=latestSnapshotInfo,proto3" json:"latest_snapshot_info,omitempty"` // worker_selector is the per-actor placement constraint. The scheduler // evaluates the AND of this selector and the template's workerSelector to // find eligible pools. Set at CreateActor; may be updated at any time via // UpdateActor. Changes take effect on the next ResumeActor call. - WorkerSelector *Selector `protobuf:"bytes,13,opt,name=worker_selector,json=workerSelector,proto3" json:"worker_selector,omitempty"` + WorkerSelector *Selector `protobuf:"bytes,11,opt,name=worker_selector,json=workerSelector,proto3" json:"worker_selector,omitempty"` // worker_pool_name is the name of the WorkerPool that owns the currently // assigned worker, in the same namespace as ateom_pod_namespace (pool and // pod namespaces always match). Set by the scheduler at assignment time // and cleared when the worker is freed. Needed to release the worker on // suspend/pause since eligibility is no longer a single fixed pool // reference on the ActorTemplate. - WorkerPoolName string `protobuf:"bytes,14,opt,name=worker_pool_name,json=workerPoolName,proto3" json:"worker_pool_name,omitempty"` - // The atespace this actor belongs to. Part of the actor's - // resource identity; folded into the Redis key as actor::. - Atespace string `protobuf:"bytes,15,opt,name=atespace,proto3" json:"atespace,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + WorkerPoolName string `protobuf:"bytes,12,opt,name=worker_pool_name,json=workerPoolName,proto3" json:"worker_pool_name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Actor) Reset() { *x = Actor{} - mi := &file_ateapi_proto_msgTypes[4] + mi := &file_ateapi_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -372,7 +464,7 @@ func (x *Actor) String() string { func (*Actor) ProtoMessage() {} func (x *Actor) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[4] + mi := &file_ateapi_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -385,21 +477,14 @@ func (x *Actor) ProtoReflect() protoreflect.Message { // Deprecated: Use Actor.ProtoReflect.Descriptor instead. func (*Actor) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{4} -} - -func (x *Actor) GetActorId() string { - if x != nil { - return x.ActorId - } - return "" + return file_ateapi_proto_rawDescGZIP(), []int{5} } -func (x *Actor) GetVersion() int64 { +func (x *Actor) GetMetadata() *ResourceMetadata { if x != nil { - return x.Version + return x.Metadata } - return 0 + return nil } func (x *Actor) GetActorTemplateNamespace() string { @@ -479,24 +564,19 @@ func (x *Actor) GetWorkerPoolName() string { return "" } -func (x *Actor) GetAtespace() string { - if x != nil { - return x.Atespace - } - return "" -} - -// Atespace is the isolation boundary an Actor is created into. +// Atespace is the isolation boundary an Actor is created into. Global-scoped: +// metadata.atespace is always empty; the atespace's identity is metadata.name. type Atespace struct { - state protoimpl.MessageState `protogen:"open.v1"` - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // Common resource metadata: name, uid, version, timestamps. + Metadata *ResourceMetadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *Atespace) Reset() { *x = Atespace{} - mi := &file_ateapi_proto_msgTypes[5] + mi := &file_ateapi_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -508,7 +588,7 @@ func (x *Atespace) String() string { func (*Atespace) ProtoMessage() {} func (x *Atespace) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[5] + mi := &file_ateapi_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -521,14 +601,14 @@ func (x *Atespace) ProtoReflect() protoreflect.Message { // Deprecated: Use Atespace.ProtoReflect.Descriptor instead. func (*Atespace) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{5} + return file_ateapi_proto_rawDescGZIP(), []int{6} } -func (x *Atespace) GetName() string { +func (x *Atespace) GetMetadata() *ResourceMetadata { if x != nil { - return x.Name + return x.Metadata } - return "" + return nil } // ActorRef identifies an actor: a name is only unique within its atespace. @@ -542,7 +622,7 @@ type ActorRef struct { func (x *ActorRef) Reset() { *x = ActorRef{} - mi := &file_ateapi_proto_msgTypes[6] + mi := &file_ateapi_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -554,7 +634,7 @@ func (x *ActorRef) String() string { func (*ActorRef) ProtoMessage() {} func (x *ActorRef) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[6] + mi := &file_ateapi_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -567,7 +647,7 @@ func (x *ActorRef) ProtoReflect() protoreflect.Message { // Deprecated: Use ActorRef.ProtoReflect.Descriptor instead. func (*ActorRef) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{6} + return file_ateapi_proto_rawDescGZIP(), []int{7} } func (x *ActorRef) GetAtespace() string { @@ -593,7 +673,7 @@ type CreateAtespaceRequest struct { func (x *CreateAtespaceRequest) Reset() { *x = CreateAtespaceRequest{} - mi := &file_ateapi_proto_msgTypes[7] + mi := &file_ateapi_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -605,7 +685,7 @@ func (x *CreateAtespaceRequest) String() string { func (*CreateAtespaceRequest) ProtoMessage() {} func (x *CreateAtespaceRequest) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[7] + mi := &file_ateapi_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -618,7 +698,7 @@ func (x *CreateAtespaceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateAtespaceRequest.ProtoReflect.Descriptor instead. func (*CreateAtespaceRequest) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{7} + return file_ateapi_proto_rawDescGZIP(), []int{8} } func (x *CreateAtespaceRequest) GetName() string { @@ -637,7 +717,7 @@ type CreateAtespaceResponse struct { func (x *CreateAtespaceResponse) Reset() { *x = CreateAtespaceResponse{} - mi := &file_ateapi_proto_msgTypes[8] + mi := &file_ateapi_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -649,7 +729,7 @@ func (x *CreateAtespaceResponse) String() string { func (*CreateAtespaceResponse) ProtoMessage() {} func (x *CreateAtespaceResponse) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[8] + mi := &file_ateapi_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -662,7 +742,7 @@ func (x *CreateAtespaceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateAtespaceResponse.ProtoReflect.Descriptor instead. func (*CreateAtespaceResponse) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{8} + return file_ateapi_proto_rawDescGZIP(), []int{9} } func (x *CreateAtespaceResponse) GetAtespace() *Atespace { @@ -681,7 +761,7 @@ type GetAtespaceRequest struct { func (x *GetAtespaceRequest) Reset() { *x = GetAtespaceRequest{} - mi := &file_ateapi_proto_msgTypes[9] + mi := &file_ateapi_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -693,7 +773,7 @@ func (x *GetAtespaceRequest) String() string { func (*GetAtespaceRequest) ProtoMessage() {} func (x *GetAtespaceRequest) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[9] + mi := &file_ateapi_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -706,7 +786,7 @@ func (x *GetAtespaceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAtespaceRequest.ProtoReflect.Descriptor instead. func (*GetAtespaceRequest) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{9} + return file_ateapi_proto_rawDescGZIP(), []int{10} } func (x *GetAtespaceRequest) GetName() string { @@ -725,7 +805,7 @@ type GetAtespaceResponse struct { func (x *GetAtespaceResponse) Reset() { *x = GetAtespaceResponse{} - mi := &file_ateapi_proto_msgTypes[10] + mi := &file_ateapi_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -737,7 +817,7 @@ func (x *GetAtespaceResponse) String() string { func (*GetAtespaceResponse) ProtoMessage() {} func (x *GetAtespaceResponse) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[10] + mi := &file_ateapi_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -750,7 +830,7 @@ func (x *GetAtespaceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAtespaceResponse.ProtoReflect.Descriptor instead. func (*GetAtespaceResponse) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{10} + return file_ateapi_proto_rawDescGZIP(), []int{11} } func (x *GetAtespaceResponse) GetAtespace() *Atespace { @@ -768,7 +848,7 @@ type ListAtespacesRequest struct { func (x *ListAtespacesRequest) Reset() { *x = ListAtespacesRequest{} - mi := &file_ateapi_proto_msgTypes[11] + mi := &file_ateapi_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -780,7 +860,7 @@ func (x *ListAtespacesRequest) String() string { func (*ListAtespacesRequest) ProtoMessage() {} func (x *ListAtespacesRequest) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[11] + mi := &file_ateapi_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -793,7 +873,7 @@ func (x *ListAtespacesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAtespacesRequest.ProtoReflect.Descriptor instead. func (*ListAtespacesRequest) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{11} + return file_ateapi_proto_rawDescGZIP(), []int{12} } type ListAtespacesResponse struct { @@ -805,7 +885,7 @@ type ListAtespacesResponse struct { func (x *ListAtespacesResponse) Reset() { *x = ListAtespacesResponse{} - mi := &file_ateapi_proto_msgTypes[12] + mi := &file_ateapi_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -817,7 +897,7 @@ func (x *ListAtespacesResponse) String() string { func (*ListAtespacesResponse) ProtoMessage() {} func (x *ListAtespacesResponse) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[12] + mi := &file_ateapi_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -830,7 +910,7 @@ func (x *ListAtespacesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAtespacesResponse.ProtoReflect.Descriptor instead. func (*ListAtespacesResponse) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{12} + return file_ateapi_proto_rawDescGZIP(), []int{13} } func (x *ListAtespacesResponse) GetAtespaces() []*Atespace { @@ -849,7 +929,7 @@ type DeleteAtespaceRequest struct { func (x *DeleteAtespaceRequest) Reset() { *x = DeleteAtespaceRequest{} - mi := &file_ateapi_proto_msgTypes[13] + mi := &file_ateapi_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -861,7 +941,7 @@ func (x *DeleteAtespaceRequest) String() string { func (*DeleteAtespaceRequest) ProtoMessage() {} func (x *DeleteAtespaceRequest) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[13] + mi := &file_ateapi_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -874,7 +954,7 @@ func (x *DeleteAtespaceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteAtespaceRequest.ProtoReflect.Descriptor instead. func (*DeleteAtespaceRequest) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{13} + return file_ateapi_proto_rawDescGZIP(), []int{14} } func (x *DeleteAtespaceRequest) GetName() string { @@ -892,7 +972,7 @@ type DeleteAtespaceResponse struct { func (x *DeleteAtespaceResponse) Reset() { *x = DeleteAtespaceResponse{} - mi := &file_ateapi_proto_msgTypes[14] + mi := &file_ateapi_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -904,7 +984,7 @@ func (x *DeleteAtespaceResponse) String() string { func (*DeleteAtespaceResponse) ProtoMessage() {} func (x *DeleteAtespaceResponse) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[14] + mi := &file_ateapi_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -917,7 +997,7 @@ func (x *DeleteAtespaceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteAtespaceResponse.ProtoReflect.Descriptor instead. func (*DeleteAtespaceResponse) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{14} + return file_ateapi_proto_rawDescGZIP(), []int{15} } type GetActorRequest struct { @@ -929,7 +1009,7 @@ type GetActorRequest struct { func (x *GetActorRequest) Reset() { *x = GetActorRequest{} - mi := &file_ateapi_proto_msgTypes[15] + mi := &file_ateapi_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -941,7 +1021,7 @@ func (x *GetActorRequest) String() string { func (*GetActorRequest) ProtoMessage() {} func (x *GetActorRequest) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[15] + mi := &file_ateapi_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -954,7 +1034,7 @@ func (x *GetActorRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetActorRequest.ProtoReflect.Descriptor instead. func (*GetActorRequest) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{15} + return file_ateapi_proto_rawDescGZIP(), []int{16} } func (x *GetActorRequest) GetActorRef() *ActorRef { @@ -973,7 +1053,7 @@ type GetActorResponse struct { func (x *GetActorResponse) Reset() { *x = GetActorResponse{} - mi := &file_ateapi_proto_msgTypes[16] + mi := &file_ateapi_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -985,7 +1065,7 @@ func (x *GetActorResponse) String() string { func (*GetActorResponse) ProtoMessage() {} func (x *GetActorResponse) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[16] + mi := &file_ateapi_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -998,7 +1078,7 @@ func (x *GetActorResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetActorResponse.ProtoReflect.Descriptor instead. func (*GetActorResponse) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{16} + return file_ateapi_proto_rawDescGZIP(), []int{17} } func (x *GetActorResponse) GetActor() *Actor { @@ -1026,7 +1106,7 @@ type CreateActorRequest struct { func (x *CreateActorRequest) Reset() { *x = CreateActorRequest{} - mi := &file_ateapi_proto_msgTypes[17] + mi := &file_ateapi_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1038,7 +1118,7 @@ func (x *CreateActorRequest) String() string { func (*CreateActorRequest) ProtoMessage() {} func (x *CreateActorRequest) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[17] + mi := &file_ateapi_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1051,7 +1131,7 @@ func (x *CreateActorRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateActorRequest.ProtoReflect.Descriptor instead. func (*CreateActorRequest) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{17} + return file_ateapi_proto_rawDescGZIP(), []int{18} } func (x *CreateActorRequest) GetActorRef() *ActorRef { @@ -1091,7 +1171,7 @@ type CreateActorResponse struct { func (x *CreateActorResponse) Reset() { *x = CreateActorResponse{} - mi := &file_ateapi_proto_msgTypes[18] + mi := &file_ateapi_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1103,7 +1183,7 @@ func (x *CreateActorResponse) String() string { func (*CreateActorResponse) ProtoMessage() {} func (x *CreateActorResponse) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[18] + mi := &file_ateapi_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1116,7 +1196,7 @@ func (x *CreateActorResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateActorResponse.ProtoReflect.Descriptor instead. func (*CreateActorResponse) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{18} + return file_ateapi_proto_rawDescGZIP(), []int{19} } func (x *CreateActorResponse) GetActor() *Actor { @@ -1141,7 +1221,7 @@ type UpdateActorRequest struct { func (x *UpdateActorRequest) Reset() { *x = UpdateActorRequest{} - mi := &file_ateapi_proto_msgTypes[19] + mi := &file_ateapi_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1153,7 +1233,7 @@ func (x *UpdateActorRequest) String() string { func (*UpdateActorRequest) ProtoMessage() {} func (x *UpdateActorRequest) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[19] + mi := &file_ateapi_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1166,7 +1246,7 @@ func (x *UpdateActorRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateActorRequest.ProtoReflect.Descriptor instead. func (*UpdateActorRequest) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{19} + return file_ateapi_proto_rawDescGZIP(), []int{20} } func (x *UpdateActorRequest) GetActorRef() *ActorRef { @@ -1192,7 +1272,7 @@ type UpdateActorResponse struct { func (x *UpdateActorResponse) Reset() { *x = UpdateActorResponse{} - mi := &file_ateapi_proto_msgTypes[20] + mi := &file_ateapi_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1204,7 +1284,7 @@ func (x *UpdateActorResponse) String() string { func (*UpdateActorResponse) ProtoMessage() {} func (x *UpdateActorResponse) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[20] + mi := &file_ateapi_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1217,7 +1297,7 @@ func (x *UpdateActorResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateActorResponse.ProtoReflect.Descriptor instead. func (*UpdateActorResponse) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{20} + return file_ateapi_proto_rawDescGZIP(), []int{21} } func (x *UpdateActorResponse) GetActor() *Actor { @@ -1236,7 +1316,7 @@ type SuspendActorRequest struct { func (x *SuspendActorRequest) Reset() { *x = SuspendActorRequest{} - mi := &file_ateapi_proto_msgTypes[21] + mi := &file_ateapi_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1248,7 +1328,7 @@ func (x *SuspendActorRequest) String() string { func (*SuspendActorRequest) ProtoMessage() {} func (x *SuspendActorRequest) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[21] + mi := &file_ateapi_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1261,7 +1341,7 @@ func (x *SuspendActorRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SuspendActorRequest.ProtoReflect.Descriptor instead. func (*SuspendActorRequest) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{21} + return file_ateapi_proto_rawDescGZIP(), []int{22} } func (x *SuspendActorRequest) GetActorRef() *ActorRef { @@ -1280,7 +1360,7 @@ type SuspendActorResponse struct { func (x *SuspendActorResponse) Reset() { *x = SuspendActorResponse{} - mi := &file_ateapi_proto_msgTypes[22] + mi := &file_ateapi_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1292,7 +1372,7 @@ func (x *SuspendActorResponse) String() string { func (*SuspendActorResponse) ProtoMessage() {} func (x *SuspendActorResponse) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[22] + mi := &file_ateapi_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1305,7 +1385,7 @@ func (x *SuspendActorResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SuspendActorResponse.ProtoReflect.Descriptor instead. func (*SuspendActorResponse) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{22} + return file_ateapi_proto_rawDescGZIP(), []int{23} } func (x *SuspendActorResponse) GetActor() *Actor { @@ -1324,7 +1404,7 @@ type PauseActorRequest struct { func (x *PauseActorRequest) Reset() { *x = PauseActorRequest{} - mi := &file_ateapi_proto_msgTypes[23] + mi := &file_ateapi_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1336,7 +1416,7 @@ func (x *PauseActorRequest) String() string { func (*PauseActorRequest) ProtoMessage() {} func (x *PauseActorRequest) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[23] + mi := &file_ateapi_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1349,7 +1429,7 @@ func (x *PauseActorRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PauseActorRequest.ProtoReflect.Descriptor instead. func (*PauseActorRequest) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{23} + return file_ateapi_proto_rawDescGZIP(), []int{24} } func (x *PauseActorRequest) GetActorRef() *ActorRef { @@ -1368,7 +1448,7 @@ type PauseActorResponse struct { func (x *PauseActorResponse) Reset() { *x = PauseActorResponse{} - mi := &file_ateapi_proto_msgTypes[24] + mi := &file_ateapi_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1380,7 +1460,7 @@ func (x *PauseActorResponse) String() string { func (*PauseActorResponse) ProtoMessage() {} func (x *PauseActorResponse) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[24] + mi := &file_ateapi_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1393,7 +1473,7 @@ func (x *PauseActorResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PauseActorResponse.ProtoReflect.Descriptor instead. func (*PauseActorResponse) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{24} + return file_ateapi_proto_rawDescGZIP(), []int{25} } func (x *PauseActorResponse) GetActor() *Actor { @@ -1414,7 +1494,7 @@ type ResumeActorRequest struct { func (x *ResumeActorRequest) Reset() { *x = ResumeActorRequest{} - mi := &file_ateapi_proto_msgTypes[25] + mi := &file_ateapi_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1426,7 +1506,7 @@ func (x *ResumeActorRequest) String() string { func (*ResumeActorRequest) ProtoMessage() {} func (x *ResumeActorRequest) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[25] + mi := &file_ateapi_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1439,7 +1519,7 @@ func (x *ResumeActorRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResumeActorRequest.ProtoReflect.Descriptor instead. func (*ResumeActorRequest) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{25} + return file_ateapi_proto_rawDescGZIP(), []int{26} } func (x *ResumeActorRequest) GetActorRef() *ActorRef { @@ -1465,7 +1545,7 @@ type ResumeActorResponse struct { func (x *ResumeActorResponse) Reset() { *x = ResumeActorResponse{} - mi := &file_ateapi_proto_msgTypes[26] + mi := &file_ateapi_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1477,7 +1557,7 @@ func (x *ResumeActorResponse) String() string { func (*ResumeActorResponse) ProtoMessage() {} func (x *ResumeActorResponse) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[26] + mi := &file_ateapi_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1490,7 +1570,7 @@ func (x *ResumeActorResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResumeActorResponse.ProtoReflect.Descriptor instead. func (*ResumeActorResponse) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{26} + return file_ateapi_proto_rawDescGZIP(), []int{27} } func (x *ResumeActorResponse) GetActor() *Actor { @@ -1509,7 +1589,7 @@ type DeleteActorRequest struct { func (x *DeleteActorRequest) Reset() { *x = DeleteActorRequest{} - mi := &file_ateapi_proto_msgTypes[27] + mi := &file_ateapi_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1521,7 +1601,7 @@ func (x *DeleteActorRequest) String() string { func (*DeleteActorRequest) ProtoMessage() {} func (x *DeleteActorRequest) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[27] + mi := &file_ateapi_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1534,7 +1614,7 @@ func (x *DeleteActorRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteActorRequest.ProtoReflect.Descriptor instead. func (*DeleteActorRequest) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{27} + return file_ateapi_proto_rawDescGZIP(), []int{28} } func (x *DeleteActorRequest) GetActorRef() *ActorRef { @@ -1552,7 +1632,7 @@ type DeleteActorResponse struct { func (x *DeleteActorResponse) Reset() { *x = DeleteActorResponse{} - mi := &file_ateapi_proto_msgTypes[28] + mi := &file_ateapi_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1564,7 +1644,7 @@ func (x *DeleteActorResponse) String() string { func (*DeleteActorResponse) ProtoMessage() {} func (x *DeleteActorResponse) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[28] + mi := &file_ateapi_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1577,7 +1657,7 @@ func (x *DeleteActorResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteActorResponse.ProtoReflect.Descriptor instead. func (*DeleteActorResponse) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{28} + return file_ateapi_proto_rawDescGZIP(), []int{29} } type ListWorkersRequest struct { @@ -1588,7 +1668,7 @@ type ListWorkersRequest struct { func (x *ListWorkersRequest) Reset() { *x = ListWorkersRequest{} - mi := &file_ateapi_proto_msgTypes[29] + mi := &file_ateapi_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1600,7 +1680,7 @@ func (x *ListWorkersRequest) String() string { func (*ListWorkersRequest) ProtoMessage() {} func (x *ListWorkersRequest) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[29] + mi := &file_ateapi_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1613,7 +1693,7 @@ func (x *ListWorkersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWorkersRequest.ProtoReflect.Descriptor instead. func (*ListWorkersRequest) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{29} + return file_ateapi_proto_rawDescGZIP(), []int{30} } type ListWorkersResponse struct { @@ -1625,7 +1705,7 @@ type ListWorkersResponse struct { func (x *ListWorkersResponse) Reset() { *x = ListWorkersResponse{} - mi := &file_ateapi_proto_msgTypes[30] + mi := &file_ateapi_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1637,7 +1717,7 @@ func (x *ListWorkersResponse) String() string { func (*ListWorkersResponse) ProtoMessage() {} func (x *ListWorkersResponse) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[30] + mi := &file_ateapi_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1650,7 +1730,7 @@ func (x *ListWorkersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWorkersResponse.ProtoReflect.Descriptor instead. func (*ListWorkersResponse) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{30} + return file_ateapi_proto_rawDescGZIP(), []int{31} } func (x *ListWorkersResponse) GetWorkers() []*Worker { @@ -1679,7 +1759,7 @@ type ListActorsRequest struct { func (x *ListActorsRequest) Reset() { *x = ListActorsRequest{} - mi := &file_ateapi_proto_msgTypes[31] + mi := &file_ateapi_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1691,7 +1771,7 @@ func (x *ListActorsRequest) String() string { func (*ListActorsRequest) ProtoMessage() {} func (x *ListActorsRequest) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[31] + mi := &file_ateapi_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1704,7 +1784,7 @@ func (x *ListActorsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListActorsRequest.ProtoReflect.Descriptor instead. func (*ListActorsRequest) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{31} + return file_ateapi_proto_rawDescGZIP(), []int{32} } func (x *ListActorsRequest) GetPageSize() int32 { @@ -1742,7 +1822,7 @@ type ListActorsResponse struct { func (x *ListActorsResponse) Reset() { *x = ListActorsResponse{} - mi := &file_ateapi_proto_msgTypes[32] + mi := &file_ateapi_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1754,7 +1834,7 @@ func (x *ListActorsResponse) String() string { func (*ListActorsResponse) ProtoMessage() {} func (x *ListActorsResponse) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[32] + mi := &file_ateapi_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1767,7 +1847,7 @@ func (x *ListActorsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListActorsResponse.ProtoReflect.Descriptor instead. func (*ListActorsResponse) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{32} + return file_ateapi_proto_rawDescGZIP(), []int{33} } func (x *ListActorsResponse) GetActors() []*Actor { @@ -1802,7 +1882,7 @@ type Worker struct { func (x *Worker) Reset() { *x = Worker{} - mi := &file_ateapi_proto_msgTypes[33] + mi := &file_ateapi_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1814,7 +1894,7 @@ func (x *Worker) String() string { func (*Worker) ProtoMessage() {} func (x *Worker) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[33] + mi := &file_ateapi_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1827,7 +1907,7 @@ func (x *Worker) ProtoReflect() protoreflect.Message { // Deprecated: Use Worker.ProtoReflect.Descriptor instead. func (*Worker) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{33} + return file_ateapi_proto_rawDescGZIP(), []int{34} } func (x *Worker) GetWorkerNamespace() string { @@ -1910,7 +1990,7 @@ type Assignment struct { func (x *Assignment) Reset() { *x = Assignment{} - mi := &file_ateapi_proto_msgTypes[34] + mi := &file_ateapi_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1922,7 +2002,7 @@ func (x *Assignment) String() string { func (*Assignment) ProtoMessage() {} func (x *Assignment) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[34] + mi := &file_ateapi_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1935,7 +2015,7 @@ func (x *Assignment) ProtoReflect() protoreflect.Message { // Deprecated: Use Assignment.ProtoReflect.Descriptor instead. func (*Assignment) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{34} + return file_ateapi_proto_rawDescGZIP(), []int{35} } func (x *Assignment) GetActorTemplate() *KubeNamespacedObjectRef { @@ -1962,7 +2042,7 @@ type KubeNamespacedObjectRef struct { func (x *KubeNamespacedObjectRef) Reset() { *x = KubeNamespacedObjectRef{} - mi := &file_ateapi_proto_msgTypes[35] + mi := &file_ateapi_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1974,7 +2054,7 @@ func (x *KubeNamespacedObjectRef) String() string { func (*KubeNamespacedObjectRef) ProtoMessage() {} func (x *KubeNamespacedObjectRef) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[35] + mi := &file_ateapi_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1987,7 +2067,7 @@ func (x *KubeNamespacedObjectRef) ProtoReflect() protoreflect.Message { // Deprecated: Use KubeNamespacedObjectRef.ProtoReflect.Descriptor instead. func (*KubeNamespacedObjectRef) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{35} + return file_ateapi_proto_rawDescGZIP(), []int{36} } func (x *KubeNamespacedObjectRef) GetNamespace() string { @@ -2012,7 +2092,7 @@ type DebugClearRequest struct { func (x *DebugClearRequest) Reset() { *x = DebugClearRequest{} - mi := &file_ateapi_proto_msgTypes[36] + mi := &file_ateapi_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2024,7 +2104,7 @@ func (x *DebugClearRequest) String() string { func (*DebugClearRequest) ProtoMessage() {} func (x *DebugClearRequest) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[36] + mi := &file_ateapi_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2037,7 +2117,7 @@ func (x *DebugClearRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DebugClearRequest.ProtoReflect.Descriptor instead. func (*DebugClearRequest) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{36} + return file_ateapi_proto_rawDescGZIP(), []int{37} } type DebugClearResponse struct { @@ -2048,7 +2128,7 @@ type DebugClearResponse struct { func (x *DebugClearResponse) Reset() { *x = DebugClearResponse{} - mi := &file_ateapi_proto_msgTypes[37] + mi := &file_ateapi_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2060,7 +2140,7 @@ func (x *DebugClearResponse) String() string { func (*DebugClearResponse) ProtoMessage() {} func (x *DebugClearResponse) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[37] + mi := &file_ateapi_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2073,7 +2153,7 @@ func (x *DebugClearResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DebugClearResponse.ProtoReflect.Descriptor instead. func (*DebugClearResponse) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{37} + return file_ateapi_proto_rawDescGZIP(), []int{38} } type MintJWTRequest struct { @@ -2088,7 +2168,7 @@ type MintJWTRequest struct { func (x *MintJWTRequest) Reset() { *x = MintJWTRequest{} - mi := &file_ateapi_proto_msgTypes[38] + mi := &file_ateapi_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2100,7 +2180,7 @@ func (x *MintJWTRequest) String() string { func (*MintJWTRequest) ProtoMessage() {} func (x *MintJWTRequest) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[38] + mi := &file_ateapi_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2113,7 +2193,7 @@ func (x *MintJWTRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MintJWTRequest.ProtoReflect.Descriptor instead. func (*MintJWTRequest) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{38} + return file_ateapi_proto_rawDescGZIP(), []int{39} } func (x *MintJWTRequest) GetAudience() []string { @@ -2173,7 +2253,7 @@ type MintJWTResponse struct { func (x *MintJWTResponse) Reset() { *x = MintJWTResponse{} - mi := &file_ateapi_proto_msgTypes[39] + mi := &file_ateapi_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2185,7 +2265,7 @@ func (x *MintJWTResponse) String() string { func (*MintJWTResponse) ProtoMessage() {} func (x *MintJWTResponse) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[39] + mi := &file_ateapi_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2198,7 +2278,7 @@ func (x *MintJWTResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MintJWTResponse.ProtoReflect.Descriptor instead. func (*MintJWTResponse) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{39} + return file_ateapi_proto_rawDescGZIP(), []int{40} } func (x *MintJWTResponse) GetSessionJwt() string { @@ -2223,7 +2303,7 @@ type MintCertRequest struct { func (x *MintCertRequest) Reset() { *x = MintCertRequest{} - mi := &file_ateapi_proto_msgTypes[40] + mi := &file_ateapi_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2235,7 +2315,7 @@ func (x *MintCertRequest) String() string { func (*MintCertRequest) ProtoMessage() {} func (x *MintCertRequest) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[40] + mi := &file_ateapi_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2248,7 +2328,7 @@ func (x *MintCertRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MintCertRequest.ProtoReflect.Descriptor instead. func (*MintCertRequest) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{40} + return file_ateapi_proto_rawDescGZIP(), []int{41} } func (x *MintCertRequest) GetAppId() string { @@ -2291,7 +2371,7 @@ type MintCertResponse struct { func (x *MintCertResponse) Reset() { *x = MintCertResponse{} - mi := &file_ateapi_proto_msgTypes[41] + mi := &file_ateapi_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2303,7 +2383,7 @@ func (x *MintCertResponse) String() string { func (*MintCertResponse) ProtoMessage() {} func (x *MintCertResponse) ProtoReflect() protoreflect.Message { - mi := &file_ateapi_proto_msgTypes[41] + mi := &file_ateapi_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2316,7 +2396,7 @@ func (x *MintCertResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MintCertResponse.ProtoReflect.Descriptor instead. func (*MintCertResponse) Descriptor() ([]byte, []int) { - return file_ateapi_proto_rawDescGZIP(), []int{41} + return file_ateapi_proto_rawDescGZIP(), []int{42} } func (x *MintCertResponse) GetSessionCertificates() [][]byte { @@ -2330,7 +2410,7 @@ var File_ateapi_proto protoreflect.FileDescriptor const file_ateapi_proto_rawDesc = "" + "\n" + - "\fateapi.proto\x12\x06ateapi\"F\n" + + "\fateapi.proto\x12\x06ateapi\x1a\x1fgoogle/protobuf/timestamp.proto\"F\n" + "\x14ExternalSnapshotInfo\x12.\n" + "\x13snapshot_uri_prefix\x18\x01 \x01(\tR\x11snapshotUriPrefix\"~\n" + "\x11LocalSnapshotInfo\x12'\n" + @@ -2344,24 +2424,31 @@ const file_ateapi_proto_rawDesc = "" + "\fmatch_labels\x18\x01 \x03(\v2!.ateapi.Selector.MatchLabelsEntryR\vmatchLabels\x1a>\n" + "\x10MatchLabelsEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xa5\x06\n" + - "\x05Actor\x12\x19\n" + - "\bactor_id\x18\x01 \x01(\tR\aactorId\x12\x18\n" + - "\aversion\x18\x02 \x01(\x03R\aversion\x128\n" + - "\x18actor_template_namespace\x18\x03 \x01(\tR\x16actorTemplateNamespace\x12.\n" + - "\x13actor_template_name\x18\x04 \x01(\tR\x11actorTemplateName\x12,\n" + - "\x06status\x18\x05 \x01(\x0e2\x14.ateapi.Actor.StatusR\x06status\x12.\n" + - "\x13ateom_pod_namespace\x18\x06 \x01(\tR\x11ateomPodNamespace\x12$\n" + - "\x0eateom_pod_name\x18\a \x01(\tR\fateomPodName\x12 \n" + - "\fateom_pod_ip\x18\b \x01(\tR\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xe8\x01\n" + + "\x10ResourceMetadata\x12\x1a\n" + + "\batespace\x18\x01 \x01(\tR\batespace\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x12\x10\n" + + "\x03uid\x18\x03 \x01(\tR\x03uid\x12\x18\n" + + "\aversion\x18\x04 \x01(\x03R\aversion\x12;\n" + + "\vcreate_time\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\n" + + "createTime\x12;\n" + + "\vupdate_time\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\n" + + "updateTime\"\x84\x06\n" + + "\x05Actor\x124\n" + + "\bmetadata\x18\x01 \x01(\v2\x18.ateapi.ResourceMetadataR\bmetadata\x128\n" + + "\x18actor_template_namespace\x18\x02 \x01(\tR\x16actorTemplateNamespace\x12.\n" + + "\x13actor_template_name\x18\x03 \x01(\tR\x11actorTemplateName\x12,\n" + + "\x06status\x18\x04 \x01(\x0e2\x14.ateapi.Actor.StatusR\x06status\x12.\n" + + "\x13ateom_pod_namespace\x18\x05 \x01(\tR\x11ateomPodNamespace\x12$\n" + + "\x0eateom_pod_name\x18\x06 \x01(\tR\fateomPodName\x12 \n" + + "\fateom_pod_ip\x18\a \x01(\tR\n" + "ateomPodIp\x120\n" + - "\x14in_progress_snapshot\x18\n" + - " \x01(\tR\x12inProgressSnapshot\x12\"\n" + - "\rateom_pod_uid\x18\v \x01(\tR\vateomPodUid\x12F\n" + - "\x14latest_snapshot_info\x18\f \x01(\v2\x14.ateapi.SnapshotInfoR\x12latestSnapshotInfo\x129\n" + - "\x0fworker_selector\x18\r \x01(\v2\x10.ateapi.SelectorR\x0eworkerSelector\x12(\n" + - "\x10worker_pool_name\x18\x0e \x01(\tR\x0eworkerPoolName\x12\x1a\n" + - "\batespace\x18\x0f \x01(\tR\batespace\"\xb1\x01\n" + + "\x14in_progress_snapshot\x18\b \x01(\tR\x12inProgressSnapshot\x12\"\n" + + "\rateom_pod_uid\x18\t \x01(\tR\vateomPodUid\x12F\n" + + "\x14latest_snapshot_info\x18\n" + + " \x01(\v2\x14.ateapi.SnapshotInfoR\x12latestSnapshotInfo\x129\n" + + "\x0fworker_selector\x18\v \x01(\v2\x10.ateapi.SelectorR\x0eworkerSelector\x12(\n" + + "\x10worker_pool_name\x18\f \x01(\tR\x0eworkerPoolName\"\xb1\x01\n" + "\x06Status\x12\x16\n" + "\x12STATUS_UNSPECIFIED\x10\x00\x12\x13\n" + "\x0fSTATUS_RESUMING\x10\x01\x12\x12\n" + @@ -2370,10 +2457,9 @@ const file_ateapi_proto_rawDesc = "" + "\x10STATUS_SUSPENDED\x10\x04\x12\x12\n" + "\x0eSTATUS_PAUSING\x10\x05\x12\x11\n" + "\rSTATUS_PAUSED\x10\x06\x12\x12\n" + - "\x0eSTATUS_CRASHED\x10\aJ\x04\b\t\x10\n" + - "\"\x1e\n" + - "\bAtespace\x12\x12\n" + - "\x04name\x18\x01 \x01(\tR\x04name\":\n" + + "\x0eSTATUS_CRASHED\x10\a\"@\n" + + "\bAtespace\x124\n" + + "\bmetadata\x18\x01 \x01(\v2\x18.ateapi.ResourceMetadataR\bmetadata\":\n" + "\bActorRef\x12\x1a\n" + "\batespace\x18\x01 \x01(\tR\batespace\x12\x12\n" + "\x04name\x18\x02 \x01(\tR\x04name\"+\n" + @@ -2514,122 +2600,128 @@ func file_ateapi_proto_rawDescGZIP() []byte { } var file_ateapi_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_ateapi_proto_msgTypes = make([]protoimpl.MessageInfo, 44) +var file_ateapi_proto_msgTypes = make([]protoimpl.MessageInfo, 45) var file_ateapi_proto_goTypes = []any{ (Actor_Status)(0), // 0: ateapi.Actor.Status (*ExternalSnapshotInfo)(nil), // 1: ateapi.ExternalSnapshotInfo (*LocalSnapshotInfo)(nil), // 2: ateapi.LocalSnapshotInfo (*SnapshotInfo)(nil), // 3: ateapi.SnapshotInfo (*Selector)(nil), // 4: ateapi.Selector - (*Actor)(nil), // 5: ateapi.Actor - (*Atespace)(nil), // 6: ateapi.Atespace - (*ActorRef)(nil), // 7: ateapi.ActorRef - (*CreateAtespaceRequest)(nil), // 8: ateapi.CreateAtespaceRequest - (*CreateAtespaceResponse)(nil), // 9: ateapi.CreateAtespaceResponse - (*GetAtespaceRequest)(nil), // 10: ateapi.GetAtespaceRequest - (*GetAtespaceResponse)(nil), // 11: ateapi.GetAtespaceResponse - (*ListAtespacesRequest)(nil), // 12: ateapi.ListAtespacesRequest - (*ListAtespacesResponse)(nil), // 13: ateapi.ListAtespacesResponse - (*DeleteAtespaceRequest)(nil), // 14: ateapi.DeleteAtespaceRequest - (*DeleteAtespaceResponse)(nil), // 15: ateapi.DeleteAtespaceResponse - (*GetActorRequest)(nil), // 16: ateapi.GetActorRequest - (*GetActorResponse)(nil), // 17: ateapi.GetActorResponse - (*CreateActorRequest)(nil), // 18: ateapi.CreateActorRequest - (*CreateActorResponse)(nil), // 19: ateapi.CreateActorResponse - (*UpdateActorRequest)(nil), // 20: ateapi.UpdateActorRequest - (*UpdateActorResponse)(nil), // 21: ateapi.UpdateActorResponse - (*SuspendActorRequest)(nil), // 22: ateapi.SuspendActorRequest - (*SuspendActorResponse)(nil), // 23: ateapi.SuspendActorResponse - (*PauseActorRequest)(nil), // 24: ateapi.PauseActorRequest - (*PauseActorResponse)(nil), // 25: ateapi.PauseActorResponse - (*ResumeActorRequest)(nil), // 26: ateapi.ResumeActorRequest - (*ResumeActorResponse)(nil), // 27: ateapi.ResumeActorResponse - (*DeleteActorRequest)(nil), // 28: ateapi.DeleteActorRequest - (*DeleteActorResponse)(nil), // 29: ateapi.DeleteActorResponse - (*ListWorkersRequest)(nil), // 30: ateapi.ListWorkersRequest - (*ListWorkersResponse)(nil), // 31: ateapi.ListWorkersResponse - (*ListActorsRequest)(nil), // 32: ateapi.ListActorsRequest - (*ListActorsResponse)(nil), // 33: ateapi.ListActorsResponse - (*Worker)(nil), // 34: ateapi.Worker - (*Assignment)(nil), // 35: ateapi.Assignment - (*KubeNamespacedObjectRef)(nil), // 36: ateapi.KubeNamespacedObjectRef - (*DebugClearRequest)(nil), // 37: ateapi.DebugClearRequest - (*DebugClearResponse)(nil), // 38: ateapi.DebugClearResponse - (*MintJWTRequest)(nil), // 39: ateapi.MintJWTRequest - (*MintJWTResponse)(nil), // 40: ateapi.MintJWTResponse - (*MintCertRequest)(nil), // 41: ateapi.MintCertRequest - (*MintCertResponse)(nil), // 42: ateapi.MintCertResponse - nil, // 43: ateapi.Selector.MatchLabelsEntry - nil, // 44: ateapi.Worker.LabelsEntry + (*ResourceMetadata)(nil), // 5: ateapi.ResourceMetadata + (*Actor)(nil), // 6: ateapi.Actor + (*Atespace)(nil), // 7: ateapi.Atespace + (*ActorRef)(nil), // 8: ateapi.ActorRef + (*CreateAtespaceRequest)(nil), // 9: ateapi.CreateAtespaceRequest + (*CreateAtespaceResponse)(nil), // 10: ateapi.CreateAtespaceResponse + (*GetAtespaceRequest)(nil), // 11: ateapi.GetAtespaceRequest + (*GetAtespaceResponse)(nil), // 12: ateapi.GetAtespaceResponse + (*ListAtespacesRequest)(nil), // 13: ateapi.ListAtespacesRequest + (*ListAtespacesResponse)(nil), // 14: ateapi.ListAtespacesResponse + (*DeleteAtespaceRequest)(nil), // 15: ateapi.DeleteAtespaceRequest + (*DeleteAtespaceResponse)(nil), // 16: ateapi.DeleteAtespaceResponse + (*GetActorRequest)(nil), // 17: ateapi.GetActorRequest + (*GetActorResponse)(nil), // 18: ateapi.GetActorResponse + (*CreateActorRequest)(nil), // 19: ateapi.CreateActorRequest + (*CreateActorResponse)(nil), // 20: ateapi.CreateActorResponse + (*UpdateActorRequest)(nil), // 21: ateapi.UpdateActorRequest + (*UpdateActorResponse)(nil), // 22: ateapi.UpdateActorResponse + (*SuspendActorRequest)(nil), // 23: ateapi.SuspendActorRequest + (*SuspendActorResponse)(nil), // 24: ateapi.SuspendActorResponse + (*PauseActorRequest)(nil), // 25: ateapi.PauseActorRequest + (*PauseActorResponse)(nil), // 26: ateapi.PauseActorResponse + (*ResumeActorRequest)(nil), // 27: ateapi.ResumeActorRequest + (*ResumeActorResponse)(nil), // 28: ateapi.ResumeActorResponse + (*DeleteActorRequest)(nil), // 29: ateapi.DeleteActorRequest + (*DeleteActorResponse)(nil), // 30: ateapi.DeleteActorResponse + (*ListWorkersRequest)(nil), // 31: ateapi.ListWorkersRequest + (*ListWorkersResponse)(nil), // 32: ateapi.ListWorkersResponse + (*ListActorsRequest)(nil), // 33: ateapi.ListActorsRequest + (*ListActorsResponse)(nil), // 34: ateapi.ListActorsResponse + (*Worker)(nil), // 35: ateapi.Worker + (*Assignment)(nil), // 36: ateapi.Assignment + (*KubeNamespacedObjectRef)(nil), // 37: ateapi.KubeNamespacedObjectRef + (*DebugClearRequest)(nil), // 38: ateapi.DebugClearRequest + (*DebugClearResponse)(nil), // 39: ateapi.DebugClearResponse + (*MintJWTRequest)(nil), // 40: ateapi.MintJWTRequest + (*MintJWTResponse)(nil), // 41: ateapi.MintJWTResponse + (*MintCertRequest)(nil), // 42: ateapi.MintCertRequest + (*MintCertResponse)(nil), // 43: ateapi.MintCertResponse + nil, // 44: ateapi.Selector.MatchLabelsEntry + nil, // 45: ateapi.Worker.LabelsEntry + (*timestamppb.Timestamp)(nil), // 46: google.protobuf.Timestamp } var file_ateapi_proto_depIdxs = []int32{ 1, // 0: ateapi.SnapshotInfo.external:type_name -> ateapi.ExternalSnapshotInfo 2, // 1: ateapi.SnapshotInfo.local:type_name -> ateapi.LocalSnapshotInfo - 43, // 2: ateapi.Selector.match_labels:type_name -> ateapi.Selector.MatchLabelsEntry - 0, // 3: ateapi.Actor.status:type_name -> ateapi.Actor.Status - 3, // 4: ateapi.Actor.latest_snapshot_info:type_name -> ateapi.SnapshotInfo - 4, // 5: ateapi.Actor.worker_selector:type_name -> ateapi.Selector - 6, // 6: ateapi.CreateAtespaceResponse.atespace:type_name -> ateapi.Atespace - 6, // 7: ateapi.GetAtespaceResponse.atespace:type_name -> ateapi.Atespace - 6, // 8: ateapi.ListAtespacesResponse.atespaces:type_name -> ateapi.Atespace - 7, // 9: ateapi.GetActorRequest.actor_ref:type_name -> ateapi.ActorRef - 5, // 10: ateapi.GetActorResponse.actor:type_name -> ateapi.Actor - 7, // 11: ateapi.CreateActorRequest.actor_ref:type_name -> ateapi.ActorRef - 4, // 12: ateapi.CreateActorRequest.worker_selector:type_name -> ateapi.Selector - 5, // 13: ateapi.CreateActorResponse.actor:type_name -> ateapi.Actor - 7, // 14: ateapi.UpdateActorRequest.actor_ref:type_name -> ateapi.ActorRef - 4, // 15: ateapi.UpdateActorRequest.worker_selector:type_name -> ateapi.Selector - 5, // 16: ateapi.UpdateActorResponse.actor:type_name -> ateapi.Actor - 7, // 17: ateapi.SuspendActorRequest.actor_ref:type_name -> ateapi.ActorRef - 5, // 18: ateapi.SuspendActorResponse.actor:type_name -> ateapi.Actor - 7, // 19: ateapi.PauseActorRequest.actor_ref:type_name -> ateapi.ActorRef - 5, // 20: ateapi.PauseActorResponse.actor:type_name -> ateapi.Actor - 7, // 21: ateapi.ResumeActorRequest.actor_ref:type_name -> ateapi.ActorRef - 5, // 22: ateapi.ResumeActorResponse.actor:type_name -> ateapi.Actor - 7, // 23: ateapi.DeleteActorRequest.actor_ref:type_name -> ateapi.ActorRef - 34, // 24: ateapi.ListWorkersResponse.workers:type_name -> ateapi.Worker - 5, // 25: ateapi.ListActorsResponse.actors:type_name -> ateapi.Actor - 35, // 26: ateapi.Worker.assignment:type_name -> ateapi.Assignment - 44, // 27: ateapi.Worker.labels:type_name -> ateapi.Worker.LabelsEntry - 36, // 28: ateapi.Assignment.actor_template:type_name -> ateapi.KubeNamespacedObjectRef - 7, // 29: ateapi.Assignment.actor:type_name -> ateapi.ActorRef - 16, // 30: ateapi.Control.GetActor:input_type -> ateapi.GetActorRequest - 18, // 31: ateapi.Control.CreateActor:input_type -> ateapi.CreateActorRequest - 20, // 32: ateapi.Control.UpdateActor:input_type -> ateapi.UpdateActorRequest - 22, // 33: ateapi.Control.SuspendActor:input_type -> ateapi.SuspendActorRequest - 24, // 34: ateapi.Control.PauseActor:input_type -> ateapi.PauseActorRequest - 26, // 35: ateapi.Control.ResumeActor:input_type -> ateapi.ResumeActorRequest - 28, // 36: ateapi.Control.DeleteActor:input_type -> ateapi.DeleteActorRequest - 30, // 37: ateapi.Control.ListWorkers:input_type -> ateapi.ListWorkersRequest - 32, // 38: ateapi.Control.ListActors:input_type -> ateapi.ListActorsRequest - 8, // 39: ateapi.Control.CreateAtespace:input_type -> ateapi.CreateAtespaceRequest - 10, // 40: ateapi.Control.GetAtespace:input_type -> ateapi.GetAtespaceRequest - 12, // 41: ateapi.Control.ListAtespaces:input_type -> ateapi.ListAtespacesRequest - 14, // 42: ateapi.Control.DeleteAtespace:input_type -> ateapi.DeleteAtespaceRequest - 37, // 43: ateapi.Control.DebugClear:input_type -> ateapi.DebugClearRequest - 39, // 44: ateapi.SessionIdentity.MintJWT:input_type -> ateapi.MintJWTRequest - 41, // 45: ateapi.SessionIdentity.MintCert:input_type -> ateapi.MintCertRequest - 17, // 46: ateapi.Control.GetActor:output_type -> ateapi.GetActorResponse - 19, // 47: ateapi.Control.CreateActor:output_type -> ateapi.CreateActorResponse - 21, // 48: ateapi.Control.UpdateActor:output_type -> ateapi.UpdateActorResponse - 23, // 49: ateapi.Control.SuspendActor:output_type -> ateapi.SuspendActorResponse - 25, // 50: ateapi.Control.PauseActor:output_type -> ateapi.PauseActorResponse - 27, // 51: ateapi.Control.ResumeActor:output_type -> ateapi.ResumeActorResponse - 29, // 52: ateapi.Control.DeleteActor:output_type -> ateapi.DeleteActorResponse - 31, // 53: ateapi.Control.ListWorkers:output_type -> ateapi.ListWorkersResponse - 33, // 54: ateapi.Control.ListActors:output_type -> ateapi.ListActorsResponse - 9, // 55: ateapi.Control.CreateAtespace:output_type -> ateapi.CreateAtespaceResponse - 11, // 56: ateapi.Control.GetAtespace:output_type -> ateapi.GetAtespaceResponse - 13, // 57: ateapi.Control.ListAtespaces:output_type -> ateapi.ListAtespacesResponse - 15, // 58: ateapi.Control.DeleteAtespace:output_type -> ateapi.DeleteAtespaceResponse - 38, // 59: ateapi.Control.DebugClear:output_type -> ateapi.DebugClearResponse - 40, // 60: ateapi.SessionIdentity.MintJWT:output_type -> ateapi.MintJWTResponse - 42, // 61: ateapi.SessionIdentity.MintCert:output_type -> ateapi.MintCertResponse - 46, // [46:62] is the sub-list for method output_type - 30, // [30:46] is the sub-list for method input_type - 30, // [30:30] is the sub-list for extension type_name - 30, // [30:30] is the sub-list for extension extendee - 0, // [0:30] is the sub-list for field type_name + 44, // 2: ateapi.Selector.match_labels:type_name -> ateapi.Selector.MatchLabelsEntry + 46, // 3: ateapi.ResourceMetadata.create_time:type_name -> google.protobuf.Timestamp + 46, // 4: ateapi.ResourceMetadata.update_time:type_name -> google.protobuf.Timestamp + 5, // 5: ateapi.Actor.metadata:type_name -> ateapi.ResourceMetadata + 0, // 6: ateapi.Actor.status:type_name -> ateapi.Actor.Status + 3, // 7: ateapi.Actor.latest_snapshot_info:type_name -> ateapi.SnapshotInfo + 4, // 8: ateapi.Actor.worker_selector:type_name -> ateapi.Selector + 5, // 9: ateapi.Atespace.metadata:type_name -> ateapi.ResourceMetadata + 7, // 10: ateapi.CreateAtespaceResponse.atespace:type_name -> ateapi.Atespace + 7, // 11: ateapi.GetAtespaceResponse.atespace:type_name -> ateapi.Atespace + 7, // 12: ateapi.ListAtespacesResponse.atespaces:type_name -> ateapi.Atespace + 8, // 13: ateapi.GetActorRequest.actor_ref:type_name -> ateapi.ActorRef + 6, // 14: ateapi.GetActorResponse.actor:type_name -> ateapi.Actor + 8, // 15: ateapi.CreateActorRequest.actor_ref:type_name -> ateapi.ActorRef + 4, // 16: ateapi.CreateActorRequest.worker_selector:type_name -> ateapi.Selector + 6, // 17: ateapi.CreateActorResponse.actor:type_name -> ateapi.Actor + 8, // 18: ateapi.UpdateActorRequest.actor_ref:type_name -> ateapi.ActorRef + 4, // 19: ateapi.UpdateActorRequest.worker_selector:type_name -> ateapi.Selector + 6, // 20: ateapi.UpdateActorResponse.actor:type_name -> ateapi.Actor + 8, // 21: ateapi.SuspendActorRequest.actor_ref:type_name -> ateapi.ActorRef + 6, // 22: ateapi.SuspendActorResponse.actor:type_name -> ateapi.Actor + 8, // 23: ateapi.PauseActorRequest.actor_ref:type_name -> ateapi.ActorRef + 6, // 24: ateapi.PauseActorResponse.actor:type_name -> ateapi.Actor + 8, // 25: ateapi.ResumeActorRequest.actor_ref:type_name -> ateapi.ActorRef + 6, // 26: ateapi.ResumeActorResponse.actor:type_name -> ateapi.Actor + 8, // 27: ateapi.DeleteActorRequest.actor_ref:type_name -> ateapi.ActorRef + 35, // 28: ateapi.ListWorkersResponse.workers:type_name -> ateapi.Worker + 6, // 29: ateapi.ListActorsResponse.actors:type_name -> ateapi.Actor + 36, // 30: ateapi.Worker.assignment:type_name -> ateapi.Assignment + 45, // 31: ateapi.Worker.labels:type_name -> ateapi.Worker.LabelsEntry + 37, // 32: ateapi.Assignment.actor_template:type_name -> ateapi.KubeNamespacedObjectRef + 8, // 33: ateapi.Assignment.actor:type_name -> ateapi.ActorRef + 17, // 34: ateapi.Control.GetActor:input_type -> ateapi.GetActorRequest + 19, // 35: ateapi.Control.CreateActor:input_type -> ateapi.CreateActorRequest + 21, // 36: ateapi.Control.UpdateActor:input_type -> ateapi.UpdateActorRequest + 23, // 37: ateapi.Control.SuspendActor:input_type -> ateapi.SuspendActorRequest + 25, // 38: ateapi.Control.PauseActor:input_type -> ateapi.PauseActorRequest + 27, // 39: ateapi.Control.ResumeActor:input_type -> ateapi.ResumeActorRequest + 29, // 40: ateapi.Control.DeleteActor:input_type -> ateapi.DeleteActorRequest + 31, // 41: ateapi.Control.ListWorkers:input_type -> ateapi.ListWorkersRequest + 33, // 42: ateapi.Control.ListActors:input_type -> ateapi.ListActorsRequest + 9, // 43: ateapi.Control.CreateAtespace:input_type -> ateapi.CreateAtespaceRequest + 11, // 44: ateapi.Control.GetAtespace:input_type -> ateapi.GetAtespaceRequest + 13, // 45: ateapi.Control.ListAtespaces:input_type -> ateapi.ListAtespacesRequest + 15, // 46: ateapi.Control.DeleteAtespace:input_type -> ateapi.DeleteAtespaceRequest + 38, // 47: ateapi.Control.DebugClear:input_type -> ateapi.DebugClearRequest + 40, // 48: ateapi.SessionIdentity.MintJWT:input_type -> ateapi.MintJWTRequest + 42, // 49: ateapi.SessionIdentity.MintCert:input_type -> ateapi.MintCertRequest + 18, // 50: ateapi.Control.GetActor:output_type -> ateapi.GetActorResponse + 20, // 51: ateapi.Control.CreateActor:output_type -> ateapi.CreateActorResponse + 22, // 52: ateapi.Control.UpdateActor:output_type -> ateapi.UpdateActorResponse + 24, // 53: ateapi.Control.SuspendActor:output_type -> ateapi.SuspendActorResponse + 26, // 54: ateapi.Control.PauseActor:output_type -> ateapi.PauseActorResponse + 28, // 55: ateapi.Control.ResumeActor:output_type -> ateapi.ResumeActorResponse + 30, // 56: ateapi.Control.DeleteActor:output_type -> ateapi.DeleteActorResponse + 32, // 57: ateapi.Control.ListWorkers:output_type -> ateapi.ListWorkersResponse + 34, // 58: ateapi.Control.ListActors:output_type -> ateapi.ListActorsResponse + 10, // 59: ateapi.Control.CreateAtespace:output_type -> ateapi.CreateAtespaceResponse + 12, // 60: ateapi.Control.GetAtespace:output_type -> ateapi.GetAtespaceResponse + 14, // 61: ateapi.Control.ListAtespaces:output_type -> ateapi.ListAtespacesResponse + 16, // 62: ateapi.Control.DeleteAtespace:output_type -> ateapi.DeleteAtespaceResponse + 39, // 63: ateapi.Control.DebugClear:output_type -> ateapi.DebugClearResponse + 41, // 64: ateapi.SessionIdentity.MintJWT:output_type -> ateapi.MintJWTResponse + 43, // 65: ateapi.SessionIdentity.MintCert:output_type -> ateapi.MintCertResponse + 50, // [50:66] is the sub-list for method output_type + 34, // [34:50] is the sub-list for method input_type + 34, // [34:34] is the sub-list for extension type_name + 34, // [34:34] is the sub-list for extension extendee + 0, // [0:34] is the sub-list for field type_name } func init() { file_ateapi_proto_init() } @@ -2647,7 +2739,7 @@ func file_ateapi_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_ateapi_proto_rawDesc), len(file_ateapi_proto_rawDesc)), NumEnums: 1, - NumMessages: 44, + NumMessages: 45, NumExtensions: 0, NumServices: 2, }, diff --git a/pkg/proto/ateapipb/ateapi.proto b/pkg/proto/ateapipb/ateapi.proto index 47a249cd9..6a3a439f1 100644 --- a/pkg/proto/ateapipb/ateapi.proto +++ b/pkg/proto/ateapipb/ateapi.proto @@ -18,6 +18,8 @@ syntax = "proto3"; package ateapi; +import "google/protobuf/timestamp.proto"; + option go_package = "github.com/agent-substrate/substrate/pkg/proto/ateapipb"; @@ -92,12 +94,36 @@ message Selector { map match_labels = 1; } +// ResourceMetadata holds the common fields carried by every Substrate resource. +message ResourceMetadata { + // atespace is the namespace the resource belongs to. Empty for global-scoped + // resources. Caller-specified at creation and immutable thereafter. + string atespace = 1; + + // name is the resource's name, unique within its atespace (or globally, for + // global-scoped resources). Caller-specified at creation and immutable thereafter. + string name = 2; + + // uid is a server-assigned, globally unique identifier for this resource. + // Immutable throughout the lifecycle of the resource. + string uid = 3; + + // version is increased on every mutation. + int64 version = 4; + + // create_time is the time the resource was created. + google.protobuf.Timestamp create_time = 5; + + // update_time is the time the resource was last updated. + google.protobuf.Timestamp update_time = 6; +} + message Actor { - string actor_id = 1; - int64 version = 2; + // Common resource metadata: atespace, name, uid, version, timestamps. + ResourceMetadata metadata = 1; - string actor_template_namespace = 3; - string actor_template_name = 4; + string actor_template_namespace = 2; + string actor_template_name = 3; enum Status { STATUS_UNSPECIFIED = 0; @@ -109,23 +135,21 @@ message Actor { STATUS_PAUSED = 6; STATUS_CRASHED = 7; } - Status status = 5; + Status status = 4; - string ateom_pod_namespace = 6; - string ateom_pod_name = 7; - string ateom_pod_ip = 8; + string ateom_pod_namespace = 5; + string ateom_pod_name = 6; + string ateom_pod_ip = 7; - // last_snapshot - reserved 9; - string in_progress_snapshot = 10; - string ateom_pod_uid = 11; - SnapshotInfo latest_snapshot_info = 12; + string in_progress_snapshot = 8; + string ateom_pod_uid = 9; + SnapshotInfo latest_snapshot_info = 10; // worker_selector is the per-actor placement constraint. The scheduler // evaluates the AND of this selector and the template's workerSelector to // find eligible pools. Set at CreateActor; may be updated at any time via // UpdateActor. Changes take effect on the next ResumeActor call. - Selector worker_selector = 13; + Selector worker_selector = 11; // worker_pool_name is the name of the WorkerPool that owns the currently // assigned worker, in the same namespace as ateom_pod_namespace (pool and @@ -133,16 +157,14 @@ message Actor { // and cleared when the worker is freed. Needed to release the worker on // suspend/pause since eligibility is no longer a single fixed pool // reference on the ActorTemplate. - string worker_pool_name = 14; - - // The atespace this actor belongs to. Part of the actor's - // resource identity; folded into the Redis key as actor::. - string atespace = 15; + string worker_pool_name = 12; } -// Atespace is the isolation boundary an Actor is created into. +// Atespace is the isolation boundary an Actor is created into. Global-scoped: +// metadata.atespace is always empty; the atespace's identity is metadata.name. message Atespace { - string name = 1; + // Common resource metadata: name, uid, version, timestamps. + ResourceMetadata metadata = 1; } // ActorRef identifies an actor: a name is only unique within its atespace.