Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/_typos.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Configuration for typos spell checker
# See: https://github.com/crate-ci/typos

[default]
# Ensure we check binary file names
binary = false


[default.extend-words]
# Add custom dictionary entries here for intentional "misspellings" used in the codebase
# Common Go/Nexus specific terms that may be flagged as typos
cancelation = "cancelation" # Common alternate spelling of cancellation used in the spec

[files]
extend-exclude = [
"*.svg",
]

8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,11 @@ jobs:
steps:
- uses: actions/checkout@v3
- uses: dprint/check@v2.2

typos:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: crate-ci/typos@v1
with:
config: ./.github/workflows/_typos.toml
51 changes: 30 additions & 21 deletions SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The Nexus protocol, as specified below, is a synchronous RPC protocol for system
duration operations are modelled on top of a set of pre-defined synchronous RPCs.

A Nexus **caller** calls a **handler**. The handler may respond inline (synchronous response) or return a token
referencing the ongoing operation (asynchronous response), which the the caller use to cancel the operation. In lieu of
referencing the ongoing operation (asynchronous response), which the caller may use to cancel the operation. In lieu of
a higher level service contract, the caller cannot determine whether an operation is going to resolve synchronously or
asynchronously, and should specify a callback URL, which the handler uses to deliver the result of an asynchronous
operation when it is ready.
Expand Down Expand Up @@ -111,6 +111,10 @@ Headers that start with the `Nexus-Callback-` prefix are expected to be attached
the handler. The callback request must strip away the `Nexus-Callback-` prefix. E.g if a Start Operation request
includes a `Nexus-Callback-Token: some-token` header, the callback request would include a `Token: some-token` header.

If a callback query parameter is provided, the `Nexus-Callback-Token` header is **OPTIONAL**. It MAY contain a
caller-generated token that is used to recreate context when processing the callback. Handlers MUST include this
header’s value as a `Token` header when invoking Callback requests.

The `Operation-Timeout` header field can be added to inform the handler how long the caller is willing to wait for an
operation to complete. This is distinct from the more general `Request-Timeout` header which is used to indicate the
timeout for a single HTTP request. Format of this header value is number + unit, where unit can be `ms` for
Expand Down Expand Up @@ -156,7 +160,7 @@ The body may contain arbitrary data. Headers should specify content type and enc
### 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.
ignore multiple cancellations of the same operation and return successfully if cancellation was already requested.

**Path**: `/{service}/{operation}/cancel`

Expand Down Expand Up @@ -197,7 +201,7 @@ Operation Error [`Failure`](#failure) representation is as follows:
"cause": { /* <Optional cause> */ },
"details": {
"state": "canceled | failed",
// Aribtrary details may be added here as needed.
// Arbitrary details may be added here as needed.
},
}
```
Expand All @@ -221,33 +225,33 @@ Handler Error [`Failure`](#failure) representation is as follows:
"details": {
"type": "<predefined error type (e.g. INTERNAL)",
// "retryableOverride": Optional boolean.
// Aribtrary details may be added here as needed.
// Arbitrary details may be added here as needed.
},
}
```

### Predefined Handler Errors

For compatiblity of this HTTP spec with future transports, when a handler fails a request, it **should** use one of the
For compatibility of this HTTP spec with future transports, when a handler fails a request, it **should** use one of the
following predefined error codes.

