-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This is a first take at specifying the Nexus RPC HTTP protocol, changes to be expected.
- Loading branch information
Showing
5 changed files
with
345 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
name: Continuous Integration | ||
|
||
on: # rebuild any PRs and main branch changes | ||
pull_request: | ||
push: | ||
branches: | ||
- main | ||
- "releases/*" | ||
|
||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
jobs: | ||
lint: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: dprint/[email protected] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2023 Temporal Technologies Inc. All Rights Reserved | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Nexus API | ||
|
||
Nexus RPC HTTP Specification. | ||
|
||
## Spec Location | ||
|
||
The specification is edited in the [SPEC.md](./SPEC.md) markdown file. | ||
|
||
## Contributing to this repo | ||
|
||
### Prerequisites | ||
|
||
- [dprint](https://dprint.dev/install/) | ||
|
||
### Check formatting | ||
|
||
```shell | ||
dprint check | ||
``` | ||
|
||
### Format markdown | ||
|
||
```shell | ||
dprint fmt | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,275 @@ | ||
# Nexus RPC HTTP Specification | ||
|
||
## Overview | ||
|
||
The Nexus protocol, as specified below, is a synchronous RPC protocol. Arbitrary length operations are modelled on top | ||
of a set of pre-defined synchronous RPCs. | ||
|
||
A Nexus **caller** calls a **handler**. The handler may respond inline or return a reference for a future, asynchronous | ||
operation. The caller can cancel an asynchronous operation, check for its outcome, or fetch its current state. The caller | ||
can also specify a callback URL, which the handler uses to asynchronously deliver the result of an operation when it | ||
is ready. | ||
|
||
## Operation Addressability | ||
|
||
An operation is addressed using three components: | ||
|
||
- The containing service, a URL prefix (e.g. `http://api.mycompany.com/v1/myservice/`) | ||
- [Operation Name](#operation-name) | ||
- [Operation ID](#operation-id) | ||
|
||
Both the name and ID MUST not be empty and may contain any arbitrary character sequence as long as they're encoded into | ||
the URL. | ||
|
||
## Schema Definitions | ||
|
||
### Failure | ||
|
||
The `Failure` object represents protocol level failures returned in non successful HTTP responses as well as `failed` or | ||
`canceled` operation results. The object MUST adhere to the following JSON schema: | ||
|
||
```yaml | ||
type: object | ||
properties: | ||
message: | ||
type: string | ||
description: A simple text message. | ||
|
||
metadata: | ||
type: object | ||
additionalProperties: | ||
type: string | ||
description: | | ||
A key-value mapping for additional context. Useful for decoding the 'details' field, if needed. | ||
details: | ||
type: any | ||
properties: | ||
description: | | ||
Additional structured data. | ||
``` | ||
### OperationInfo | ||
The `OperationInfo` object MUST adhere to the given schema: | ||
|
||
```yaml | ||
type: object | ||
properties: | ||
id: | ||
type: string | ||
description: | | ||
An identifier for referencing this operation. | ||
state: | ||
enum: | ||
- succeeded | ||
- failed | ||
- canceled | ||
- running | ||
description: | | ||
Describes the current state of an operation. | ||
``` | ||
|
||
## Endpoint Descriptions | ||
|
||
### Start Operation | ||
|
||
Start an arbitrary length operation. | ||
The response of the operation may be delivered synchronously (inline), or asynchronously, via a provided callback or the | ||
[Get Operation Result](#get-operation-result) endpoint. | ||
|
||
**Path**: `/{operation}` | ||
|
||
**Method**: `POST` | ||
|
||
#### Query Parameters | ||
|
||
- `callback`: Optional. If the operation is asynchronous, the handler should invoke this URL once the operation's | ||
result is available. | ||
|
||
#### Request Body | ||
|
||
The body may contain arbitrary data. Headers should specify content type and encoding. | ||
|
||
#### Response Codes | ||
|
||
- `200 OK`: Operation completed successfully. | ||
|
||
**Headers**: | ||
|
||
- `Nexus-Operation-State: succeeded` | ||
|
||
**Body**: Arbitrary data conveying the operation's result. Headers should specify content type and encoding. | ||
|
||
- `201 Created`: Operation was started and will complete asynchronously. | ||
|
||
**Headers**: | ||
|
||
- `Content-Type: application/json` | ||
|
||
**Body**: A JSON serialized [`OperationInfo`](#operationinfo) object. | ||
|
||
- `424 Failed Dependency`: Operation completed as `failed` or `canceled`. | ||
|
||
**Headers**: | ||
|
||
- `Content-Type: application/json` | ||
- `Nexus-Operation-State: failed | canceled` | ||
|
||
**Body**: A JSON serialized [`Failure`](#failure) object. | ||
|
||
- `409 Conflict`: This operation was already started with a different request ID. | ||
|
||
**Headers**: | ||
|
||
- `Content-Type: application/json` | ||
|
||
**Body**: A JSON serialized [`Failure`](#failure) object. | ||
|
||
### Cancel Operation | ||
|
||
Request to cancel an operation. | ||
The operation may later complete as canceled or any other outcome. | ||
Handlers should ignore multiple cancelations of the same operation and return successfully if cancelation was already | ||
requested. | ||
|
||
**Path**: `/{operation}/{operation_id}/cancel` | ||
|
||
**Method**: `POST` | ||
|
||
#### Response Codes | ||
|
||
- `202 Accepted`: Cancelation request accepted. | ||
|
||
**Body**: Empty. | ||
|
||
- `404 Not Found`: Operation ID not recognized or references deleted. | ||
|
||
**Headers**: | ||
|
||
- `Content-Type: application/json` | ||
|
||
**Body**: A JSON serialized [`Failure`](#failure) object. | ||
|
||
### Get Operation Result | ||
|
||
Retrieve operation result. | ||
|
||
**Path**: `/{operation}/{operation_id}/result` | ||
|
||
**Method**: `GET` | ||
|
||
#### Query Parameters | ||
|
||
- `wait`: Optional. Duration indicating the waiting period for a result, defaulting to no wait. | ||
If by the end of the wait period the operation is still running, the request should resolve with a 412 status code | ||
(see below). | ||
|
||
Format of this parameter is number + unit, where unit can be `ms` for milliseconds, `s` for seconds, and `m` for | ||
minutes. Examples: | ||
|
||
- `100ms` | ||
- `1m` | ||
- `5s` | ||
|
||
#### Response Codes | ||
|
||
- `200 OK`: Operation completed successfully. | ||
|
||
**Headers**: | ||
|
||
- `Nexus-Operation-State: succeeded` | ||
|
||
**Body**: Arbitrary data conveying the operation's result. Headers should specify content type and encoding. | ||
|
||
- `408 Request Timeout`: The server gave up waiting for operation completion. The request may be retried by the caller. | ||
|
||
**Body**: Empty. | ||
|
||
- `412 Precondition Failed`: Operation still running. | ||
|
||
When waiting for completion, the caller may re-issue this request to start a new long poll. | ||
|
||
**Body**: Empty. | ||
|
||
- `424 Failed Dependency`: Operation completed as `failed` or `canceled`. | ||
|
||
**Headers**: | ||
|
||
- `Content-Type: application/json` | ||
- `Nexus-Operation-State: failed | canceled` | ||
|
||
**Body**: A JSON serialized [`Failure`](#failure) object. | ||
|
||
- `404 Not Found`: Operation ID not recognized or references deleted. | ||
|
||
**Headers**: | ||
|
||
- `Content-Type: application/json` | ||
|
||
**Body**: A JSON serialized [`Failure`](#failure) object. | ||
|
||
### Get Operation Info | ||
|
||
Retrieve operation details. | ||
|
||
**Path**: `/{operation}/{operation_id}` | ||
|
||
**Method**: `GET` | ||
|
||
#### Response Codes | ||
|
||
- `200 OK`: Successfully retrieved info. | ||
|
||
**Headers**: | ||
|
||
- `Content-Type: application/json` | ||
|
||
**Body**: | ||
|
||
A JSON serialized [`OperationInfo`](#operationinfo) object. | ||
|
||
- `404 Not Found`: Operation ID not recognized or references deleted. | ||
|
||
**Headers**: | ||
|
||
- `Content-Type: application/json` | ||
|
||
**Body**: A JSON serialized [`Failure`](#failure) object. | ||
|
||
## General Information on HTTP Response Codes | ||
|
||
The Nexus protocol follows standard HTTP practices, response codes not specified here should be interpreted according to | ||
the HTTP specification. | ||
|
||
## Callback URLs | ||
|
||
Any HTTP URL can be used to deliver operation completions. | ||
|
||
Callers should ensure URLs contain sufficient information to correlate completions with initiators. | ||
|
||
For invoking a callback URL: | ||
|
||
- Issue a POST request to the caller-provided URL. | ||
- Include the `Nexus-Operation-State` header. | ||
- If state is `succeeded`, deliver non-empty results in the body with corresponding `Content-*` headers. | ||
- If state is `failed` or `canceled`, content type should be `application/json` and the body must have a serialized | ||
[`Failure`](#failure) object. | ||
- Upon successful completion delivery, the handler should reply with a `200 OK` status and an empty body. | ||
|
||
### Security | ||
|
||
There's no enforced security for callback URLs at this time. However, some specific Nexus server implementations may | ||
deliver additional details as headers or have other security requirements of the callback endpoint. | ||
When starting an operation, callers may embed a signed token into the URL, which can be verified upon delivery of | ||
completion. | ||
|
||
[rfc3986-section-2.3]: https://datatracker.ietf.org/doc/html/rfc3986#section-2.3 | ||
|
||
## Q/A | ||
|
||
1. What potential security concerns should be taken into consideration while implementing this protocol? | ||
|
||
Security is not part of this specification, but as this is a thin layer on top of HTTP, standard practices should be | ||
used to secure these APIs. For securing callback URLs, see [Callback URLs > Security](#security). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"markdown": {}, | ||
"includes": ["*.md"], | ||
"excludes": [], | ||
"plugins": ["https://plugins.dprint.dev/markdown-0.15.3.wasm"] | ||
} |