Skip to content
Merged
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
31 changes: 29 additions & 2 deletions scripts/lib/openapi-docs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,22 @@ function createRenderer(spec, { baseUrl, tokenPlaceholder, modelsHref }) {
const resp = rawResp.$ref ? resolveRef(rawResp.$ref) : rawResp;
const media = jsonBody(resp);

// An example authored on the response wins outright — it shows the whole
// envelope, including any `meta`, exactly as the API returns it.
// Examples authored on the response win outright — they show the whole
// envelope, including any `meta`, exactly as the API returns it. Where a
// spec authors several, each is one the others cannot stand in for: a
// configured resource beside its unset default, a full page beside an
// empty one. They render in spec order, since `default` is only a key
// here and does not mean "the representative one".
const named = media?.examples;
if (named && typeof named === "object") {
const authoredAll = Object.entries(named).filter(
([, entry]) => entry && "value" in entry
);
if (authoredAll.length > 1) {
return exampleBlocks(successCode, authoredAll);
}
}

const authored = mediaTypeExample(media);
if (authored !== undefined) {
return exampleBlock(successCode, authored);
Expand Down Expand Up @@ -266,6 +280,19 @@ function createRenderer(spec, { baseUrl, tokenPlaceholder, modelsHref }) {
return `\n**Example response \`${code}\`**\n\n\`\`\`json\n${JSON.stringify(body, null, 2)}\n\`\`\`\n`;
}

// Several authored examples under one heading, each captioned with its
// summary so the reader can see which case it is.
function exampleBlocks(code, entries) {
const blocks = entries
.map(([key, entry]) => {
const label = escapeMarkdown(entry.summary ?? key);
const body = JSON.stringify(entry.value, null, 2);
return `\n_${label}_\n\n\`\`\`json\n${body}\n\`\`\`\n`;
})
.join("");
return `\n**Example responses \`${code}\`**\n${blocks}`;
}

// -------------------------------------------------------------------------
// Types and constraints
// -------------------------------------------------------------------------
Expand Down
3 changes: 2 additions & 1 deletion site/dolt/src/content/products/hosted/api/v1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ See [Authentication](/products/hosted/api/v1/authentication) for how to create a
| **PATCH** | `/api/v1/deployments/{owner}/{deployment}/config` | [Change some of a deployment's configuration overrides](/products/hosted/api/v1/deployment#patchDeploymentConfig) |
| **GET** | `/api/v1/deployments/{owner}/{deployment}/logs` | [Read a deployment's logs](/products/hosted/api/v1/deployment#getDeploymentLogs) |
| **PATCH** | `/api/v1/deployments/{owner}/{deployment}/expose` | [Expose or stop exposing the remotesapi or MCP endpoint](/products/hosted/api/v1/deployment#exposeDeploymentService) |
| **GET** | `/api/v1/deployments/{owner}/{deployment}/service-windows` | [List a deployment's service windows](/products/hosted/api/v1/deployment#listDeploymentServiceWindows) |
| **GET** | `/api/v1/deployments/{owner}/{deployment}/metrics` | [List a deployment's metrics](/products/hosted/api/v1/deployment#listDeploymentMetrics) |
| **GET** | `/api/v1/deployments/{owner}/{deployment}/metrics/{metric}` | [Read one of a deployment's metrics](/products/hosted/api/v1/deployment#getDeploymentMetric) |
| **GET** | `/api/v1/deployments/{owner}/{deployment}/backups` | [List a deployment's backups](/products/hosted/api/v1/deployment#listDeploymentBackups) |
Expand Down Expand Up @@ -88,7 +89,7 @@ List endpoints put the pagination cursor in `meta`:

When `meta.next_page_token` is present, pass it back as the `page_token` query parameter to fetch the next page. On the last page `meta` is omitted entirely, so checking whether the token is present is all a client needs — it is never returned present but empty. Page size is fixed and not caller-controlled, so a full page is not itself a sign that another one follows.

Two kinds of list depart from that. A pull request's [comments](/products/hosted/api/v1/pull-request#listDeploymentPullComments) and its [activity log](/products/hosted/api/v1/pull-request#listDeploymentPullLogs), and a deployment's [metrics catalogue](/products/hosted/api/v1/deployment#listDeploymentMetrics), are small enough by nature to be returned whole, so they take no `page_token` at all. And [log retrieval](/products/hosted/api/v1/deployment#getDeploymentLogs) walks a window of history rather than a finite list: it is the only endpoint that pages in both directions, and the only one whose page size you set (`lines`). There `meta.next_page_token` reads further back, `meta.prev_page_token` reads toward the present, both can be present at once, and either can come back on a page with no lines — so stop when a page comes back empty, not when a token is missing.
Two kinds of list depart from that. A pull request's [comments](/products/hosted/api/v1/pull-request#listDeploymentPullComments) and its [activity log](/products/hosted/api/v1/pull-request#listDeploymentPullLogs), and a deployment's [metrics catalogue](/products/hosted/api/v1/deployment#listDeploymentMetrics) and [service windows](/products/hosted/api/v1/deployment#listDeploymentServiceWindows), are small enough by nature to be returned whole, so they take no `page_token` at all. And [log retrieval](/products/hosted/api/v1/deployment#getDeploymentLogs) walks a window of history rather than a finite list: it is the only endpoint that pages in both directions, and the only one whose page size you set (`lines`). There `meta.next_page_token` reads further back, `meta.prev_page_token` reads toward the present, both can be present at once, and either can come back on a page with no lines — so stop when a page comes back empty, not when a token is missing.

Each endpoint's parameters say which of the three it is.

Expand Down
86 changes: 85 additions & 1 deletion site/dolt/src/content/products/hosted/api/v1/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,9 @@ curl -X GET 'https://hosted.doltdb.com/api/v1/deployments/{owner}/{deployment}/l
| `500` | An unexpected server error occurred. | [`Problem`](/products/hosted/api/v1/models#model-problem) |
| `503` | The service is temporarily unavailable. | [`Problem`](/products/hosted/api/v1/models#model-problem) |

**Example response `200`**
**Example responses `200`**

_Two lines with more history available._

```json
{
Expand All @@ -773,6 +775,14 @@ curl -X GET 'https://hosted.doltdb.com/api/v1/deployments/{owner}/{deployment}/l
}
```

_A window with nothing in it._

```json
{
"data": []
}
```

---

## Expose or stop exposing a deployment's remotesapi or MCP endpoint {#exposeDeploymentService}
Expand Down Expand Up @@ -850,6 +860,80 @@ _Stop serving the remotesapi endpoint._

---

## List a deployment's service windows {#listDeploymentServiceWindows}
<span class="api-method" style="background:#29E3C1">GET</span> <code class="api-path">/api/v1/deployments/{owner}/{deployment}/service-windows</code>

Returns the weekly windows in which Hosted may restart the deployment's instances to apply maintenance.

A window covers whole hours in UTC on one day of the week. `start_hour_utc` is inclusive and `end_hour_utc` is exclusive, so 7 and 8 mean the hour beginning 07:00 UTC.

Every deployment has at least one. Until one is set, the list holds a single window with `is_default` set: Sunday 07:00 to 08:00 UTC.


**Parameters**

| Name | In | Type | Required | Description |
|------|----|------|----------|-------------|
| `owner` | path | string | yes | The user or organization that owns the deployment. 3–32 characters of letters, digits, hyphens, and underscores. |
| `deployment` | path | string | yes | The deployment name, unique within the owner. 3–32 characters of letters, digits, hyphens, and underscores. |

**Example request**

```sh
curl -X GET 'https://hosted.doltdb.com/api/v1/deployments/{owner}/{deployment}/service-windows' \
-H 'Authorization: Bearer YOUR_TOKEN'
```

**Responses**

| Status | Description | Schema |
|--------|-------------|--------|
| `200` | The deployment's service windows. | [`ServiceWindow[]`](/products/hosted/api/v1/models#model-servicewindow) |
| `400` | The request was malformed or failed input validation. | [`Problem`](/products/hosted/api/v1/models#model-problem) |
| `401` | Authentication credentials were missing or invalid. | [`Problem`](/products/hosted/api/v1/models#model-problem) |
| `403` | Authenticated, but not permitted to perform this action. | [`Problem`](/products/hosted/api/v1/models#model-problem) |
| `404` | The requested resource does not exist. | [`Problem`](/products/hosted/api/v1/models#model-problem) |
| `405` | The HTTP method is not supported for this resource. | [`Problem`](/products/hosted/api/v1/models#model-problem) |
| `422` | The request was well-formed but semantically invalid. | [`Problem`](/products/hosted/api/v1/models#model-problem) |
| `500` | An unexpected server error occurred. | [`Problem`](/products/hosted/api/v1/models#model-problem) |
| `503` | The service is temporarily unavailable. | [`Problem`](/products/hosted/api/v1/models#model-problem) |

**Example responses `200`**

_A window set for early Tuesday morning UTC._

```json
{
"data": [
{
"id": "7c1e9a3b-2d4f-4a6c-8b0d-1e2f3a4b5c6d",
"day_of_week": "tuesday",
"start_hour_utc": 3,
"end_hour_utc": 5,
"is_default": false
}
]
}
```

_A deployment with no window configured._

```json
{
"data": [
{
"id": "00000000-0000-0000-0000-000000000000",
"day_of_week": "sunday",
"start_hour_utc": 7,
"end_hour_utc": 8,
"is_default": true
}
]
}
```

---

## Disable a deployment {#disableDeployment}
<span class="api-method" style="background:#6DB0FC">POST</span> <code class="api-path">/api/v1/deployments/{owner}/{deployment}/disable</code>

Expand Down
30 changes: 30 additions & 0 deletions site/dolt/src/content/products/hosted/api/v1/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,36 @@ One metric a deployment collects. Read it with `GET /api/v1/deployments/{owner}/

---

## DayOfWeek {#model-dayofweek}
The day of the week a service window falls on, in UTC.

**Enum values**

| Value |
|-------|
| `sunday` |
| `monday` |
| `tuesday` |
| `wednesday` |
| `thursday` |
| `friday` |
| `saturday` |

---

## ServiceWindow {#model-servicewindow}
One weekly window in which Hosted may restart the deployment's instances for maintenance.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `id` | `string` | yes | The window's identifier, unique within the deployment. A default window has no identifier of its own and reports the nil UUID, `00000000-0000-0000-0000-000000000000`. |
| `day_of_week` | [`DayOfWeek`](/products/hosted/api/v1/models#model-dayofweek) | yes | The day of the week a service window falls on, in UTC. |
| `start_hour_utc` | `integer` | yes | The first hour of the window, in UTC. Inclusive. |
| `end_hour_utc` | `integer` | yes | The hour the window ends, in UTC. Exclusive, so a window of 3 to 5 covers 03:00 until 05:00. |
| `is_default` | `boolean` | yes | Whether this is the default window Hosted falls back to rather than one that was configured. `true` means no maintenance window has been set for this deployment. |

---

## DeploymentInstance {#model-deploymentinstance}
One instance backing a deployment. A deployment has a primary and, when it has read replicas, one instance per replica.

Expand Down
168 changes: 168 additions & 0 deletions specs/hosted-v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1328,6 +1328,103 @@ paths:
"503":
$ref: "#/components/responses/ServiceUnavailable"

/api/v1/deployments/{owner}/{deployment}/service-windows:
get:
operationId: listDeploymentServiceWindows
summary: List a deployment's service windows.
description: >-
Returns the weekly windows in which Hosted may restart the deployment's instances to
apply maintenance.


A window covers whole hours in UTC on one day of the week. `start_hour_utc` is
inclusive and `end_hour_utc` is exclusive, so 7 and 8 mean the hour beginning
07:00 UTC.


Every deployment has at least one. Until one is set, the list holds a single window
with `is_default` set: Sunday 07:00 to 08:00 UTC.
tags:
- Deployment
security:
- apiToken: []
parameters:
- name: owner
in: path
required: true
description: >-
The user or organization that owns the deployment. 3–32 characters of letters,
digits, hyphens, and underscores.
schema:
type: string
pattern: "^[-a-zA-Z0-9_]{3,32}$"
example: acme
- name: deployment
in: path
required: true
description: >-
The deployment name, unique within the owner. 3–32 characters of letters,
digits, hyphens, and underscores.
schema:
type: string
pattern: "^[-a-zA-Z0-9_]{3,32}$"
example: analytics
responses:
"200":
description: The deployment's service windows.
headers:
x-request-id:
$ref: "#/components/headers/RequestId"
content:
application/json:
schema:
allOf:
- $ref: "#/components/schemas/Envelope"
- type: object
required:
- data
properties:
data:
type: array
description: The deployment's service windows.
items:
$ref: "#/components/schemas/ServiceWindow"
examples:
configured:
summary: A window set for early Tuesday morning UTC.
value:
data:
- id: 7c1e9a3b-2d4f-4a6c-8b0d-1e2f3a4b5c6d
day_of_week: tuesday
start_hour_utc: 3
end_hour_utc: 5
is_default: false
default:
summary: A deployment with no window configured.
value:
data:
- id: 00000000-0000-0000-0000-000000000000
day_of_week: sunday
start_hour_utc: 7
end_hour_utc: 8
is_default: true
"400":
$ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"405":
$ref: "#/components/responses/MethodNotAllowed"
"422":
$ref: "#/components/responses/UnprocessableEntity"
"500":
$ref: "#/components/responses/InternalServerError"
"503":
$ref: "#/components/responses/ServiceUnavailable"

/api/v1/deployments/{owner}/{deployment}/disable:
post:
operationId: disableDeployment
Expand Down Expand Up @@ -2882,6 +2979,77 @@ components:
- id: cpu
display_name: CPU Utilization

DayOfWeek:
type: string
title: DayOfWeek
description: The day of the week a service window falls on, in UTC.
enum:
- sunday
- monday
- tuesday
- wednesday
- thursday
- friday
- saturday
examples:
- tuesday

ServiceWindow:
type: object
title: ServiceWindow
description: >-
One weekly window in which Hosted may restart the deployment's instances for
maintenance.
required:
- id
- day_of_week
- start_hour_utc
- end_hour_utc
- is_default
properties:
id:
type: string
format: uuid
description: >-
The window's identifier, unique within the deployment. A default window has no
identifier of its own and reports the nil UUID,
`00000000-0000-0000-0000-000000000000`.
examples:
- 7c1e9a3b-2d4f-4a6c-8b0d-1e2f3a4b5c6d
day_of_week:
$ref: "#/components/schemas/DayOfWeek"
start_hour_utc:
type: integer
format: int32
minimum: 0
maximum: 23
description: The first hour of the window, in UTC. Inclusive.
examples:
- 3
end_hour_utc:
type: integer
format: int32
minimum: 0
maximum: 23
description: >-
The hour the window ends, in UTC. Exclusive, so a window of 3 to 5 covers
03:00 until 05:00.
examples:
- 5
is_default:
type: boolean
description: >-
Whether this is the default window Hosted falls back to rather than one that was
configured. `true` means no maintenance window has been set for this deployment.
examples:
- false
examples:
- id: 7c1e9a3b-2d4f-4a6c-8b0d-1e2f3a4b5c6d
day_of_week: tuesday
start_hour_utc: 3
end_hour_utc: 5
is_default: false

DeploymentInstance:
type: object
title: DeploymentInstance
Expand Down