| Name | Status Code | Description |
| -------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `BAD_REQUEST` | 400 | The handler cannot or will not process the request due to an apparent client error. Clients should not retry this request unless advised otherwise. |
| `UNAUTHENTICATED` | 401 | The client did not supply valid authentication credentials for this request. Clients should not retry this request unless advised otherwise. |
| `UNAUTHORIZED` | 403 | The caller does not have permission to execute the specified operation. Clients should not retry this request unless advised otherwise. |
| `NOT_FOUND` | 404 | The requested resource could not be found but may be available in the future. Subsequent requests by the client are permissible but not advised. |
| `REQUEST_TIMEOUT` | 408 | Returned by the server to when it has given up handling a request. The may occur by enforcing a client provided `Request-Timeout` or for any arbitrary reason such as enforcing some configurable limit. Subsequent requests by the client are permissible. |
| `CONFLICT` | 409 | The request could not be made due to a conflict. The may happen when trying to create an operation that has already been started. Clients should not retry this request unless advised otherwise. |
| `RESOURCE_EXHAUSTED` | 429 | Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system is out of space. Subsequent requests by the client are permissible. |
| `INTERNAL` | 500 | An internal error occured. Subsequent requests by the client are permissible. |
| `NOT_IMPLEMENTED` | 501 | The handler either does not recognize the request method, or it lacks the ability to fulfill the request. Clients should not retry this request unless advised otherwise. |
| `UNAVAILABLE` | 503 | The service is currently unavailable. Subsequent requests by the client are permissible. |
| `UPSTREAM_TIMEOUT` | 520 | Used by gateways to report that a request to an upstream handler has timed out. Subsequent requests by the client are permissible. |
| Name | Status Code | Description |
| -------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `BAD_REQUEST` | 400 | The handler cannot or will not process the request due to an apparent client error. Clients should not retry this request unless advised otherwise. |
| `UNAUTHENTICATED` | 401 | The client did not supply valid authentication credentials for this request. Clients should not retry this request unless advised otherwise. |
| `UNAUTHORIZED` | 403 | The caller does not have permission to execute the specified operation. Clients should not retry this request unless advised otherwise. |
| `NOT_FOUND` | 404 | The requested resource could not be found but may be available in the future. Subsequent requests by the client are permissible but not advised. |
| `REQUEST_TIMEOUT` | 408 | Returned by the server to when it has given up handling a request. This may occur by enforcing a client provided `Request-Timeout` or for any arbitrary reason such as enforcing some configurable limit. Subsequent requests by the client are permissible. |
| `CONFLICT` | 409 | The request could not be made due to a conflict. This may happen when trying to create an operation that has already been started. Clients should not retry this request unless advised otherwise. |
| `RESOURCE_EXHAUSTED` | 429 | Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system is out of space. Subsequent requests by the client are permissible. |
| `INTERNAL` | 500 | An internal error occurred. Subsequent requests by the client are permissible. |
| `NOT_IMPLEMENTED` | 501 | The handler either does not recognize the request method, or it lacks the ability to fulfill the request. Clients should not retry this request unless advised otherwise. |
| `UNAVAILABLE` | 503 | The service is currently unavailable. Subsequent requests by the client are permissible. |
| `UPSTREAM_TIMEOUT` | 520 | Used by gateways to report that a request to an upstream handler has timed out. Subsequent requests by the client are permissible. |

Client implementations should try to rehydrate a `HandlerError` from the serialized `Failure` object in the response
body whenever a request fails with one of the status codes listed below. If the handler error type in the `Failure`
object details doesn't match the response status code, the `Failure` object takes precendence.
object details doesn't match the response status code, the `Failure` object takes precedence.

If the serialized `Failure` does not represent a `HandlerError`, clients should construct a wrapper `HandlerError`,
setting the response `Failure` as the `cause` (if available) translating the response status code to the `HandlerError`
Expand Down Expand Up @@ -292,14 +296,19 @@ For invoking a callback URL:
- Issue a POST request to the caller-provided URL.
- Include any callback headers supplied in the originating StartOperation request, stripping away the `Nexus-Callback-`
prefix.

- The callback request **MUST include** a `Token` header derived from the required `Nexus-Callback-Token` header in the
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm wondering if we want to call it Nexus-Callback-Token on the callback side too because Token is a bit vague.

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, I agree. A sizable number of exception cases is hard to hold in your head as well. Not sure if we could change it now but Nexus-Callback-Token -> Nexus-Token seems a bit more clear.

Copy link
Author

Choose a reason for hiding this comment

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

Suggested change
- The callback request **MUST include** a `Token` header derived from the required `Nexus-Callback-Token` header in the
- The callback request **MUST include** the `Nexus-Callback-Token` header in the

originating StartOperation request. This header uniquely associates the callback with its originating operation and is
mandatory for all callback deliveries.

- Include the following headers for resources associated with this operation to support completing asynchronous
operations before the response to StartOperation is received:
- `Nexus-Operation-Token`
- `Nexus-Operation-Start-Time`
- any `Nexus-Link` headers
- The `Nexus-Operation-Start-Time` header should be in a valid HTTP format described
[here](https://www.rfc-editor.org/rfc/rfc5322.html#section-3.3). If is omitted, the time the completion is received
will be used as operation start time.
[here](https://www.rfc-editor.org/rfc/rfc5322.html#section-3.3). If omitted, the time the completion is received will
be used as operation start time.
- Include a `Nexus-Operation-Close-Time` header, indicating the time when the operation completed (either successfully
or unsuccessfully). The header's value must be a
[valid RFC 3339 format timestamp](https://datatracker.ietf.org/doc/html/rfc3339#section-5), with a resolution of
Expand Down