Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metadata API: report actor runtime status #7040

Merged
merged 56 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
bb9eb57
Metadata API: report actor runtime status
ItalyPaleAle Oct 14, 2023
5644f7c
Added integration tests
ItalyPaleAle Oct 18, 2023
b0f08c0
Merge branch 'master' into metadata-actor-status
dapr-bot Oct 19, 2023
acbc6ad
Merge branch 'master' into metadata-actor-status
dapr-bot Oct 20, 2023
42c6bb0
Merge branch 'master' into metadata-actor-status
dapr-bot Oct 20, 2023
7f33edb
Changed per review feedback
ItalyPaleAle Oct 20, 2023
9d4a012
Merge branch 'master' into metadata-actor-status
dapr-bot Oct 20, 2023
81e2d9b
Merge branch 'master' into metadata-actor-status
dapr-bot Oct 21, 2023
41fd0fa
Merge branch 'master' into metadata-actor-status
dapr-bot Oct 21, 2023
0795ea8
Merge branch 'master' into metadata-actor-status
dapr-bot Oct 21, 2023
2c8162b
Merge branch 'master' into metadata-actor-status
dapr-bot Oct 21, 2023
f3bbe0b
Merge branch 'master' into metadata-actor-status
dapr-bot Oct 21, 2023
6b68cb3
Merge branch 'master' into metadata-actor-status
dapr-bot Oct 23, 2023
311ef3b
Merge branch 'master' into metadata-actor-status
dapr-bot Oct 23, 2023
c71430f
Merge branch 'master' into metadata-actor-status
dapr-bot Oct 24, 2023
01e5eb7
Merge branch 'master' of https://github.com/dapr/dapr into metadata-a…
ItalyPaleAle Oct 26, 2023
dd9ba6d
Merge branch 'master' into metadata-actor-status
dapr-bot Oct 26, 2023
2bdbcc3
Merge branch 'master' into metadata-actor-status
mukundansundar Oct 27, 2023
1eb1f35
Merge branch 'master' into metadata-actor-status
dapr-bot Oct 27, 2023
68b5aa2
Merge branch 'master' into metadata-actor-status
dapr-bot Oct 30, 2023
f7fcb0c
Merge branch 'master' into metadata-actor-status
dapr-bot Oct 30, 2023
d381443
Address review feedback 1
ItalyPaleAle Oct 31, 2023
054a1c6
Address review feedback 2
ItalyPaleAle Oct 31, 2023
54f4c29
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 2, 2023
410b989
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 2, 2023
40a4861
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 3, 2023
ae1c8aa
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 4, 2023
6e7a6ed
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 4, 2023
5023d2e
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 4, 2023
753649a
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 6, 2023
02c751c
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 7, 2023
3d24b04
Renamed to WithInMemoryActorStateStore
ItalyPaleAle Nov 7, 2023
6ed4831
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 9, 2023
2e3f3fa
Added comments
ItalyPaleAle Nov 9, 2023
8023a1f
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 9, 2023
4a8b73f
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 9, 2023
8521923
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 13, 2023
2750607
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 13, 2023
4218803
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 13, 2023
5fcb057
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 13, 2023
57554bc
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 13, 2023
8360ec9
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 15, 2023
0704706
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 15, 2023
657791c
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 15, 2023
1c13428
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 15, 2023
83234b1
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 16, 2023
6405e8a
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 16, 2023
36c36d2
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 17, 2023
f412cca
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 17, 2023
8e608b8
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 17, 2023
fb542dd
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 17, 2023
48da34c
Merge branch 'master' of https://github.com/dapr/dapr into metadata-a…
ItalyPaleAle Nov 19, 2023
d744520
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 20, 2023
3e49978
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 20, 2023
9712d15
Merge branch 'master' into metadata-actor-status
dapr-bot Nov 21, 2023
6e490c8
Merge branch 'master' of https://github.com/dapr/dapr into metadata-a…
ItalyPaleAle Nov 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 20 additions & 1 deletion dapr/proto/runtime/v1/dapr.proto
Original file line number Diff line number Diff line change
Expand Up @@ -595,14 +595,33 @@ message GetMetadataRequest {
// GetMetadataResponse is a message that is returned on GetMetadata rpc call.
message GetMetadataResponse {
string id = 1;
repeated ActiveActorsCount active_actors_count = 2 [json_name = "actors"];
// Deprecated alias for actor_runtime.active_actors.
repeated ActiveActorsCount active_actors_count = 2 [json_name = "actors", deprecated = true];
repeated RegisteredComponents registered_components = 3 [json_name = "components"];
map<string, string> extended_metadata = 4 [json_name = "extended"];
repeated PubsubSubscription subscriptions = 5 [json_name = "subscriptions"];
repeated MetadataHTTPEndpoint http_endpoints = 6 [json_name = "httpEndpoints"];
AppConnectionProperties app_connection_properties = 7 [json_name = "appConnectionProperties"];
string runtime_version = 8 [json_name = "runtimeVersion"];
repeated string enabled_features = 9 [json_name = "enabledFeatures"];
ActorRuntime actor_runtime = 10 [json_name = "actorRuntime"];
}

message ActorRuntime {
enum ActorRuntimeStatus {
INITIALIZING = 0;
DISABLED = 1;
ItalyPaleAle marked this conversation as resolved.
Show resolved Hide resolved
ItalyPaleAle marked this conversation as resolved.
Show resolved Hide resolved
RUNNING = 2;
}

// Contains an enum indicating whether the actor runtime has been initialized.
ActorRuntimeStatus runtime_status = 1 [json_name = "runtimeStatus"];
// Count of active actors per type.
repeated ActiveActorsCount active_actors = 2 [json_name = "activeActors"];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just trying to understand the context: Why knowing count would be useful here? Some debugging purpose to know of load?
I see that it is already there but just trying to understand the relevance of it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't fully understand it either. But it was there before, and I didn't add it - I just added it here too for consistency.

// Indicates whether the actor runtime is ready to host actors.
bool host_ready = 3 [json_name = "hostReady"];
// Custom message from the placement provider.
string placement = 4 [json_name = "placement"];
mukundansundar marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As it is a message received from placement, should the name be more explicit? placement_msg

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the "msg" is redundant IMHO. Just sending more bytes over the wire (when using JSON).

}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should the actor api level also be included in this ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, but it’s currently not used. When the placement does report the min actor level, then we can add it.


message ActiveActorsCount {
Expand Down
18 changes: 16 additions & 2 deletions pkg/actors/actors.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ type ActorRuntime interface {
io.Closer
Init(context.Context) error
IsActorHosted(ctx context.Context, req *ActorHostedRequest) bool
GetActiveActorsCount(ctx context.Context) []*runtimev1pb.ActiveActorsCount
GetRuntimeStatus(ctx context.Context) *runtimev1pb.ActorRuntime
RegisterInternalActor(ctx context.Context, actorType string, actor InternalActor, actorIdleTimeout time.Duration) error
}

Expand Down Expand Up @@ -972,7 +972,21 @@ func (a *actorsRuntime) RegisterInternalActor(ctx context.Context, actorType str
return nil
}

func (a *actorsRuntime) GetActiveActorsCount(ctx context.Context) []*runtimev1pb.ActiveActorsCount {
func (a *actorsRuntime) GetRuntimeStatus(ctx context.Context) *runtimev1pb.ActorRuntime {
// Do not populate RuntimeStatus, which will be populated by the runtime
res := &runtimev1pb.ActorRuntime{
ActiveActors: a.getActiveActorsCount(ctx),
}

if a.placement != nil {
res.HostReady = a.placement.PlacementHealthy() && a.haveCompatibleStorage()
res.Placement = a.placement.StatusMessage()
}

return res
}

func (a *actorsRuntime) getActiveActorsCount(ctx context.Context) []*runtimev1pb.ActiveActorsCount {
actorTypes := a.actorsConfig.Config.HostedActorTypes.ListActorTypes()
actorCountMap := make(map[string]int32, len(actorTypes))
for _, actorType := range actorTypes {
Expand Down
39 changes: 27 additions & 12 deletions pkg/actors/actors_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pkg/actors/actors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1004,7 +1004,7 @@ func TestActiveActorsCount(t *testing.T) {
fakeCallAndActivateActor(testActorsRuntime, "cat", "xyz", testActorsRuntime.clock)
fakeCallAndActivateActor(testActorsRuntime, "dog", "xyz", testActorsRuntime.clock)

actualCounts := testActorsRuntime.GetActiveActorsCount(ctx)
actualCounts := testActorsRuntime.getActiveActorsCount(ctx)
assert.ElementsMatch(t, expectedCounts, actualCounts)
})

Expand All @@ -1015,7 +1015,7 @@ func TestActiveActorsCount(t *testing.T) {
testActorsRuntime.actorsConfig.Config.HostedActorTypes = internal.NewHostedActors([]string{})
defer testActorsRuntime.Close()

actualCounts := testActorsRuntime.GetActiveActorsCount(ctx)
actualCounts := testActorsRuntime.getActiveActorsCount(ctx)
assert.Equal(t, expectedCounts, actualCounts)
})
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/actors/internal/placement_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ type PlacementService interface {
WaitUntilReady(ctx context.Context) error
LookupActor(ctx context.Context, req LookupActorRequest) (LookupActorResponse, error)
AddHostedActorType(actorType string, idleTimeout time.Duration) error

// PlacementHealthy returns true if the placement service is healthy.
PlacementHealthy() bool
// StatusMessage returns a custom status message.
StatusMessage() string
}

// LookupActorRequest is the request for LookupActor.
Expand Down
2 changes: 1 addition & 1 deletion pkg/actors/internal_actor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,6 @@ func TestInternalActorsNotCounted(t *testing.T) {
internalActors[InternalActorTypePrefix+"wfengine.workflow"] = &mockInternalActor{}
testActorRuntime, err := newTestActorsRuntimeWithInternalActors(internalActors)
require.NoError(t, err)
actorCounts := testActorRuntime.GetActiveActorsCount(context.Background())
actorCounts := testActorRuntime.getActiveActorsCount(context.Background())
assert.Empty(t, actorCounts)
}
11 changes: 11 additions & 0 deletions pkg/actors/placement/placement.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,17 @@ func NewActorPlacement(opts ActorPlacementOpts) internal.PlacementService {
}
}

func (p *actorPlacement) PlacementHealthy() bool {
return p.appHealthy.Load() && p.client.isConnected()
}

func (p *actorPlacement) StatusMessage() string {
if p.client.isConnected() {
return "placement: connected"
}
return "placement: disconnected"
}

// Register an actor type by adding it to the list of known actor types (if it's not already registered)
// The placement tables will get updated when the next heartbeat fires
func (p *actorPlacement) AddHostedActorType(actorType string, idleTimeout time.Duration) error {
Expand Down
51 changes: 22 additions & 29 deletions pkg/grpc/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4157,23 +4157,9 @@ func TestMetadata(t *testing.T) {
})

mockActors := new(actors.MockActors)
mockActors.On("GetActiveActorsCount")

appConnectionConfig := config.AppConnectionConfig{
ChannelAddress: "1.2.3.4",
MaxConcurrency: 10,
Port: 5000,
Protocol: "grpc",
HealthCheckHTTPPath: "/healthz",
HealthCheck: &config.AppHealthConfig{
ProbeInterval: 10 * time.Second,
ProbeTimeout: 5 * time.Second,
ProbeOnly: true,
Threshold: 3,
},
}
mockActors.On("GetRuntimeStatus")

server, lis := startDaprAPIServer(&api{
a := &api{
UniversalAPI: &universalapi.UniversalAPI{
AppID: "fakeAPI",
Actors: mockActors,
Expand All @@ -4189,10 +4175,26 @@ func TestMetadata(t *testing.T) {
ExtendedMetadata: map[string]string{
"test": "value",
},
AppConnectionConfig: appConnectionConfig,
GlobalConfig: &config.Configuration{},
AppConnectionConfig: config.AppConnectionConfig{
ChannelAddress: "1.2.3.4",
MaxConcurrency: 10,
Port: 5000,
Protocol: "grpc",
HealthCheckHTTPPath: "/healthz",
HealthCheck: &config.AppHealthConfig{
ProbeInterval: 10 * time.Second,
ProbeTimeout: 5 * time.Second,
ProbeOnly: true,
Threshold: 3,
},
},
GlobalConfig: &config.Configuration{},
},
}, "")
}
a.UniversalAPI.InitUniversalAPI()
a.UniversalAPI.SetActorsInitDone()

server, lis := startDaprAPIServer(a, "")
defer server.Stop()

clientConn := createTestClient(lis)
Expand All @@ -4217,16 +4219,7 @@ func TestMetadata(t *testing.T) {
bytes, err := json.Marshal(res)
assert.NoError(t, err)

expectedResponse := `{"id":"fakeAPI",` +
`"active_actors_count":[{"type":"abcd","count":10},{"type":"xyz","count":5}],` +
`"registered_components":[{"name":"MockComponent1Name","type":"mock.component1Type","version":"v1.0","capabilities":["mock.feat.MockComponent1Name"]},` +
`{"name":"MockComponent2Name","type":"mock.component2Type","version":"v1.0","capabilities":["mock.feat.MockComponent2Name"]}],` +
`"extended_metadata":{"daprRuntimeVersion":"edge","foo":"bar","test":"value"},` +
`"subscriptions":[{"pubsub_name":"test","topic":"topic","rules":{"rules":[{"path":"path"}]},"dead_letter_topic":"dead"}],` +
`"http_endpoints":[{"name":"MockHTTPEndpoint"}],` +
`"app_connection_properties":{"port":5000,"protocol":"grpc","channel_address":"1.2.3.4","max_concurrency":10,` +
`"health":{"health_probe_interval":"10s","health_probe_timeout":"5s","health_threshold":3}},` +
`"runtime_version":"edge"}`
expectedResponse := `{"id":"fakeAPI","active_actors_count":[{"type":"abcd","count":10},{"type":"xyz","count":5}],"registered_components":[{"name":"MockComponent1Name","type":"mock.component1Type","version":"v1.0","capabilities":["mock.feat.MockComponent1Name"]},{"name":"MockComponent2Name","type":"mock.component2Type","version":"v1.0","capabilities":["mock.feat.MockComponent2Name"]}],"extended_metadata":{"daprRuntimeVersion":"edge","foo":"bar","test":"value"},"subscriptions":[{"pubsub_name":"test","topic":"topic","rules":{"rules":[{"path":"path"}]},"dead_letter_topic":"dead"}],"http_endpoints":[{"name":"MockHTTPEndpoint"}],"app_connection_properties":{"port":5000,"protocol":"grpc","channel_address":"1.2.3.4","max_concurrency":10,"health":{"health_probe_interval":"10s","health_probe_timeout":"5s","health_threshold":3}},"runtime_version":"edge","actor_runtime":{"runtime_status":2,"active_actors":[{"type":"abcd","count":10},{"type":"xyz","count":5}],"host_ready":true}}`
assert.Equal(t, expectedResponse, string(bytes))
})
}
Expand Down
18 changes: 13 additions & 5 deletions pkg/grpc/universalapi/api_metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,17 @@ func (a *UniversalAPI) GetMetadata(ctx context.Context, in *runtimev1pb.GetMetad
// This is deprecated, but we still need to support it for backward compatibility.
extendedMetadata[daprRuntimeVersionKey] = buildinfo.Version()

// Active actors count
activeActorsCount := []*runtimev1pb.ActiveActorsCount{}
if a.Actors != nil {
activeActorsCount = a.Actors.GetActiveActorsCount(ctx)
// Actor runtime
var actorRuntime *runtimev1pb.ActorRuntime
if a.actorsReady.Load() {
if a.Actors == nil {
actorRuntime = &runtimev1pb.ActorRuntime{
RuntimeStatus: runtimev1pb.ActorRuntime_DISABLED,
}
} else {
actorRuntime = a.Actors.GetRuntimeStatus(ctx)
actorRuntime.RuntimeStatus = runtimev1pb.ActorRuntime_RUNNING
}
}

// App connection information
Expand Down Expand Up @@ -104,12 +111,13 @@ func (a *UniversalAPI) GetMetadata(ctx context.Context, in *runtimev1pb.GetMetad
Id: a.AppID,
ExtendedMetadata: extendedMetadata,
RegisteredComponents: registeredComponents,
ActiveActorsCount: activeActorsCount,
ActiveActorsCount: actorRuntime.GetActiveActors(), // Alias for backwards-compatibility
Subscriptions: ps,
HttpEndpoints: registeredHTTPEndpoints,
AppConnectionProperties: appConnectionProperties,
RuntimeVersion: buildinfo.Version(),
EnabledFeatures: a.GlobalConfig.EnabledFeatures(),
ActorRuntime: actorRuntime,
}, nil
}

Expand Down
8 changes: 3 additions & 5 deletions pkg/grpc/universalapi/api_metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@ func TestGetMetadata(t *testing.T) {
fakeComponent.Name = "testComponent"

mockActors := new(actors.MockActors)
mockActors.On("GetActiveActorsCount").Return(&runtimev1pb.ActiveActorsCount{
Count: 10,
Type: "abcd",
})
mockActors.On("GetRuntimeStatus")

compStore := compstore.New()
compStore.AddComponent(fakeComponent)
Expand Down Expand Up @@ -106,6 +103,7 @@ func TestGetMetadata(t *testing.T) {
AppConnectionConfig: appConnectionConfig,
GlobalConfig: &config.Configuration{},
}
fakeAPI.actorsReady.Store(true)

response, err := fakeAPI.GetMetadata(context.Background(), &runtimev1pb.GetMetadataRequest{})
require.NoError(t, err, "Expected no error")
Expand All @@ -125,7 +123,7 @@ func TestGetMetadata(t *testing.T) {
`"subscriptions":[{"pubsub_name":"test","topic":"topic","rules":{"rules":[{"path":"path"}]},"dead_letter_topic":"dead"}],` +
`"app_connection_properties":{"port":1234,"protocol":"http","channel_address":"1.2.3.4","max_concurrency":10` +
healthCheckJSON +
`"runtime_version":"edge"}`
`"runtime_version":"edge","actor_runtime":{"runtime_status":2,"active_actors":[{"type":"abcd","count":10},{"type":"xyz","count":5}],"host_ready":true}}`
assert.Equal(t, expectedResponse, string(bytes))
})
}
Expand Down
20 changes: 19 additions & 1 deletion pkg/http/api_metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func (a *api) onGetMetadata() http.HandlerFunc {
ID: out.Id,
Extended: out.ExtendedMetadata,
// We can embed the proto object directly only for as long as the protojson key is == json key
ActiveActorsCount: out.ActiveActorsCount,
ActiveActorsCount: out.ActiveActorsCount, //nolint:staticcheck
RegisteredComponents: out.RegisteredComponents,
HTTPEndpoints: out.HttpEndpoints,
RuntimeVersion: out.RuntimeVersion,
Expand Down Expand Up @@ -115,6 +115,16 @@ func (a *api) onGetMetadata() http.HandlerFunc {
res.Subscriptions = subs
}

// Actor runtime
// We need to include the status as string
actorRuntime := out.GetActorRuntime()
res.ActorRuntime = metadataActorRuntime{
Status: actorRuntime.GetRuntimeStatus().String(),
ActiveActors: actorRuntime.GetActiveActors(),
HostReady: actorRuntime.GetHostReady(),
Placement: actorRuntime.GetPlacement(),
}

return res, nil
},
},
Expand Down Expand Up @@ -155,6 +165,14 @@ type metadataResponse struct {
Subscriptions []metadataResponsePubsubSubscription `json:"subscriptions,omitempty"`
HTTPEndpoints []*runtimev1pb.MetadataHTTPEndpoint `json:"httpEndpoints,omitempty"`
AppConnectionProperties metadataResponseAppConnectionProperties `json:"appConnectionProperties,omitempty"`
ActorRuntime metadataActorRuntime `json:"actorRuntime,omitempty"`
}

