Skip to content

Commit

Permalink
tolerate partial success
Browse files Browse the repository at this point in the history
  • Loading branch information
caindy committed Mar 21, 2024
1 parent 036344a commit 72932f8
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 35 deletions.
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
,"openapi"
,"overvoltage"
,"owasp"
,"Postel"
,"pseudocode"
,"redoc"
,"Redocly"
Expand Down
4 changes: 2 additions & 2 deletions docs/_data/components/schemas/forecast-limit-period.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
period:
type: object
properties:
period-end:
$ref: ./period-start.yaml
period-start:
$ref: ./period-start.yaml
period-end:
$ref: ./period-start.yaml
required:
- period-start
- period-end
Expand Down
3 changes: 3 additions & 0 deletions docs/_data/components/schemas/headers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ proposal-header: &header
properties:
source:
$ref: ./data-provenance.yaml
proposal-begins:
$ref: ./period-start.yaml
default-emergency-durations:
$ref: ./array-max-emergency-durations.yaml#/emergency-durations
power-system-resources:
$ref: ./array-max-monitored-elements.yaml#/named-power-system-resources

required:
- source
- proposal-begins
- default-emergency-durations
- power-system-resources
additionalProperties: false
Expand Down
25 changes: 10 additions & 15 deletions docs/_data/components/schemas/period-start.yaml
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
description: >
RFC 3339 date-time string with *no fractional seconds component* that
designates an operating period (such as an hour) that
starts at a specified time. This will frequently be at the start of an hour,
but may be finer-grained, such as
every 30 minutes, should the Transmission Provider choose.
description: |
If the Transmission Provider is operating in EST, these are
RFC 3339 date-time string with *no fractional seconds component* that
designates a start or end to an operating period (such as an hour) that starts
at a specified time. This will frequently be at the start of an hour, but may
be finer-grained, such as every 30 minutes, should the Clearinghouse Provider
choose.
valid and equivalent values:
If the Transmission Provider is operating in EST, these are valid and
equivalent values:
* 2023-01-01T06:00Z
* 2023-01-01T01:00-5:00
* 2023-01-01T00:00-6:00
* 2023-01-01T11:30+5:30
The server should uniformly represent date-times in the operational time zone
of the Transmission Provider.
of the Clearinghouse Provider.
type: string
format: date-time
maxLength: 25
Expand Down
6 changes: 5 additions & 1 deletion docs/articles/forecast-windows.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ Forecast Window deadline, the TROLIE server returns `202 Accepted` to confirm
that the `PATCH` contained a valid proposal and will be processed by the
Clearinghouse.

{: .nb }
> **NOTE**: The Ratings Provider populates the `proposal-header.proposal-begins`
> to indicate the intended Forecast Window. Accordingly, the TROLIE server
> checks `proposal-header.proposal-begins` to determine if the proposal is late or not.
### Late <i class="fa-solid fa-arrow-right-long"></i> `409 Conflict`

Again, submitting a Ratings Forecast Proposal to TROLIE is done by `PATCH`ing
Expand All @@ -55,7 +60,6 @@ with the server's state, so a `409 Conflict` client error with an appropriate
{% include_relative examples/forecast-proposal-invalid-units.json %}
```


## Forecast Processing State Machine

> When one window closes, another one opens.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"provider": "UTILITY-A",
"origin-id": "5aeacb25-9b65-4738-8a00-ac10afa63640"
},
"proposal-begins": "2025-11-01T01:00:00-05:00",
"default-emergency-durations": [
{
"name": "lte",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"forecast-provider": {
"provider": "UTILITY-A",
"last-updated": "2023-07-12T15:05:43.044267100-07:00",
"origin-id": "5aeacb25-9b65-4738-8a00-ac10afa63640"
},
"incomplete-obligation-count": 0,
"incomplete-obligations": [],
"invalid-proposal-count": 0,
"proposal-validation-errors": []
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"last-updated": "2023-07-12T15:05:43.044267100-07:00",
"origin-id": "5aeacb25-9b65-4738-8a00-ac10afa63640"
},
"incomplete-obligation-count": 150,
"incomplete-obligation-count": 1,
"incomplete-obligations": [
{ "resource-id": "8badf00d",
"alternate-identifiers": [
Expand Down
88 changes: 72 additions & 16 deletions docs/example-narratives/submitting-forecasts.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This article assume some familiarity with HTTP in general and RESTful
APIs in particular ([background](../articles/trolie-for-ems-and-ot)).


### Quick Links
### Scenario Quick Links
{:.no_toc}

* toc
Expand All @@ -21,25 +21,24 @@ APIs in particular ([background](../articles/trolie-for-ems-and-ot)).

## Simplified Example: Transmission Owner Sends Forecast with `curl`

If a Transmission Owner is their own Ratings Provider, they must regularly
regularly (at least hourly) send an Ratings Forecast to their Transmission
Provider. TROLIE provides the
If a Transmission Owner is their own Ratings Provider, they must regularly send
an Ratings Forecast to their Transmission Provider. TROLIE provides the
[patchRatingForecastProposal](../spec#tag/Rating-Proposals/operation/patchRatingForecastProposal)
operation for this purpose.


Assume the Transmission Owner creates a file called `input.json` containing
their forecast. An example of the required format for the file is given below. The format is
one of TROLIE's [supported media types](../articles/supported-media-types)
named `application/vnd.trolie.rating-forecast-proposal.v1+json`.

their forecast. An example of the required format for the file is given below.

```json
{% include_relative examples/forecast-ratings-proposal-patch.json %}
```

(This example also illustrates handling the fall Daylight Savings transition
in the Central timezone.)
This example also illustrates handling the fall Daylight Savings transition in
the Central timezone. The format is one of TROLIE's [supported media
types](../articles/supported-media-types) named
`application/vnd.trolie.rating-forecast-proposal.v1+json`.


### Pushing `input.json` to TROLIE with `curl`
{:.no_toc}
Expand All @@ -55,16 +54,73 @@ curl -d @input.json \
"https://trolie.example.com/rating-proposals/forecast"
```

