Skip to content

Commit

Permalink
Update Nexus Incoming Service CRUD to match Cloud API (#372)
Browse files Browse the repository at this point in the history
  • Loading branch information
bergundy authored Mar 19, 2024
1 parent 905672f commit c43384d
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 52 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
SHELL=/bin/bash -o pipefail

$(VERBOSE).SILENT:
############################# Main targets #############################
ci-build: install proto http-api-docs
Expand Down
4 changes: 3 additions & 1 deletion buf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ breaking:
- WIRE_JSON
ignore:
- google
# Uncomment this after https://github.com/temporalio/api/pull/362 is merged
# Uncomment this after https://github.com/temporalio/api/pull/372 has been merged.
- temporal/api/operatorservice/v1/request_response.proto
- temporal/api/operatorservice/v1/service.proto
- temporal/api/nexus/v1/message.proto
lint:
use:
- DEFAULT
Expand Down
61 changes: 54 additions & 7 deletions openapi/openapiv2.json
Original file line number Diff line number Diff line change
Expand Up @@ -3982,20 +3982,20 @@
}
}
},
"v1CreateNexusOutgoingServiceResponse": {
"v1CreateNexusIncomingServiceResponse": {
"type": "object",
"properties": {
"service": {
"$ref": "#/definitions/v1OutgoingService",
"$ref": "#/definitions/v1IncomingService",
"description": "Data post acceptance. Can be used to issue additional updates to this record."
}
}
},
"v1CreateOrUpdateNexusIncomingServiceResponse": {
"v1CreateNexusOutgoingServiceResponse": {
"type": "object",
"properties": {
"service": {
"$ref": "#/definitions/v1IncomingService",
"$ref": "#/definitions/v1OutgoingService",
"description": "Data post acceptance. Can be used to issue additional updates to this record."
}
}
Expand Down Expand Up @@ -4740,11 +4740,39 @@
"version": {
"type": "string",
"format": "int64",
"description": "Data version for this service, incremented for every update issued via the CreateOrUpdateNexusIncomingService\nAPI."
"description": "Data version for this service, incremented for every update issued via the UpdateNexusIncomingService API."
},
"id": {
"type": "string",
"description": "Unique server-generated service ID."
},
"spec": {
"$ref": "#/definitions/v1IncomingServiceSpec",
"description": "Spec for the service."
},
"createdTime": {
"type": "string",
"format": "date-time",
"description": "The date and time when the service was created."
},
"lastModifiedTime": {
"type": "string",
"format": "date-time",
"description": "The date and time when the service was last modified.\nWill not be set if the service has never been modified."
},
"urlPrefix": {
"type": "string",
"description": "Server exposed URL prefix for invocation of operations on this service.\nThis doesn't include the protocol, hostname or port as the server does not know how it should be accessed\npublicly. The URL is stable in the face of service renames."
}
},
"description": "A cluster-global binding from a service ID to namespace, task queue, and metadata for dispatching incoming Nexus\nrequests."
},
"v1IncomingServiceSpec": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Service name, unique for this cluster.\nThe service name is used to address this service.\nBy default, when using Nexus over HTTP, the service name is matched against the base URL path.\nE.g. the URL /api/v1/services/my-service/ would match a service named \"my-service\".\nThe name must match `[a-zA-Z_][a-zA-Z0-9_]*`."
"description": "Service name, unique for this cluster. Must match `[a-zA-Z_][a-zA-Z0-9_]*`."
},
"namespace": {
"type": "string",
Expand All @@ -4762,7 +4790,7 @@
"description": "Generic service metadata that is available to the server's authorizer."
}
},
"description": "A binding from a service name to namespace, task queue, and metadata for dispatching incoming Nexus requests."
"description": "Contains mutable fields for an IncomingService."
},
"v1IndexedValueType": {
"type": "string",
Expand Down Expand Up @@ -5329,6 +5357,16 @@
"spec": {
"$ref": "#/definitions/v1OutgoingServiceSpec",
"description": "Spec for the service."
},
"createdTime": {
"type": "string",
"format": "date-time",
"description": "The date and time when the service was created."
},
"lastModifiedTime": {
"type": "string",
"format": "date-time",
"description": "The date and time when the service was last modified.\nWill not be set if the service has never been modified."
}
},
"description": "A per-namespace binding from service name to URL that is used by the service to invoke Nexus requests that are\ninitiated by workflows."
Expand Down Expand Up @@ -7404,6 +7442,15 @@
}
}
},
"v1UpdateNexusIncomingServiceResponse": {
"type": "object",
"properties": {
"service": {
"$ref": "#/definitions/v1IncomingService",
"description": "Data post acceptance. Can be used to issue additional updates to this record."
}
}
},
"v1UpdateNexusOutgoingServiceResponse": {
"type": "object",
"properties": {
Expand Down
57 changes: 44 additions & 13 deletions temporal/api/nexus/v1/message.proto
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ option csharp_namespace = "Temporalio.Api.Nexus.V1";

import "google/protobuf/any.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
import "temporal/api/common/v1/message.proto";

// A general purpose failure message.
Expand Down Expand Up @@ -118,26 +119,45 @@ message Response {
}
}

// A binding from a service name to namespace, task queue, and metadata for dispatching incoming Nexus requests.
// A cluster-global binding from a service ID to namespace, task queue, and metadata for dispatching incoming Nexus
// requests.
message IncomingService {
// Data version for this service, incremented for every update issued via the CreateOrUpdateNexusIncomingService
// API.
// Data version for this service, incremented for every update issued via the UpdateNexusIncomingService API.
int64 version = 1;
// Service name, unique for this cluster.
// The service name is used to address this service.
// By default, when using Nexus over HTTP, the service name is matched against the base URL path.
// E.g. the URL /api/v1/services/my-service/ would match a service named "my-service".
// The name must match `[a-zA-Z_][a-zA-Z0-9_]*`.
string name = 2;
// Unique server-generated service ID.
string id = 2;
// Spec for the service.
IncomingServiceSpec spec = 3;

// The date and time when the service was created.
// (-- api-linter: core::0142::time-field-names=disabled
// aip.dev/not-precedent: Not following linter rules. --)
google.protobuf.Timestamp created_time = 4;

// The date and time when the service was last modified.
// Will not be set if the service has never been modified.
// (-- api-linter: core::0142::time-field-names=disabled
// aip.dev/not-precedent: Not following linter rules. --)
google.protobuf.Timestamp last_modified_time = 5;

// Server exposed URL prefix for invocation of operations on this service.
// This doesn't include the protocol, hostname or port as the server does not know how it should be accessed
// publicly. The URL is stable in the face of service renames.
string url_prefix = 6;
}

// Contains mutable fields for an IncomingService.
message IncomingServiceSpec {
// Service name, unique for this cluster. Must match `[a-zA-Z_][a-zA-Z0-9_]*`.
string name = 1;
// Namespace to route requests to.
string namespace = 3;
string namespace = 2;
// Task queue to route requests to.
string task_queue = 4;
string task_queue = 3;
// Generic service metadata that is available to the server's authorizer.
map<string, google.protobuf.Any> metadata = 5;
map<string, google.protobuf.Any> metadata = 4;
}


// A per-namespace binding from service name to URL that is used by the service to invoke Nexus requests that are
// initiated by workflows.
message OutgoingService {
Expand All @@ -147,6 +167,17 @@ message OutgoingService {
string name = 2;
// Spec for the service.
OutgoingServiceSpec spec = 3;

// The date and time when the service was created.
// (-- api-linter: core::0142::time-field-names=disabled
// aip.dev/not-precedent: Not following linter rules. --)
google.protobuf.Timestamp created_time = 4;

// The date and time when the service was last modified.
// Will not be set if the service has never been modified.
// (-- api-linter: core::0142::time-field-names=disabled
// aip.dev/not-precedent: Not following linter rules. --)
google.protobuf.Timestamp last_modified_time = 5;
}

// Contains mutable fields for an OutgoingService.
Expand Down
49 changes: 28 additions & 21 deletions temporal/api/operatorservice/v1/request_response.proto
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ option csharp_namespace = "Temporalio.Api.OperatorService.V1";

import "temporal/api/enums/v1/common.proto";
import "temporal/api/nexus/v1/message.proto";
import "google/protobuf/any.proto";
import "google/protobuf/duration.proto";

// (-- Search Attribute --)
Expand Down Expand Up @@ -128,39 +127,43 @@ message ClusterMetadata {
}

message GetNexusIncomingServiceRequest {
// Name of service to retrieve.
string name = 1;
// Server-generated unique service ID.
string id = 1;
}

message GetNexusIncomingServiceResponse {
temporal.api.nexus.v1.IncomingService service = 1;
}

message CreateOrUpdateNexusIncomingServiceRequest {
// Data version for this service. Must match current version on update or set to 0 to create a new service.
int64 version = 1;
// Service name, unique for this cluster.
// The service name is used to address this service.
// By default, when using Nexus over HTTP, the service name is matched against the base URL path.
// E.g. the URL /api/v1/services/my-service/ would match a service named "my-service".
// The name must match `[a-zA-Z_][a-zA-Z0-9_]*`.
string name = 2;
// Namespace to route requests to.
string target_namespace = 3;
// Task queue to route requests to.
string target_task_queue = 4;
// Generic service metadata that is available to the server's authorizer.
map<string, google.protobuf.Any> metadata = 5;
message CreateNexusIncomingServiceRequest {
// Service definition to create.
temporal.api.nexus.v1.IncomingServiceSpec spec = 1;
}

message CreateNexusIncomingServiceResponse {
// Data post acceptance. Can be used to issue additional updates to this record.
temporal.api.nexus.v1.IncomingService service = 1;
}

message CreateOrUpdateNexusIncomingServiceResponse {
message UpdateNexusIncomingServiceRequest {
// Server-generated unique service ID.
string id = 1;
// Data version for this service. Must match current version.
int64 version = 2;

temporal.api.nexus.v1.IncomingServiceSpec spec = 3;
}

message UpdateNexusIncomingServiceResponse {
// Data post acceptance. Can be used to issue additional updates to this record.
temporal.api.nexus.v1.IncomingService service = 1;
}

message DeleteNexusIncomingServiceRequest {
// Name of service to delete.
string name = 1;
// Server-generated unique service ID.
string id = 1;
// Data version for this service. Must match current version.
int64 version = 2;
}

message DeleteNexusIncomingServiceResponse {
Expand All @@ -172,6 +175,10 @@ message ListNexusIncomingServicesRequest {
// response, the token will be empty if there's no other page.
// Note: the last page may be empty if the total number of services registered is a multiple of the page size.
bytes next_page_token = 2;
// Name of the incoming service to filter on - optional. Specifying this will result in zero or one results.
// (-- api-linter: core::203::field-behavior-required=disabled
// aip.dev/not-precedent: Not following linter rules. --)
string name = 3;
}

message ListNexusIncomingServicesResponse {
Expand Down
29 changes: 19 additions & 10 deletions temporal/api/operatorservice/v1/service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -78,23 +78,32 @@ service OperatorService {
rpc ListClusters(ListClustersRequest) returns (ListClustersResponse) {
}

// Get a registered incoming Nexus service by name. The returned version can be used for optimistic updates.
// Get a registered incoming Nexus service by ID. The returned version can be used for optimistic updates.
rpc GetNexusIncomingService(GetNexusIncomingServiceRequest) returns (GetNexusIncomingServiceResponse) {
}

// Optimistically create or update a Nexus service based on provided version.
// To update an existing service, get the current service record via the `GetNexusIncomingService` API, modify it
// and submit to this API.
// Set version to 0 to create a new service.
// Returns the updated service with the updated version, which can be used for subsequent updates.
rpc CreateOrUpdateNexusIncomingService(CreateOrUpdateNexusIncomingServiceRequest) returns (CreateOrUpdateNexusIncomingServiceResponse) {
// Create a Nexus service. This will fail if a service with the same name already exists in the namespace with a
// status of ALREADY_EXISTS.
// Returns the created service with its initial version. You may use this version for subsequent updates.
rpc CreateNexusIncomingService(CreateNexusIncomingServiceRequest) returns (CreateNexusIncomingServiceResponse) {
}

// Optimistically update a Nexus service based on provided version as obtained via the
// `GetNexusIncomingService` or `ListNexusOutgoingServicesResponse` APIs. This will fail with a status of
// FAILED_PRECONDITION if the version does not match.
// Returns the updated service with its updated version. You may use this version for subsequent updates. You don't
// need to increment the version yourself. The server will increment the version for you after each update.
rpc UpdateNexusIncomingService(UpdateNexusIncomingServiceRequest) returns (UpdateNexusIncomingServiceResponse) {
}

// Delete an incoming Nexus service by name.
// Delete an incoming Nexus service by ID.
rpc DeleteNexusIncomingService(DeleteNexusIncomingServiceRequest) returns (DeleteNexusIncomingServiceResponse) {
}

// List all Nexus incoming services in the cluster. Use next_page_token in the response for pagination.
// List all Nexus incoming services for the cluster, sorted by service ID in ascending order. Set page_token in the
// request to the next_page_token field of the previous response to get the next page of results. An empty
// next_page_token indicates that there are no more results. During pagination, a newly added service with an ID
// lexicographically earlier than the previous page's last service name may be missed.
rpc ListNexusIncomingServices(ListNexusIncomingServicesRequest) returns (ListNexusIncomingServicesResponse) {
}

Expand All @@ -105,7 +114,7 @@ service OperatorService {

// Create a Nexus service. This will fail if a service with the same name already exists in the namespace with a
// status of ALREADY_EXISTS.
// Returns the updated service with its initial version. You may use this version for subsequent updates. You don't
// Returns the created service with its initial version. You may use this version for subsequent updates. You don't
// need to increment the version yourself. The server will increment the version for you after each update.
rpc CreateNexusOutgoingService(CreateNexusOutgoingServiceRequest) returns (CreateNexusOutgoingServiceResponse) {
}
Expand Down

0 comments on commit c43384d

Please sign in to comment.