type metadataActorRuntime struct {
Status string `json:"runtimeStatus"`
ActiveActors []*runtimev1pb.ActiveActorsCount `json:"activeActors,omitempty"`
HostReady bool `json:"hostReady"`
Placement string `json:"placement,omitempty"`
Comment on lines +168 to +175
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It concerns me somewhat that the metadata API definition is quite informal being in this package, and is treated in a more ad-hoc way than say the CRDs or proto definitions. Do you think it would be a good idea to "promote" them? Ideally, I think we should move these to proto definitions, which would make for stronger compatibilities for serious consumers of this API.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't a new change, but regardless:

  • The main struct is in the proto.
  • When the API was converted to universal, the gRPC and HTTP responses were different, so we couldn't just return the gRPC response encoded with protojson
  • So we had to create this struct which mimics what's in the proto

I don't love it, but we can't change this much.

}

type metadataResponsePubsubSubscription struct {
Expand Down
14 changes: 3 additions & 11 deletions pkg/http/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1805,7 +1805,7 @@ func TestV1MetadataEndpoint(t *testing.T) {
})

mockActors := new(actors.MockActors)
mockActors.On("GetActiveActorsCount")
mockActors.On("GetRuntimeStatus")

appConnectionConfig := config.AppConnectionConfig{
ChannelAddress: "1.2.3.4",
Expand Down Expand Up @@ -1849,15 +1849,7 @@ func TestV1MetadataEndpoint(t *testing.T) {
assert.Equal(t, 204, resp.StatusCode)
})