If this submission is successful, `output.json` will contain a the contents of
the response from TROLIE. The format of the response is defined by another
TROLIE media type:
`application/vnd.trolie.rating-forecast-proposal-status.v1+json`. An example of
this response format is given below:
If this submission is successful, `output.json` will contain the contents of the
response from TROLIE. The format of the response is defined by another TROLIE
media type: `application/vnd.trolie.rating-forecast-proposal-status.v1+json`. An
example of this response format is given below:

```json
{% include_relative examples/forecast-ratings-proposal-status-complete.json %}
```


## Invalid Forecasts for Individual Resources Should be Tolerated

The Robustness Principle, or Postel's Law, states: Be conservative in what you
send and liberal in what you accept. In keeping with this principle, TROLIE
implementations should *not* reject a forecast proposal `PATCH` when only the
forecast for any individual resource is incomplete or invalid. In other words
the Clearinghouse Provider should abide a best effort policy when validating
proposals, and this specification aims to support that policy in an unambiguous
way.

A specific example will help illustrate the idea. Suppose the Ratings Provider
submits a Forecast Proposal for two resources--`8badf00d` and `d34dc0d3`.
Further suppose that there's nothing wrong at all with the `d34dc0d3` forecast,
but the `8badf00d` forecast is missing an hour, with everything else about the
request being valid. In this case TROLIE should a return response like the
following:

```http
HTTP/1.1 202 Accepted
Content-Type: application/vnd.trolie.rating-forecast-proposal-status.v1+json
Server: trolie.example.com
Date: Wed, 29 Feb 2024 12:03:20 GMT
ETag: "123e4567e89b12d3a456426614174000"
X-Rate-Limit-Limit: 100
X-Rate-Limit-Remaining: 97
X-Rate-Limit-Reset: 3400
{% include_relative examples/forecast-ratings-proposal-status.json %}
```

### Pushing `input.json` to TROLIE with `curl`
### Client Errors are Not Acceptable
{:.no_toc}

Bear in mind the proposal must always be [on-time](/articles/forecast-windows.html#on-time--202-accepted). Moreover, there are other client errors that are not tolerated, including:

* Malformed requests, i.e., the JSON provided is not valid according to the
media type schema.
* Unprocessable content error: when the Forecast Proposal is well-formed, but
the [units provided in any of the forecasts are
invalid](/articles/how-units-are-handled#validation).
* Unprocessable content error: when none of the individual resource Forecast
Proposals are valid, but the request is otherwise well-formed.

Additional client errors are identified in the [patchRatingForecastProposal spec](../spec#tag/Rating-Proposals/operation/patchRatingForecastProposal).

### Clients Should Check the `incomplete-obligation-count`
{:.no_toc}

The flip-side of this accommodative approach is that clients will not receive an
error response when one of their resource forecasts is invalid, so the spec
defines `incomplete-obligation-count`:

> {{ site.data.components.schemas["array-max-monitored-elements"].forecast-proposal-status.properties.incomplete-obligation-count.description }}
## Multiple Submissions per Forecast Window

{{ site.data.paths["rating-proposals_forecasts"].patch.description }}


0 comments on commit 72932f8

Please sign in to comment.