Repository: nats-io/nats.go
Pull request #1173 (2022-12-28 15:29:44)

Adds response data types for latest ADR update
Update for https://github.com/nats-io/nats-architecture-and-design/pull/183

Signed-off-by: R.I.Pienaar <rip@devco.net>

coveralls: 
[![Coverage Status](https://coveralls.io/builds/55498333/badge)](https://coveralls.io/builds/55498333)

Coverage: 85.473% (-0.03%) from 85.506% when pulling **e9084d75317b48013351b801825cb93259f63d27 on ripienaar:micro_response_types** into **f2f17e6af1412edd414cf6e3d73f13a7179d6dd4 on nats-io:main**.

ripienaar: @piotrpio i fixed that, but somehow cant merge thought I was able to merge here, anyway its good to go if you want to merge.

Patch:
diff --git a/micro/service.go b/micro/service.go
index b2d01cc..146f094 100644
--- a/micro/service.go
+++ b/micro/service.go
@@ -53,7 +53,7 @@ type (
 	// DoneHandler is a function used to configure a custom done handler for a service.
 	DoneHandler func(Service)
 
-	// StatsHandleris a function used to configure a custom STATS endpoint.
+	// StatsHandler is a function used to configure a custom STATS endpoint.
 	// It should return a value which can be serialized to JSON.
 	StatsHandler func(Endpoint) interface{}
 
@@ -68,6 +68,7 @@ type (
 	// It contains stats for a specific endpoint (either request handler or monitoring enpoints).
 	Stats struct {
 		ServiceIdentity
+		Type                  string          `json:"type"`
 		NumRequests           int             `json:"num_requests"`
 		NumErrors             int             `json:"num_errors"`
 		LastError             string          `json:"last_error"`
@@ -78,11 +79,15 @@ type (
 	}
 
 	// Ping is the response type for PING monitoring endpoint.
-	Ping ServiceIdentity
+	Ping struct {
+		ServiceIdentity
+		Type string `json:"type"`
+	}
 
 	// Info is the basic information about a service type.
 	Info struct {
 		ServiceIdentity
+		Type        string `json:"type"`
 		Description string `json:"description"`
 		Subject     string `json:"subject"`
 	}
@@ -90,6 +95,7 @@ type (
 	// SchemaResp is the response value for SCHEMA requests.
 	SchemaResp struct {
 		ServiceIdentity
+		Type   string `json:"type"`
 		Schema Schema `json:"schema"`
 	}
 
@@ -180,6 +186,13 @@ const (
 	SchemaVerb
 )
 
+const (
+	InfoResponseType   = "io.nats.micro.v1.info_response"
+	PingResponseType   = "io.nats.micro.v1.ping_response"
+	StatsResponseType  = "io.nats.micro.v1.stats_response"
+	SchemaResponseType = "io.nats.micro.v1.schema_response"
+)
+
 var (
 	// this regular expression is suggested regexp for semver validation: https://semver.org/
 	semVerRegexp      = regexp.MustCompile(`^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`)
@@ -258,7 +271,10 @@ func AddService(nc *nats.Conn, config Config) (Service, error) {
 		return nil, err
 	}
 
-	ping := Ping(svcIdentity)
+	ping := Ping{
+		ServiceIdentity: svcIdentity,
+		Type:            PingResponseType,
+	}
 
 	infoHandler := func(req *Request) {
 		response, _ := json.Marshal(svc.Info())
@@ -290,6 +306,7 @@ func AddService(nc *nats.Conn, config Config) (Service, error) {
 	schema := SchemaResp{
 		ServiceIdentity: svcIdentity,
 		Schema:          config.Schema,
+		Type:            SchemaResponseType,
 	}
 	schemaHandler := func(req *Request) {
 		response, _ := json.Marshal(schema)
@@ -516,7 +533,7 @@ func restoreAsyncHandlers(nc *nats.Conn, handlers handlers) {
 	nc.SetErrorHandler(handlers.asyncErr)
 }
 
-// ID returns the service instance's unique ID.
+// Info returns information about the service
 func (s *service) Info() Info {
 	return Info{
 		ServiceIdentity: ServiceIdentity{
@@ -524,6 +541,7 @@ func (s *service) Info() Info {
 			ID:      s.id,
 			Version: s.Config.Version,
 		},
+		Type:        InfoResponseType,
 		Description: s.Config.Description,
 		Subject:     s.Config.Endpoint.Subject,
 	}
@@ -543,6 +561,7 @@ func (s *service) Stats() Stats {
 			ID:      info.ID,
 			Version: info.Version,
 		},
+		Type:                  StatsResponseType,
 		NumRequests:           s.stats.NumRequests,
 		NumErrors:             s.stats.NumErrors,
 		ProcessingTime:        s.stats.ProcessingTime,


Test patch:
diff --git a/micro/service_test.go b/micro/service_test.go
index 89e1d18..c739050 100644
--- a/micro/service_test.go
+++ b/micro/service_test.go
@@ -181,6 +181,7 @@ func TestServiceBasics(t *testing.T) {
 	// Reset stats for a service
 	svcs[0].Reset()
 	emptyStats := Stats{
+		Type:            StatsResponseType,
 		ServiceIdentity: svcs[0].Info().ServiceIdentity,
 	}
 
@@ -217,8 +218,11 @@ func TestAddService(t *testing.T) {
 				},
 			},
 			expectedPing: Ping{
-				Name:    "test_service",
-				Version: "0.1.0",
+				Type: PingResponseType,
+				ServiceIdentity: ServiceIdentity{
+					Name:    "test_service",
+					Version: "0.1.0",
+				},
 			},
 		},
 		{
@@ -235,8 +239,11 @@ func TestAddService(t *testing.T) {
 				},
 			},
 			expectedPing: Ping{
-				Name:    "test_service",
-				Version: "0.1.0",
+				Type: PingResponseType,
+				ServiceIdentity: ServiceIdentity{
+					Name:    "test_service",
+					Version: "0.1.0",
+				},
 			},
 		},
 		{
@@ -253,8 +260,11 @@ func TestAddService(t *testing.T) {
 				},
 			},
 			expectedPing: Ping{
-				Name:    "test_service",
-				Version: "0.1.0",
+				Type: PingResponseType,
+				ServiceIdentity: ServiceIdentity{
+					Name:    "test_service",
+					Version: "0.1.0",
+				},
 			},
 			asyncErrorSubject: "test.sub",
 		},
@@ -272,8 +282,11 @@ func TestAddService(t *testing.T) {
 				},
 			},
 			expectedPing: Ping{
-				Name:    "test_service",
-				Version: "0.1.0",
+				Type: PingResponseType,
+				ServiceIdentity: ServiceIdentity{
+					Name:    "test_service",
+					Version: "0.1.0",
+				},
 			},
 			asyncErrorSubject: "$SVC.PING.TEST_SERVICE",
 		},
@@ -297,8 +310,11 @@ func TestAddService(t *testing.T) {
 				errNats <- struct{}{}
 			},
 			expectedPing: Ping{
-				Name:    "test_service",
-				Version: "0.1.0",
+				Type: PingResponseType,
+				ServiceIdentity: ServiceIdentity{
+					Name:    "test_service",
+					Version: "0.1.0",
+				},
 			},
 			asyncErrorSubject: "test.sub",
 		},
@@ -322,8 +338,11 @@ func TestAddService(t *testing.T) {
 				errNats <- struct{}{}
 			},
 			expectedPing: Ping{
-				Name:    "test_service",
-				Version: "0.1.0",
+				Type: PingResponseType,
+				ServiceIdentity: ServiceIdentity{
+					Name:    "test_service",
+					Version: "0.1.0",
+				},
 			},
 		},
 		{
@@ -346,8 +365,11 @@ func TestAddService(t *testing.T) {
 				errNats <- struct{}{}
 			},
 			expectedPing: Ping{
-				Name:    "test_service",
-				Version: "0.1.0",
+				Type: PingResponseType,
+				ServiceIdentity: ServiceIdentity{
+					Name:    "test_service",
+					Version: "0.1.0",
+				},
 			},
 			asyncErrorSubject: "$SVC.PING.TEST_SERVICE",
 		},
@@ -560,33 +582,43 @@ func TestMonitoringHandlers(t *testing.T) {
 			name:    "PING all",
 			subject: "$SRV.PING",
 			expectedResponse: Ping{
-				Name:    "test_service",
-				Version: "0.1.0",
-				ID:      info.ID,
+				Type: PingResponseType,
+				ServiceIdentity: ServiceIdentity{
+					Name:    "test_service",
+					Version: "0.1.0",
+					ID:      info.ID,
+				},
 			},
 		},
 		{
 			name:    "PING name",
 			subject: "$SRV.PING.test_service",
 			expectedResponse: Ping{
-				Name:    "test_service",
-				Version: "0.1.0",
-				ID:      info.ID,
+				Type: PingResponseType,
+				ServiceIdentity: ServiceIdentity{
+					Name:    "test_service",
+					Version: "0.1.0",
+					ID:      info.ID,
+				},
 			},
 		},
 		{
 			name:    "PING ID",
 			subject: fmt.Sprintf("$SRV.PING.test_service.%s", info.ID),
 			expectedResponse: Ping{
-				Name:    "test_service",
-				Version: "0.1.0",
-				ID:      info.ID,
+				Type: PingResponseType,
+				ServiceIdentity: ServiceIdentity{
+					Name:    "test_service",
+					Version: "0.1.0",
+					ID:      info.ID,
+				},
 			},
 		},
 		{
 			name:    "INFO all",
 			subject: "$SRV.INFO",
 			expectedResponse: Info{
+				Type: InfoResponseType,
 				ServiceIdentity: ServiceIdentity{
 					Name:    "test_service",
 					Version: "0.1.0",
@@ -599,6 +631,7 @@ func TestMonitoringHandlers(t *testing.T) {
 			name:    "INFO name",
 			subject: "$SRV.INFO.test_service",
 			expectedResponse: Info{
+				Type: InfoResponseType,
 				ServiceIdentity: ServiceIdentity{
 					Name:    "test_service",
 					Version: "0.1.0",
@@ -611,6 +644,7 @@ func TestMonitoringHandlers(t *testing.T) {
 			name:    "INFO ID",
 			subject: fmt.Sprintf("$SRV.INFO.test_service.%s", info.ID),
 			expectedResponse: Info{
+				Type: InfoResponseType,
 				ServiceIdentity: ServiceIdentity{
 					Name:    "test_service",
 					Version: "0.1.0",
@@ -623,6 +657,7 @@ func TestMonitoringHandlers(t *testing.T) {
 			name:    "SCHEMA all",
 			subject: "$SRV.SCHEMA",
 			expectedResponse: SchemaResp{
+				Type: SchemaResponseType,
 				ServiceIdentity: ServiceIdentity{
 					Name:    "test_service",
 					Version: "0.1.0",
@@ -637,6 +672,7 @@ func TestMonitoringHandlers(t *testing.T) {
 			name:    "SCHEMA name",
 			subject: "$SRV.SCHEMA.test_service",
 			expectedResponse: SchemaResp{
+				Type: SchemaResponseType,
 				ServiceIdentity: ServiceIdentity{
 					Name:    "test_service",
 					Version: "0.1.0",
@@ -651,6 +687,7 @@ func TestMonitoringHandlers(t *testing.T) {
 			name:    "SCHEMA ID",
 			subject: fmt.Sprintf("$SRV.SCHEMA.test_service.%s", info.ID),
 			expectedResponse: SchemaResp{
+				Type: SchemaResponseType,
 				ServiceIdentity: ServiceIdentity{
 					Name:    "test_service",
 					Version: "0.1.0",