const expectedBody = `{"id":"xyz","runtimeVersion":"edge",` +
`"actors":[{"type":"abcd","count":10},{"type":"xyz","count":5}],` +
`"components":[{"name":"MockComponent1Name","type":"mock.component1Type","version":"v1.0","capabilities":["mock.feat.MockComponent1Name"]},` +
`{"name":"MockComponent2Name","type":"mock.component2Type","version":"v1.0","capabilities":["mock.feat.MockComponent2Name"]}],` +
`"extended":{"daprRuntimeVersion":"edge","foo":"bar","test":"value"},` +
`"subscriptions":[{"pubsubname":"test","topic":"topic","rules":[{"path":"path"}],"deadLetterTopic":"dead"}],` +
`"httpEndpoints":[{"name":"MockHTTPEndpoint"}],` +
`"appConnectionProperties":{"port":5000,"protocol":"http","channelAddress":"1.2.3.4","maxConcurrency":10,` +
`"health":{"healthCheckPath":"/healthz","healthProbeInterval":"10s","healthProbeTimeout":"5s","healthThreshold":3}}}`
const expectedBody = `{"id":"xyz","runtimeVersion":"edge","actors":[{"type":"abcd","count":10},{"type":"xyz","count":5}],"components":[{"name":"MockComponent1Name","type":"mock.component1Type","version":"v1.0","capabilities":["mock.feat.MockComponent1Name"]},{"name":"MockComponent2Name","type":"mock.component2Type","version":"v1.0","capabilities":["mock.feat.MockComponent2Name"]}],"extended":{"daprRuntimeVersion":"edge","foo":"bar","test":"value"},"subscriptions":[{"pubsubname":"test","topic":"topic","rules":[{"path":"path"}],"deadLetterTopic":"dead"}],"httpEndpoints":[{"name":"MockHTTPEndpoint"}],"appConnectionProperties":{"port":5000,"protocol":"http","channelAddress":"1.2.3.4","maxConcurrency":10,"health":{"healthCheckPath":"/healthz","healthProbeInterval":"10s","healthProbeTimeout":"5s","healthThreshold":3}},"actorRuntime":{"runtimeStatus":"RUNNING","activeActors":[{"type":"abcd","count":10},{"type":"xyz","count":5}],"hostReady":true}}`

t.Run("Get Metadata", func(t *testing.T) {
resp := fakeServer.DoRequest("GET", "v1.0/metadata", nil, nil)
Expand All @@ -1872,7 +1864,7 @@ func TestV1MetadataEndpoint(t *testing.T) {

assert.Equal(t, 200, resp.StatusCode)
assert.Equal(t, expectedBody, string(resp.RawBody))
mockActors.AssertNumberOfCalls(t, "GetActiveActorsCount", 1)
mockActors.AssertNumberOfCalls(t, "GetRuntimeStatus", 1)
})

fakeServer.Shutdown()
Expand Down