diff --git a/pyproject.toml b/pyproject.toml index 6f5784c..8b0dedf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ license-files = ["LICENSE"] requires-python = ">=3.11" dependencies = [ "h2>=4.1.0", - "protobuf>=5.29.0", + "protobuf>=6.31.1,<7.0.0", "zstandard>=0.23.0", ] diff --git a/s2-specs b/s2-specs new file mode 160000 index 0000000..a47ed3e --- /dev/null +++ b/s2-specs @@ -0,0 +1 @@ +Subproject commit a47ed3e27d3aef295b6b4fedeeee678a86f4dc0d diff --git a/s2-specs/.github/workflows/dispatch.yaml b/s2-specs/.github/workflows/dispatch.yaml deleted file mode 100644 index 7f43277..0000000 --- a/s2-specs/.github/workflows/dispatch.yaml +++ /dev/null @@ -1,32 +0,0 @@ -name: Trigger s2-specs-update for downstream repos -on: - push: - branches: - - main - paths: - - "s2/**" -jobs: - dispatch: - strategy: - matrix: - repo: - - "s2-streamstore/docs" - - "s2-streamstore/s2" - - "s2-streamstore/s2-sdk-typescript" - - "s2-streamstore/s2-sdk-go" - - "s2-streamstore/s2-sdk-python" - runs-on: ubuntu-latest - steps: - - uses: actions/create-github-app-token@v1 - id: app-token - with: - app-id: ${{ secrets.APP_ID }} - private-key: ${{ secrets.APP_SECRET_KEY }} - owner: ${{ github.repository_owner }} - - name: Repository Dispatch - uses: peter-evans/repository-dispatch@v3 - with: - token: ${{ steps.app-token.outputs.token }} - repository: ${{ matrix.repo }} - event-type: s2-specs-update - client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}"}' diff --git a/s2-specs/README.md b/s2-specs/README.md deleted file mode 100644 index a8fb185..0000000 --- a/s2-specs/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# S2 specs - -- OpenAPI specification -- Protobuf messages -- Session protocol (`s2s`) - -The current API version is [v1](s2/v1). - -You can also refer to the [s2.dev docsite](https://s2.dev/docs/api). diff --git a/s2-specs/buf.yaml b/s2-specs/buf.yaml deleted file mode 100644 index c9f06f7..0000000 --- a/s2-specs/buf.yaml +++ /dev/null @@ -1,15 +0,0 @@ -version: v2 - -modules: - - name: buf.build/streamstore/s2 - lint: - use: - - STANDARD - - COMMENTS - except: - - COMMENT_ENUM - - COMMENT_MESSAGE - -breaking: - use: - - WIRE diff --git a/s2-specs/s2/v1/openapi.json b/s2-specs/s2/v1/openapi.json deleted file mode 100644 index c971f8e..0000000 --- a/s2-specs/s2/v1/openapi.json +++ /dev/null @@ -1,3277 +0,0 @@ -{ - "openapi": "3.1.0", - "info": { - "title": "S2, the durable streams API", - "description": "Streams as a cloud storage primitive.", - "termsOfService": "https://s2.dev/terms", - "contact": { - "email": "support@s2.dev" - }, - "license": { - "name": "MIT" - }, - "version": "1.0.0" - }, - "servers": [ - { - "url": "https://aws.s2.dev/v1" - } - ], - "paths": { - "/access-tokens": { - "get": { - "tags": [ - "access-tokens" - ], - "summary": "List access tokens.", - "operationId": "list_access_tokens", - "parameters": [ - { - "name": "prefix", - "in": "query", - "description": "Filter to access tokens whose IDs begin with this prefix.", - "required": false, - "schema": { - "type": "string", - "default": "" - } - }, - { - "name": "start_after", - "in": "query", - "description": "Filter to access tokens whose IDs lexicographically start after this string.", - "required": false, - "schema": { - "type": "string", - "default": "" - } - }, - { - "name": "limit", - "in": "query", - "description": "Number of results, up to a maximum of 1000.", - "required": false, - "schema": { - "type": "integer", - "default": 1000, - "maximum": 1000, - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListAccessTokensResponse" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - }, - "post": { - "tags": [ - "access-tokens" - ], - "summary": "Issue a new access token.", - "operationId": "issue_access_token", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AccessTokenInfo" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IssueAccessTokenResponse" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "409": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - } - }, - "/access-tokens/{id}": { - "delete": { - "tags": [ - "access-tokens" - ], - "summary": "Revoke an access token.", - "operationId": "revoke_access_token", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Access token ID.", - "required": true, - "schema": { - "$ref": "#/components/schemas/AccessTokenIdStr" - } - } - ], - "responses": { - "204": { - "description": "" - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - } - }, - "/basins": { - "get": { - "tags": [ - "basins" - ], - "summary": "List basins.", - "operationId": "list_basins", - "parameters": [ - { - "name": "prefix", - "in": "query", - "description": "Filter to basins whose names begin with this prefix.", - "required": false, - "schema": { - "type": "string", - "default": "" - } - }, - { - "name": "start_after", - "in": "query", - "description": "Filter to basins whose names lexicographically start after this string.\nIt must be greater than or equal to the `prefix` if specified.", - "required": false, - "schema": { - "type": "string", - "default": "" - } - }, - { - "name": "limit", - "in": "query", - "description": "Number of results, up to a maximum of 1000.", - "required": false, - "schema": { - "type": "integer", - "default": 1000, - "maximum": 1000, - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListBasinsResponse" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - }, - "post": { - "tags": [ - "basins" - ], - "summary": "Create a basin.", - "operationId": "create_basin", - "parameters": [ - { - "name": "s2-request-token", - "in": "header", - "description": "Client-specified request token for idempotent retries.", - "required": false, - "schema": { - "$ref": "#/components/schemas/RequestToken" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateBasinRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BasinInfo" - } - } - } - }, - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BasinInfo" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "409": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - } - }, - "/basins/{basin}": { - "get": { - "tags": [ - "basins" - ], - "summary": "Get basin configuration.", - "operationId": "get_basin_config", - "parameters": [ - { - "name": "basin", - "in": "path", - "description": "Basin name.", - "required": true, - "schema": { - "$ref": "#/components/schemas/BasinNameStr" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BasinConfig" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - }, - "put": { - "tags": [ - "basins" - ], - "summary": "Create or reconfigure a basin.", - "operationId": "create_or_reconfigure_basin", - "parameters": [ - { - "name": "basin", - "in": "path", - "description": "Basin name.", - "required": true, - "schema": { - "$ref": "#/components/schemas/BasinNameStr" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/CreateOrReconfigureBasinRequest" - } - ] - } - } - } - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BasinInfo" - } - } - } - }, - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BasinInfo" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - }, - "delete": { - "tags": [ - "basins" - ], - "summary": "Delete a basin.", - "operationId": "delete_basin", - "parameters": [ - { - "name": "basin", - "in": "path", - "description": "Basin name.", - "required": true, - "schema": { - "$ref": "#/components/schemas/BasinNameStr" - } - } - ], - "responses": { - "202": { - "description": "" - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - }, - "patch": { - "tags": [ - "basins" - ], - "summary": "Reconfigure a basin.", - "operationId": "reconfigure_basin", - "parameters": [ - { - "name": "basin", - "in": "path", - "description": "Basin name.", - "required": true, - "schema": { - "$ref": "#/components/schemas/BasinNameStr" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BasinReconfiguration" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BasinConfig" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - } - }, - "/metrics": { - "get": { - "tags": [ - "metrics" - ], - "summary": "Account-level metrics.", - "operationId": "account_metrics", - "parameters": [ - { - "name": "set", - "in": "query", - "description": "Metric set to return.", - "required": true, - "schema": { - "$ref": "#/components/schemas/AccountMetricSet" - } - }, - { - "name": "start", - "in": "query", - "description": "Start timestamp as Unix epoch seconds, if applicable for the metric set.", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "end", - "in": "query", - "description": "End timestamp as Unix epoch seconds, if applicable for the metric set.", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "interval", - "in": "query", - "description": "Interval to aggregate over for timeseries metric sets.", - "required": false, - "schema": { - "$ref": "#/components/schemas/TimeseriesInterval" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MetricSetResponse" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - } - }, - "/metrics/{basin}": { - "get": { - "tags": [ - "metrics" - ], - "summary": "Basin-level metrics.", - "operationId": "basin_metrics", - "parameters": [ - { - "name": "set", - "in": "query", - "description": "Metric set to return.", - "required": true, - "schema": { - "$ref": "#/components/schemas/BasinMetricSet" - } - }, - { - "name": "start", - "in": "query", - "description": "Start timestamp as Unix epoch seconds, if applicable for the metric set.", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "end", - "in": "query", - "description": "End timestamp as Unix epoch seconds, if applicable for the metric set.", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "interval", - "in": "query", - "description": "Interval to aggregate over for timeseries metric sets.", - "required": false, - "schema": { - "$ref": "#/components/schemas/TimeseriesInterval" - } - }, - { - "name": "basin", - "in": "path", - "description": "Basin name.", - "required": true, - "schema": { - "$ref": "#/components/schemas/BasinNameStr" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MetricSetResponse" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - } - }, - "/metrics/{basin}/{stream}": { - "get": { - "tags": [ - "metrics" - ], - "summary": "Stream-level metrics.", - "operationId": "stream_metrics", - "parameters": [ - { - "name": "set", - "in": "query", - "description": "Metric set to return.", - "required": true, - "schema": { - "$ref": "#/components/schemas/StreamMetricSet" - } - }, - { - "name": "start", - "in": "query", - "description": "Start timestamp as Unix epoch seconds, if applicable for the metric set.", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "end", - "in": "query", - "description": "End timestamp as Unix epoch seconds, if applicable for metric set.", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "interval", - "in": "query", - "description": "Interval to aggregate over for timeseries metric sets.", - "required": false, - "schema": { - "$ref": "#/components/schemas/TimeseriesInterval" - } - }, - { - "name": "basin", - "in": "path", - "description": "Basin name.", - "required": true, - "schema": { - "$ref": "#/components/schemas/BasinNameStr" - } - }, - { - "name": "stream", - "in": "path", - "description": "Stream name.", - "required": true, - "schema": { - "$ref": "#/components/schemas/StreamNameStr" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MetricSetResponse" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - } - }, - "/streams": { - "servers": [ - { - "url": "https://{basin}.b.s2.dev/v1", - "description": "Endpoint for the basin", - "variables": { - "basin": { - "default": "", - "description": "Basin name" - } - } - } - ], - "get": { - "tags": [ - "streams" - ], - "summary": "List streams.", - "operationId": "list_streams", - "parameters": [ - { - "name": "prefix", - "in": "query", - "description": "Filter to streams whose names begin with this prefix.", - "required": false, - "schema": { - "type": "string", - "default": "" - } - }, - { - "name": "start_after", - "in": "query", - "description": "Filter to streams whose names lexicographically start after this string.\nIt must be greater than or equal to the `prefix` if specified.", - "required": false, - "schema": { - "type": "string", - "default": "" - } - }, - { - "name": "limit", - "in": "query", - "description": "Number of results, up to a maximum of 1000.", - "required": false, - "schema": { - "type": "integer", - "default": 1000, - "maximum": 1000, - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListStreamsResponse" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - }, - "post": { - "tags": [ - "streams" - ], - "summary": "Create a stream.", - "operationId": "create_stream", - "parameters": [ - { - "name": "s2-request-token", - "in": "header", - "description": "Client-specified request token for idempotent retries.", - "required": false, - "schema": { - "$ref": "#/components/schemas/RequestToken" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateStreamRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StreamInfo" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "409": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - } - }, - "/streams/{stream}": { - "servers": [ - { - "url": "https://{basin}.b.s2.dev/v1", - "description": "Endpoint for the basin", - "variables": { - "basin": { - "default": "", - "description": "Basin name" - } - } - } - ], - "get": { - "tags": [ - "streams" - ], - "summary": "Get stream configuration.", - "operationId": "get_stream_config", - "parameters": [ - { - "name": "stream", - "in": "path", - "description": "Stream name.", - "required": true, - "schema": { - "$ref": "#/components/schemas/StreamNameStr" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StreamConfig" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "409": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - }, - "put": { - "tags": [ - "streams" - ], - "summary": "Create or reconfigure a stream.", - "operationId": "create_or_reconfigure_stream", - "parameters": [ - { - "name": "stream", - "in": "path", - "description": "Stream name.", - "required": true, - "schema": { - "$ref": "#/components/schemas/StreamNameStr" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/StreamReconfiguration" - } - ] - } - } - } - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StreamInfo" - } - } - } - }, - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StreamInfo" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "409": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - }, - "delete": { - "tags": [ - "streams" - ], - "summary": "Delete a stream.", - "operationId": "delete_stream", - "parameters": [ - { - "name": "stream", - "in": "path", - "description": "Stream name.", - "required": true, - "schema": { - "$ref": "#/components/schemas/StreamNameStr" - } - } - ], - "responses": { - "202": { - "description": "" - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - }, - "patch": { - "tags": [ - "streams" - ], - "summary": "Reconfigure a stream.", - "operationId": "reconfigure_stream", - "parameters": [ - { - "name": "stream", - "in": "path", - "description": "Stream name.", - "required": true, - "schema": { - "$ref": "#/components/schemas/StreamNameStr" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StreamReconfiguration" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StreamConfig" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "409": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - } - }, - "/streams/{stream}/records": { - "servers": [ - { - "url": "https://{basin}.b.s2.dev/v1", - "description": "Endpoint for the basin", - "variables": { - "basin": { - "default": "", - "description": "Basin name" - } - } - } - ], - "get": { - "tags": [ - "records" - ], - "summary": "Read records.", - "operationId": "read", - "parameters": [ - { - "name": "stream", - "in": "path", - "description": "Stream name.", - "required": true, - "schema": { - "$ref": "#/components/schemas/StreamNameStr" - } - }, - { - "name": "s2-format", - "in": "header", - "description": "Defines the interpretation of record data (header name, header value, and body) with the JSON content type.\nUse `raw` (default) for efficient transmission and storage of Unicode data — storage will be in UTF-8.\nUse `base64` for safe transmission with efficient storage of binary data.", - "required": false, - "schema": { - "$ref": "#/components/schemas/Format" - } - }, - { - "name": "seq_num", - "in": "query", - "description": "Start from a sequence number.", - "required": false, - "schema": { - "$ref": "#/components/schemas/u64" - } - }, - { - "name": "timestamp", - "in": "query", - "description": "Start from a timestamp.", - "required": false, - "schema": { - "$ref": "#/components/schemas/u64" - } - }, - { - "name": "tail_offset", - "in": "query", - "description": "Start from number of records before the next sequence number.", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "clamp", - "in": "query", - "description": "Start reading from the tail if the requested position is beyond it.\nOtherwise, a `416 Range Not Satisfiable` response is returned.", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "count", - "in": "query", - "description": "Record count limit.\nNon-streaming reads are capped by the default limit of 1000 records.", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "bytes", - "in": "query", - "description": "Metered bytes limit.\nNon-streaming reads are capped by the default limit of 1 MiB.", - "required": false, - "schema": { - "type": "integer", - "minimum": 0 - } - }, - { - "name": "until", - "in": "query", - "description": "Exclusive timestamp to read until.", - "required": false, - "schema": { - "$ref": "#/components/schemas/u64" - } - }, - { - "name": "wait", - "in": "query", - "description": "Duration in seconds to wait for new records.\nThe default duration is 0 if there is a bound on `count`, `bytes`, or `until`, and otherwise infinite.\nNon-streaming reads are always bounded on `count` and `bytes`, so you can achieve long poll semantics by specifying a non-zero duration up to 60 seconds.\nIn the context of an SSE or S2S streaming read, the duration will bound how much time can elapse between records throughout the lifetime of the session.", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ReadBatch" - } - }, - "text/event-stream": { - "schema": { - "$ref": "#/components/schemas/ReadEvent" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "409": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "416": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TailResponse" - } - } - } - } - } - }, - "post": { - "tags": [ - "records" - ], - "summary": "Append records.", - "operationId": "append", - "parameters": [ - { - "name": "stream", - "in": "path", - "description": "Stream name.", - "required": true, - "schema": { - "$ref": "#/components/schemas/StreamNameStr" - } - }, - { - "name": "s2-format", - "in": "header", - "description": "Defines the interpretation of record data (header name, header value, and body) with the JSON content type.\nUse `raw` (default) for efficient transmission and storage of Unicode data — storage will be in UTF-8.\nUse `base64` for safe transmission with efficient storage of binary data.", - "required": false, - "schema": { - "$ref": "#/components/schemas/Format" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AppendInput" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AppendAck" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "409": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "412": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AppendConditionFailed" - } - } - } - } - } - } - }, - "/streams/{stream}/records/tail": { - "servers": [ - { - "url": "https://{basin}.b.s2.dev/v1", - "description": "Endpoint for the basin", - "variables": { - "basin": { - "default": "", - "description": "Basin name" - } - } - } - ], - "get": { - "tags": [ - "records" - ], - "summary": "Check the tail.", - "operationId": "check_tail", - "parameters": [ - { - "name": "stream", - "in": "path", - "description": "Stream name.", - "required": true, - "schema": { - "$ref": "#/components/schemas/StreamNameStr" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TailResponse" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "408": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - }, - "409": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorInfo" - } - } - } - } - } - } - } - }, - "components": { - "schemas": { - "AccessTokenIdStr": { - "type": "string", - "maxLength": 96, - "minLength": 1 - }, - "AccessTokenInfo": { - "type": "object", - "required": [ - "id", - "scope" - ], - "properties": { - "auto_prefix_streams": { - "type": "boolean", - "description": "Namespace streams based on the configured stream-level scope, which must be a prefix.\nStream name arguments will be automatically prefixed, and the prefix will be stripped when listing streams.", - "default": false - }, - "expires_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Expiration time in RFC 3339 format.\nIf not set, the expiration will be set to that of the requestor's token." - }, - "id": { - "$ref": "#/components/schemas/AccessTokenIdStr", - "description": "Access token ID.\nIt must be unique to the account and between 1 and 96 bytes in length." - }, - "scope": { - "$ref": "#/components/schemas/AccessTokenScope", - "description": "Access token scope." - } - } - }, - "AccessTokenScope": { - "type": "object", - "properties": { - "access_tokens": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ResourceSet", - "description": "Token IDs allowed." - } - ] - }, - "basins": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ResourceSet", - "description": "Basin names allowed." - } - ] - }, - "op_groups": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/PermittedOperationGroups", - "description": "Access permissions at operation group level." - } - ] - }, - "ops": { - "type": [ - "array", - "null" - ], - "items": { - "$ref": "#/components/schemas/Operation" - }, - "description": "Operations allowed for the token.\nA union of allowed operations and groups is used as an effective set of allowed operations." - }, - "streams": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ResourceSet", - "description": "Stream names allowed." - } - ] - } - } - }, - "AccountMetricSet": { - "type": "string", - "enum": [ - "active-basins", - "account-ops" - ] - }, - "AccumulationMetric": { - "type": "object", - "required": [ - "name", - "unit", - "interval", - "values" - ], - "properties": { - "interval": { - "$ref": "#/components/schemas/TimeseriesInterval", - "description": "The interval at which data points are accumulated." - }, - "name": { - "type": "string", - "description": "Timeseries name." - }, - "unit": { - "$ref": "#/components/schemas/MetricUnit", - "description": "Unit of the metric." - }, - "values": { - "type": "array", - "items": { - "type": "array", - "items": false, - "prefixItems": [ - { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - { - "type": "number", - "format": "double" - } - ] - }, - "description": "Timeseries values.\nEach element is a tuple of a timestamp in Unix epoch seconds and a data point.\nThe data point represents the accumulated value for the time period starting at the timestamp, spanning one `interval`." - } - } - }, - "AppendAck": { - "type": "object", - "description": "Success response to an `append` request.", - "required": [ - "start", - "end", - "tail" - ], - "properties": { - "end": { - "$ref": "#/components/schemas/StreamPosition", - "description": "Sequence number of the last record that was appended `+ 1`, and timestamp of the last record that was appended.\nThe difference between `end.seq_num` and `start.seq_num` will be the number of records appended." - }, - "start": { - "$ref": "#/components/schemas/StreamPosition", - "description": "Sequence number and timestamp of the first record that was appended." - }, - "tail": { - "$ref": "#/components/schemas/StreamPosition", - "description": "Sequence number that will be assigned to the next record on the stream, and timestamp of the last record on the stream.\nThis can be greater than the `end` position in case of concurrent appends." - } - } - }, - "AppendConditionFailed": { - "oneOf": [ - { - "type": "object", - "title": "fencing token", - "description": "Fencing token did not match.\nThe expected fencing token is returned.", - "required": [ - "fencing_token_mismatch" - ], - "properties": { - "fencing_token_mismatch": { - "$ref": "#/components/schemas/FencingToken", - "description": "Fencing token did not match.\nThe expected fencing token is returned." - } - } - }, - { - "type": "object", - "title": "seq num", - "description": "Sequence number did not match the tail of the stream.\nThe expected next sequence number is returned.", - "required": [ - "seq_num_mismatch" - ], - "properties": { - "seq_num_mismatch": { - "$ref": "#/components/schemas/u64", - "description": "Sequence number did not match the tail of the stream.\nThe expected next sequence number is returned." - } - } - } - ], - "description": "Aborted due to a failed condition." - }, - "AppendInput": { - "type": "object", - "description": "Payload of an `append` request.", - "required": [ - "records" - ], - "properties": { - "fencing_token": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/FencingToken", - "description": "Enforce a fencing token, which starts out as an empty string that can be overridden by a `fence` command record." - } - ] - }, - "match_seq_num": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/u64", - "description": "Enforce that the sequence number assigned to the first record matches." - } - ] - }, - "records": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AppendRecord" - }, - "description": "Batch of records to append atomically, which must contain at least one record, and no more than 1000.\nThe total size of a batch of records may not exceed 1 MiB of metered bytes." - } - } - }, - "AppendRecord": { - "type": "object", - "description": "Record to be appended to a stream.", - "properties": { - "body": { - "type": "string", - "description": "Body of the record." - }, - "headers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Header" - }, - "description": "Series of name-value pairs for this record." - }, - "timestamp": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/u64", - "description": "Timestamp for this record.\nThe service will always ensure monotonicity by adjusting it up if necessary to the maximum observed timestamp.\nRefer to stream timestamping configuration for the finer semantics around whether a client-specified timestamp is required, and whether it will be capped at the arrival time." - } - ] - } - } - }, - "BasinConfig": { - "type": "object", - "properties": { - "create_stream_on_append": { - "type": "boolean", - "description": "Create stream on append if it doesn't exist, using the default stream configuration.", - "default": false - }, - "create_stream_on_read": { - "type": "boolean", - "description": "Create stream on read if it doesn't exist, using the default stream configuration.", - "default": false - }, - "default_stream_config": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/StreamConfig", - "description": "Default stream configuration." - } - ] - } - } - }, - "BasinInfo": { - "type": "object", - "required": [ - "name", - "created_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time", - "description": "Creation time in RFC 3339 format." - }, - "deleted_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Deletion time in RFC 3339 format, if the basin is being deleted." - }, - "name": { - "$ref": "#/components/schemas/BasinNameStr", - "description": "Basin name." - }, - "scope": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/BasinScope", - "description": "Basin scope." - } - ] - } - } - }, - "BasinMetricSet": { - "type": "string", - "enum": [ - "storage", - "append-ops", - "read-ops", - "read-throughput", - "append-throughput", - "basin-ops" - ] - }, - "BasinNameStr": { - "type": "string", - "maxLength": 48, - "minLength": 8 - }, - "BasinReconfiguration": { - "type": "object", - "properties": { - "create_stream_on_append": { - "type": [ - "boolean", - "null" - ], - "description": "Create a stream on append." - }, - "create_stream_on_read": { - "type": [ - "boolean", - "null" - ], - "description": "Create a stream on read." - }, - "default_stream_config": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/StreamReconfiguration", - "description": "Basin configuration." - } - ] - } - } - }, - "BasinScope": { - "type": "string", - "enum": [ - "aws:us-east-1" - ] - }, - "BasinState": { - "type": "string", - "enum": [ - "active", - "deleting" - ] - }, - "CreateBasinRequest": { - "type": "object", - "required": [ - "basin" - ], - "properties": { - "basin": { - "$ref": "#/components/schemas/BasinNameStr", - "description": "Basin name which must be globally unique.\nIt can be between 8 and 48 bytes in length, and comprise lowercase letters, numbers and hyphens.\nIt cannot begin or end with a hyphen." - }, - "config": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/BasinConfig", - "description": "Basin configuration." - } - ] - }, - "scope": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/BasinScope", - "description": "Basin scope." - } - ] - } - } - }, - "CreateOrReconfigureBasinRequest": { - "type": "object", - "properties": { - "config": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/BasinReconfiguration", - "description": "Basin reconfiguration." - } - ] - }, - "scope": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/BasinScope", - "description": "Basin scope.\nThis cannot be reconfigured." - } - ] - } - } - }, - "CreateStreamRequest": { - "type": "object", - "required": [ - "stream" - ], - "properties": { - "config": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/StreamConfig", - "description": "Stream configuration." - } - ] - }, - "stream": { - "$ref": "#/components/schemas/StreamNameStr", - "description": "Stream name that is unique to the basin.\nIt can be between 1 and 512 bytes in length." - } - } - }, - "DeleteOnEmptyConfig": { - "type": "object", - "properties": { - "min_age_secs": { - "type": "integer", - "format": "int64", - "description": "Minimum age in seconds before an empty stream can be deleted.\nSet to 0 (default) to disable delete-on-empty (don't delete automatically).", - "minimum": 0 - } - } - }, - "DeleteOnEmptyReconfiguration": { - "type": "object", - "properties": { - "min_age_secs": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Minimum age in seconds before an empty stream can be deleted.\nSet to 0 to disable delete-on-empty (don't delete automatically).", - "minimum": 0 - } - } - }, - "ErrorInfo": { - "type": "object", - "required": [ - "code", - "message" - ], - "properties": { - "code": { - "type": "string" - }, - "message": { - "type": "string" - } - } - }, - "FencingToken": { - "type": "string", - "maxLength": 36 - }, - "Format": { - "type": "string", - "enum": [ - "raw", - "base64" - ] - }, - "GaugeMetric": { - "type": "object", - "required": [ - "name", - "unit", - "values" - ], - "properties": { - "name": { - "type": "string", - "description": "Timeseries name." - }, - "unit": { - "$ref": "#/components/schemas/MetricUnit", - "description": "Unit of the metric." - }, - "values": { - "type": "array", - "items": { - "type": "array", - "items": false, - "prefixItems": [ - { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - { - "type": "number", - "format": "double" - } - ] - }, - "description": "Timeseries values.\nEach element is a tuple of a timestamp in Unix epoch seconds and a data point.\nThe data point represents the value at the instant of the timestamp." - } - } - }, - "Header": { - "type": "array", - "items": { - "type": "string" - }, - "maxItems": 2, - "minItems": 2 - }, - "InfiniteRetention": { - "type": "object" - }, - "IssueAccessTokenResponse": { - "type": "object", - "required": [ - "access_token" - ], - "properties": { - "access_token": { - "type": "string", - "description": "Created access token." - } - } - }, - "LabelMetric": { - "type": "object", - "required": [ - "name", - "values" - ], - "properties": { - "name": { - "type": "string", - "description": "Label name." - }, - "values": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Label values." - } - } - }, - "ListAccessTokensResponse": { - "type": "object", - "required": [ - "access_tokens", - "has_more" - ], - "properties": { - "access_tokens": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AccessTokenInfo" - }, - "description": "Matching access tokens.", - "maxItems": 1000 - }, - "has_more": { - "type": "boolean", - "description": "Indicates that there are more access tokens that match the criteria." - } - } - }, - "ListBasinsResponse": { - "type": "object", - "required": [ - "basins", - "has_more" - ], - "properties": { - "basins": { - "type": "array", - "items": { - "$ref": "#/components/schemas/BasinInfo" - }, - "description": "Matching basins.", - "maxItems": 1000 - }, - "has_more": { - "type": "boolean", - "description": "Indicates that there are more basins that match the criteria." - } - } - }, - "ListStreamsResponse": { - "type": "object", - "required": [ - "streams", - "has_more" - ], - "properties": { - "has_more": { - "type": "boolean", - "description": "Indicates that there are more results that match the criteria." - }, - "streams": { - "type": "array", - "items": { - "$ref": "#/components/schemas/StreamInfo" - }, - "description": "Matching streams.", - "maxItems": 1000 - } - } - }, - "Metric": { - "oneOf": [ - { - "type": "object", - "description": "Single named value.", - "required": [ - "scalar" - ], - "properties": { - "scalar": { - "$ref": "#/components/schemas/ScalarMetric", - "description": "Single named value." - } - } - }, - { - "type": "object", - "description": "Named series of `(timestamp, value)` points representing an accumulation over a specified interval.", - "required": [ - "accumulation" - ], - "properties": { - "accumulation": { - "$ref": "#/components/schemas/AccumulationMetric", - "description": "Named series of `(timestamp, value)` points representing an accumulation over a specified interval." - } - } - }, - { - "type": "object", - "description": "Named series of `(timestamp, value)` points each representing an instantaneous value.", - "required": [ - "gauge" - ], - "properties": { - "gauge": { - "$ref": "#/components/schemas/GaugeMetric", - "description": "Named series of `(timestamp, value)` points each representing an instantaneous value." - } - } - }, - { - "type": "object", - "description": "Set of string labels.", - "required": [ - "label" - ], - "properties": { - "label": { - "$ref": "#/components/schemas/LabelMetric", - "description": "Set of string labels." - } - } - } - ] - }, - "MetricSetResponse": { - "type": "object", - "required": [ - "values" - ], - "properties": { - "values": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Metric" - }, - "description": "Metrics comprising the set." - } - } - }, - "MetricUnit": { - "type": "string", - "enum": [ - "bytes", - "operations" - ] - }, - "Operation": { - "type": "string", - "enum": [ - "list-basins", - "create-basin", - "delete-basin", - "reconfigure-basin", - "get-basin-config", - "issue-access-token", - "revoke-access-token", - "list-access-tokens", - "list-streams", - "create-stream", - "delete-stream", - "get-stream-config", - "reconfigure-stream", - "check-tail", - "append", - "read", - "trim", - "fence", - "account-metrics", - "basin-metrics", - "stream-metrics" - ] - }, - "PermittedOperationGroups": { - "type": "object", - "properties": { - "account": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ReadWritePermissions", - "description": "Account-level access permissions." - } - ] - }, - "basin": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ReadWritePermissions", - "description": "Basin-level access permissions." - } - ] - }, - "stream": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ReadWritePermissions", - "description": "Stream-level access permissions." - } - ] - } - } - }, - "PingEventData": { - "type": "object", - "required": [ - "timestamp" - ], - "properties": { - "timestamp": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "ReadBatch": { - "type": "object", - "required": [ - "records" - ], - "properties": { - "records": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SequencedRecord" - }, - "description": "Records that are durably sequenced on the stream, retrieved based on the requested criteria.\nThis can only be empty in response to a unary read (i.e. not SSE), if the request cannot be satisfied without violating an explicit bound (`count`, `bytes`, or `until`)." - }, - "tail": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/StreamPosition", - "description": "Sequence number that will be assigned to the next record on the stream, and timestamp of the last record.\nThis will only be present when reading recent records." - } - ] - } - } - }, - "ReadEvent": { - "oneOf": [ - { - "type": "object", - "title": "batch", - "required": [ - "event", - "data", - "id" - ], - "properties": { - "data": { - "$ref": "#/components/schemas/ReadBatch" - }, - "event": { - "type": "string", - "enum": [ - "batch" - ] - }, - "id": { - "type": "string", - "pattern": "^[0-9]+,[0-9]+,[0-9]+$" - } - } - }, - { - "type": "object", - "title": "error", - "required": [ - "event", - "data" - ], - "properties": { - "data": { - "type": "string" - }, - "event": { - "type": "string", - "enum": [ - "error" - ] - } - } - }, - { - "type": "object", - "title": "ping", - "required": [ - "event", - "data" - ], - "properties": { - "data": { - "$ref": "#/components/schemas/PingEventData" - }, - "event": { - "type": "string", - "enum": [ - "ping" - ] - } - } - } - ] - }, - "ReadWritePermissions": { - "type": "object", - "properties": { - "read": { - "type": "boolean", - "description": "Read permission.", - "default": false - }, - "write": { - "type": "boolean", - "description": "Write permission.", - "default": false - } - } - }, - "RequestToken": { - "type": "string", - "maxLength": 36 - }, - "ResourceSet": { - "oneOf": [ - { - "type": "object", - "title": "exact", - "description": "Match only the resource with this exact name.\nUse an empty string to match no resources.", - "required": [ - "exact" - ], - "properties": { - "exact": { - "type": "string", - "description": "Match only the resource with this exact name.\nUse an empty string to match no resources." - } - } - }, - { - "type": "object", - "title": "prefix", - "description": "Match all resources that start with this prefix.\nUse an empty string to match all resource.", - "required": [ - "prefix" - ], - "properties": { - "prefix": { - "type": "string", - "description": "Match all resources that start with this prefix.\nUse an empty string to match all resource." - } - } - } - ] - }, - "RetentionPolicy": { - "oneOf": [ - { - "type": "object", - "description": "Age in seconds for automatic trimming of records older than this threshold.\nThis must be set to a value greater than 0 seconds.", - "required": [ - "age" - ], - "properties": { - "age": { - "type": "integer", - "format": "int64", - "description": "Age in seconds for automatic trimming of records older than this threshold.\nThis must be set to a value greater than 0 seconds.", - "minimum": 0 - } - } - }, - { - "type": "object", - "description": "Retain records unless explicitly trimmed.", - "required": [ - "infinite" - ], - "properties": { - "infinite": { - "$ref": "#/components/schemas/InfiniteRetention", - "description": "Retain records unless explicitly trimmed." - } - } - } - ] - }, - "ScalarMetric": { - "type": "object", - "required": [ - "name", - "unit", - "value" - ], - "properties": { - "name": { - "type": "string", - "description": "Metric name." - }, - "unit": { - "$ref": "#/components/schemas/MetricUnit", - "description": "Unit of the metric." - }, - "value": { - "type": "number", - "format": "double", - "description": "Metric value." - } - } - }, - "SequencedRecord": { - "type": "object", - "description": "Record that is durably sequenced on a stream.", - "required": [ - "seq_num", - "timestamp" - ], - "properties": { - "body": { - "type": "string", - "description": "Body of the record." - }, - "headers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Header" - }, - "description": "Series of name-value pairs for this record." - }, - "seq_num": { - "$ref": "#/components/schemas/u64", - "description": "Sequence number assigned by the service." - }, - "timestamp": { - "$ref": "#/components/schemas/u64", - "description": "Timestamp for this record." - } - } - }, - "StorageClass": { - "type": "string", - "enum": [ - "standard", - "express" - ] - }, - "StreamConfig": { - "type": "object", - "properties": { - "delete_on_empty": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/DeleteOnEmptyConfig", - "description": "Delete-on-empty configuration." - } - ] - }, - "retention_policy": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/RetentionPolicy", - "description": "Retention policy for the stream.\nIf unspecified, the default is to retain records for 7 days." - } - ] - }, - "storage_class": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/StorageClass", - "description": "Storage class for recent writes." - } - ] - }, - "timestamping": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/TimestampingConfig", - "description": "Timestamping behavior." - } - ] - } - } - }, - "StreamInfo": { - "type": "object", - "required": [ - "name", - "created_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time", - "description": "Creation time in RFC 3339 format." - }, - "deleted_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Deletion time in RFC 3339 format, if the stream is being deleted." - }, - "name": { - "$ref": "#/components/schemas/StreamNameStr", - "description": "Stream name." - } - } - }, - "StreamMetricSet": { - "type": "string", - "enum": [ - "storage" - ] - }, - "StreamNameStr": { - "type": "string", - "maxLength": 512, - "minLength": 1 - }, - "StreamPosition": { - "type": "object", - "description": "Position of a record in a stream.", - "required": [ - "seq_num", - "timestamp" - ], - "properties": { - "seq_num": { - "$ref": "#/components/schemas/u64", - "description": "Sequence number assigned by the service." - }, - "timestamp": { - "$ref": "#/components/schemas/u64", - "description": "Timestamp, which may be client-specified or assigned by the service.\nIf it is assigned by the service, it will represent milliseconds since Unix epoch." - } - } - }, - "StreamReconfiguration": { - "type": "object", - "properties": { - "delete_on_empty": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/DeleteOnEmptyReconfiguration", - "description": "Delete-on-empty configuration." - } - ] - }, - "retention_policy": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/RetentionPolicy", - "description": "Retention policy for the stream.\nIf unspecified, the default is to retain records for 7 days." - } - ] - }, - "storage_class": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/StorageClass", - "description": "Storage class for recent writes." - } - ] - }, - "timestamping": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/TimestampingReconfiguration", - "description": "Timestamping behavior." - } - ] - } - } - }, - "TailResponse": { - "type": "object", - "required": [ - "tail" - ], - "properties": { - "tail": { - "$ref": "#/components/schemas/StreamPosition", - "description": "Sequence number that will be assigned to the next record on the stream, and timestamp of the last record." - } - } - }, - "TimeseriesInterval": { - "type": "string", - "enum": [ - "minute", - "hour", - "day" - ] - }, - "TimestampingConfig": { - "type": "object", - "properties": { - "mode": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/TimestampingMode", - "description": "Timestamping mode for appends that influences how timestamps are handled." - } - ] - }, - "uncapped": { - "type": [ - "boolean", - "null" - ], - "description": "Allow client-specified timestamps to exceed the arrival time.\nIf this is `false` or not set, client timestamps will be capped at the arrival time." - } - } - }, - "TimestampingMode": { - "type": "string", - "enum": [ - "client-prefer", - "client-require", - "arrival" - ] - }, - "TimestampingReconfiguration": { - "type": "object", - "properties": { - "mode": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/TimestampingMode", - "description": "Timestamping mode for appends that influences how timestamps are handled." - } - ] - }, - "uncapped": { - "type": [ - "boolean", - "null" - ], - "description": "Allow client-specified timestamps to exceed the arrival time." - } - } - }, - "u64": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - "securitySchemes": { - "access_token": { - "type": "http", - "scheme": "bearer", - "description": "Bearer authentication header of the form `Bearer `, where `` is your access token." - } - } - }, - "security": [ - { - "access_token": [] - } - ], - "tags": [ - { - "name": "metrics", - "description": "Usage metrics and data." - }, - { - "name": "basins", - "description": "Manage basins" - }, - { - "name": "access-tokens", - "description": "Manage access tokens" - }, - { - "name": "streams", - "description": "Manage streams" - }, - { - "name": "records", - "description": "Manage records" - } - ] -} diff --git a/s2-specs/s2/v1/s2.proto b/s2-specs/s2/v1/s2.proto deleted file mode 100644 index 91a289f..0000000 --- a/s2-specs/s2/v1/s2.proto +++ /dev/null @@ -1,81 +0,0 @@ -syntax = "proto3"; - -package s2.v1; - -option java_multiple_files = true; -option java_package = "s2.v1"; - -// Position of a record in a stream. -message StreamPosition { - // Sequence number assigned by the service. - uint64 seq_num = 1; - // Timestamp, which may be user-specified or assigned by the service. - // If it is assigned by the service, it will represent milliseconds since Unix epoch. - uint64 timestamp = 2; -} - -// Headers add structured information to a record as name-value pairs. -message Header { - // Header name blob. - // The name cannot be empty, with the exception of an S2 command record. - bytes name = 1; - // Header value blob. - bytes value = 2; -} - -// Record to be appended to a stream. -message AppendRecord { - // Timestamp for this record. - // Precise semantics depend on the stream's `timestamping` config. - optional uint64 timestamp = 1; - // Series of name-value pairs for this record. - repeated Header headers = 2; - // Body of this record. - bytes body = 3; -} - -// Payload of an Append request message. -message AppendInput { - // Batch of records to append atomically, which must contain at least one record, and no more than 1000. - // The total size of a batch of records may not exceed 1MiB of metered bytes. - repeated AppendRecord records = 1; - // Enforce that the sequence number issued to the first record matches. - optional uint64 match_seq_num = 2; - // Enforce a fencing token which must have been previously set by a `fence` command record. - optional string fencing_token = 3; -} - -// Success response message to an Append request. -message AppendAck { - // Sequence number and timestamp of the first record that was appended. - StreamPosition start = 1; - // Sequence number of the last record that was appended + 1, and timestamp of the last record that was appended. - // The difference between `end.seq_num` and `start.seq_num` will be the number of records appended. - StreamPosition end = 2; - // Sequence number that will be assigned to the next record on the stream, and timestamp of the last record on the stream. - // This can be greater than the `end` position in case of concurrent appends. - StreamPosition tail = 3; -} - -// Record that is durably sequenced on a stream. -message SequencedRecord { - // Sequence number assigned to this record. - uint64 seq_num = 1; - // Timestamp for this record. - uint64 timestamp = 2; - // Series of name-value pairs for this record. - repeated Header headers = 3; - // Body of this record. - bytes body = 4; -} - -// Success response message to a Read request. -message ReadBatch { - // Records that are durably sequenced on the stream, retrieved based on the requested criteria. - // This can only be empty in response to a unary read if the request cannot be satisfied without violating an explicit bound (`count`, `bytes`, or `until`). - // In the context of a session, it can be empty as a heartbeat message. A heartbeat will be sent whenever a switch to following in real-time happens, and then at a randomized gap between 5 and 15 seconds if no records have become available. - repeated SequencedRecord records = 1; - // Sequence number that will be assigned to the next record on the stream, and timestamp of the last record. - // It will only be present when reading recent records. - optional StreamPosition tail = 2; -} diff --git a/s2-specs/s2/v1/s2s.md b/s2-specs/s2/v1/s2s.md deleted file mode 100644 index 13aa4fc..0000000 --- a/s2-specs/s2/v1/s2s.md +++ /dev/null @@ -1,26 +0,0 @@ -#### Setup - -* `Content-Type: s2s/proto` signals that a session is being requested. -* `Accept-Encoding` signals which compression algorithms are supported (service supports `zstd` and `gzip`). `Content-Encoding` is not sent as message-level compression is used. -* `200 OK` response establishes a session. - -#### Message framing - -_All integers use big-endian byte order. Messages smaller than 1KiB should not be compressed._ - -**Length prefix** (3 bytes): Total message length (flag + body) - -**Flag byte** (1 byte): `[T][CC][RRRRR]` -- `T` (bit 7): Terminal flag (`1` = stream ends after this message) -- `CC` (bits 6-5): Compression (`00`=`none`, `01`=`zstd`, `10`=`gzip`) -- `RRRRR` (bits 4-0): Reserved - -**Body** (variable): -- Regular message is a Protobuf -- Terminal message contains a 2-byte status code, followed by JSON error information (corresponding to unary response behavior) - -#### Data flow - -**Append** sessions are a bi-directional stream of [`AppendInput`](https://buf.build/streamstore/s2/docs/main:s2.v1#s2.v1.AppendInput) messages from *Client → Server*, and [`AppendAck`](https://buf.build/streamstore/s2/docs/main:s2.v1#s2.v1.AppendAck) messages from *Server → Client*. - -**Read** sessions are a uni-directional stream of [`ReadBatch`](https://buf.build/streamstore/s2/docs/main:s2.v1#s2.v1.ReadBatch) messages from *Server → Client*. When waiting for new records, an empty batch is sent as a heartbeat at least every 15 seconds. diff --git a/s2-specs/s2/v1alpha/s2.proto b/s2-specs/s2/v1alpha/s2.proto deleted file mode 100644 index 27f38aa..0000000 --- a/s2-specs/s2/v1alpha/s2.proto +++ /dev/null @@ -1,734 +0,0 @@ -syntax = "proto3"; - -package s2.v1alpha; - -import "google/protobuf/field_mask.proto"; - -option java_multiple_files = true; -option java_package = "s2.v1alpha"; - -// Operate on an S2 account. -service AccountService { - // List basins. - rpc ListBasins(ListBasinsRequest) returns (ListBasinsResponse) { - option idempotency_level = NO_SIDE_EFFECTS; - } - - // Create a new basin. - // Provide a client request token with the `S2-Request-Token` header for idempotent retry behaviour. - rpc CreateBasin(CreateBasinRequest) returns (CreateBasinResponse) { - option idempotency_level = IDEMPOTENT; - } - - // Delete a basin. - // Basin deletion is asynchronous, and may take a few minutes to complete. - rpc DeleteBasin(DeleteBasinRequest) returns (DeleteBasinResponse) { - option idempotency_level = IDEMPOTENT; - } - - // Update basin configuration. - rpc ReconfigureBasin(ReconfigureBasinRequest) returns (ReconfigureBasinResponse) { - option idempotency_level = IDEMPOTENT; - } - - // Get basin configuration. - rpc GetBasinConfig(GetBasinConfigRequest) returns (GetBasinConfigResponse) { - option idempotency_level = NO_SIDE_EFFECTS; - } - - // Issue a new access token. - rpc IssueAccessToken(IssueAccessTokenRequest) returns (IssueAccessTokenResponse); - - // Revoke an access token. - rpc RevokeAccessToken(RevokeAccessTokenRequest) returns (RevokeAccessTokenResponse) { - option idempotency_level = IDEMPOTENT; - } - - // List access tokens. - rpc ListAccessTokens(ListAccessTokensRequest) returns (ListAccessTokensResponse) { - option idempotency_level = NO_SIDE_EFFECTS; - } -} - -// Operate on an S2 basin. -service BasinService { - // List streams. - rpc ListStreams(ListStreamsRequest) returns (ListStreamsResponse) { - option idempotency_level = NO_SIDE_EFFECTS; - } - - // Create a stream. - // Provide a client request token with the `S2-Request-Token` header for idempotent retry behaviour. - rpc CreateStream(CreateStreamRequest) returns (CreateStreamResponse) { - option idempotency_level = IDEMPOTENT; - } - - // Delete a stream. - // Stream deletion is asynchronous, and may take a few minutes to complete. - rpc DeleteStream(DeleteStreamRequest) returns (DeleteStreamResponse) { - option idempotency_level = IDEMPOTENT; - } - - // Get stream configuration. - rpc GetStreamConfig(GetStreamConfigRequest) returns (GetStreamConfigResponse) { - option idempotency_level = NO_SIDE_EFFECTS; - } - - // Update stream configuration. - rpc ReconfigureStream(ReconfigureStreamRequest) returns (ReconfigureStreamResponse) { - option idempotency_level = IDEMPOTENT; - } -} - -// Operate on an S2 stream. -service StreamService { - // Check the tail of the stream. - rpc CheckTail(CheckTailRequest) returns (CheckTailResponse) { - option idempotency_level = NO_SIDE_EFFECTS; - } - - // Append a batch of records to a stream. - rpc Append(AppendRequest) returns (AppendResponse); - - // Append batches of records to a stream continuously, while guaranteeing pipelined requests are processed in order. - // If any request fails, the session is terminated. - rpc AppendSession(stream AppendSessionRequest) returns (stream AppendSessionResponse); - - // Retrieve a batch of records from a stream. - rpc Read(ReadRequest) returns (ReadResponse) { - option idempotency_level = NO_SIDE_EFFECTS; - } - - // Retrieve batches of records from a stream continuously. - rpc ReadSession(ReadSessionRequest) returns (stream ReadSessionResponse) { - option idempotency_level = NO_SIDE_EFFECTS; - } -} - -/// AccountService /// - -// List basins request. -message ListBasinsRequest { - // List basin names that begin with this prefix. - string prefix = 1; - // Only return basins names that lexicographically start after this name. - // This can be the last basin name seen in a previous listing, to continue from there. - // It must be greater than or equal to the prefix if specified. - string start_after = 2; - // Number of results, up to a maximum of 1000. - optional uint64 limit = 3; -} - -// List basins response. -message ListBasinsResponse { - // Matching basins. - repeated BasinInfo basins = 1; - // If set, indicates there are more results that can be listed with `start_after`. - bool has_more = 2; -} - -// Create basin request. -message CreateBasinRequest { - // Basin name, which must be globally unique. - // The name must be between 8 and 48 characters, comprising lowercase letters, numbers and hyphens. - // It cannot begin or end with a hyphen. - string basin = 1; - // Basin configuration. - BasinConfig config = 2; - // Basin scope. - BasinScope scope = 3; -} - -// Basin scope. -enum BasinScope { - // Unspecified basin scope. - BASIN_SCOPE_UNSPECIFIED = 0; - // aws us-east-1 region. - BASIN_SCOPE_AWS_US_EAST_1 = 1; -} - -// Create basin response. -message CreateBasinResponse { - // Information about the newly created basin. - BasinInfo info = 1; -} - -// Delete basin request. -message DeleteBasinRequest { - // Name of the basin to delete. - string basin = 1; -} - -// Delete basin response. -message DeleteBasinResponse {} - -// Get basin configuration request. -message GetBasinConfigRequest { - // Basin name. - string basin = 1; -} - -// Get basin configuration response. -message GetBasinConfigResponse { - // Basin configuration. - BasinConfig config = 1; -} - -// Reconfigure basin request. -message ReconfigureBasinRequest { - // Basin name. - string basin = 1; - // Basin configuration. - BasinConfig config = 2; - // Specifies the pieces of configuration being updated. - // See https://protobuf.dev/reference/protobuf/google.protobuf/#field-mask - google.protobuf.FieldMask mask = 3; -} - -// Reconfigure basin response. -message ReconfigureBasinResponse { - // Basin configuration. - BasinConfig config = 1; -} - -// Issue access token request. -message IssueAccessTokenRequest { - // Access token information. - AccessTokenInfo info = 1; -} - -// API operations. -enum Operation { - // Unspecified operation. - OPERATION_UNSPECIFIED = 0; - // List basins. - OPERATION_LIST_BASINS = 1; - // Create a basin. - OPERATION_CREATE_BASIN = 2; - // Delete a basin. - OPERATION_DELETE_BASIN = 3; - // Update basin configuration. - OPERATION_RECONFIGURE_BASIN = 4; - // Get basin configuration. - OPERATION_GET_BASIN_CONFIG = 5; - // Issue an access token. - OPERATION_ISSUE_ACCESS_TOKEN = 6; - // Revoke an access token. - OPERATION_REVOKE_ACCESS_TOKEN = 7; - // List access tokens. - OPERATION_LIST_ACCESS_TOKENS = 8; - // List streams. - OPERATION_LIST_STREAMS = 9; - // Create a stream. - OPERATION_CREATE_STREAM = 10; - // Delete a stream. - OPERATION_DELETE_STREAM = 11; - // Get stream configuration. - OPERATION_GET_STREAM_CONFIG = 12; - // Update stream configuration. - OPERATION_RECONFIGURE_STREAM = 13; - // Check tail of a stream. - OPERATION_CHECK_TAIL = 14; - // Append records to a stream. - OPERATION_APPEND = 15; - // Read records from a stream. - OPERATION_READ = 16; - // Trim records up to a sequence number. - OPERATION_TRIM = 17; - // Set a fencing token for a stream. - OPERATION_FENCE = 18; - // Retrieve account-level metrics. - OPERATION_ACCOUNT_METRICS = 19; - // Retrieve basin-level metrics. - OPERATION_BASIN_METRICS = 20; - // Retrieve stream-level metrics. - OPERATION_STREAM_METRICS = 21; -} - -// Read/Write permissions. -message ReadWritePermissions { - // Read permission. - bool read = 1; - // Write permission. - bool write = 2; -} - -// Access permissions for a group. -message PermittedOperationGroups { - // Access permissions at account level. - ReadWritePermissions account = 1; - // Access permissions at basin level. - ReadWritePermissions basin = 2; - // Access permissions at stream level. - ReadWritePermissions stream = 3; -} - -// Revoke access token request. -message RevokeAccessTokenRequest { - // Token to revoke. - string id = 1; -} - -// Revoke access token response. -message RevokeAccessTokenResponse { - // Access token information. - AccessTokenInfo info = 1; -} - -// List access tokens request. -message ListAccessTokensRequest { - // List access tokens that begin with this prefix. - string prefix = 1; - // Only return access tokens that lexicographically start after this ID. - string start_after = 2; - // Number of results, up to a maximum of 1000. - optional uint64 limit = 3; -} - -// List access tokens response. -message ListAccessTokensResponse { - // Access tokens information. - repeated AccessTokenInfo access_tokens = 1; - // If set, indicates there are more results that can be listed with `start_after`. - bool has_more = 2; -} - -// Access token information. -message AccessTokenInfo { - // Access token ID. - // It must be unique to the account and between 1 and 96 characters. - string id = 1; - // Expiration time in seconds since Unix epoch. - // If not set, the expiration will be set to that of the requestor's token. - optional uint32 expires_at = 2; - // Namespace streams based on the configured stream-level scope, which must be a prefix. - // Stream name arguments will be automatically prefixed, and the prefix will be stripped - // when listing streams. - bool auto_prefix_streams = 3; - // Access token scope. - AccessTokenScope scope = 4; -} - -// Access token scope. -message AccessTokenScope { - // Basin names allowed. - ResourceSet basins = 1; - // Stream names allowed. - ResourceSet streams = 2; - // Token IDs allowed. - ResourceSet access_tokens = 3; - // Access permissions at operation group level. - PermittedOperationGroups op_groups = 4; - // Operations allowed for the token. - // A union of allowed operations and groups is used as an effective set of allowed operations. - repeated Operation ops = 5; -} - -// Set of named resources. -message ResourceSet { - // Matching rule. - oneof matching { - // Match only the resource with this exact name. - // Use an empty string to match no resources. - string exact = 1; - // Match all resources that start with this prefix. - // Use an empty string to match all resource. - string prefix = 2; - } -} - -// Issue access token response. -message IssueAccessTokenResponse { - // Created access token. - string access_token = 1; -} - -/// BasinService /// - -// Stream information. -message StreamInfo { - // Stream name. - string name = 1; - // Creation time in seconds since Unix epoch. - uint32 created_at = 2; - // Deletion time in seconds since Unix epoch, if the stream is being deleted. - optional uint32 deleted_at = 3; -} - -// List streams request. -message ListStreamsRequest { - // List stream names that begin with this prefix. - string prefix = 1; - // Only return stream names that lexicographically start after this name. - // This can be the last stream name seen in a previous listing, to continue from there. - // It must be greater than or equal to the prefix if specified. - string start_after = 2; - // Number of results, up to a maximum of 1000. - optional uint64 limit = 3; -} - -// List streams response. -message ListStreamsResponse { - // Matching streams. - repeated StreamInfo streams = 1; - // If set, indicates there are more results that can be listed with `start_after`. - bool has_more = 2; -} - -// Create stream request. -message CreateStreamRequest { - // Stream name, which must be unique within the basin. - // It can be an arbitrary string upto 512 characters. - // Backslash (`/`) is recommended as a delimiter for hierarchical naming. - string stream = 1; - // Configuration for the new stream. - StreamConfig config = 2; -} - -// Create stream response. -message CreateStreamResponse { - // Information about the newly created stream. - StreamInfo info = 1; -} - -// Delete stream request. -message DeleteStreamRequest { - // Stream name. - string stream = 1; -} - -// Delete stream response. -message DeleteStreamResponse {} - -// Get stream configuration request. -message GetStreamConfigRequest { - // Stream name. - string stream = 1; -} - -// Get stream configuration response. -message GetStreamConfigResponse { - // Stream configuration. - StreamConfig config = 1; -} - -// Reconfigure stream request. -message ReconfigureStreamRequest { - // Stream name. - string stream = 1; - // Stream configuration with updated values. - StreamConfig config = 2; - // Specifies the pieces of configuration being updated. - // See https://protobuf.dev/reference/protobuf/google.protobuf/#field-mask - google.protobuf.FieldMask mask = 3; -} - -// Reconfigure stream response. -message ReconfigureStreamResponse { - // Stream configuration. - StreamConfig config = 1; -} - -/// StreamService /// - -// Check tail request. -message CheckTailRequest { - // Stream name. - string stream = 1; -} - -// Check tail response. -message CheckTailResponse { - // Sequence number that will be assigned to the next record on the stream. - // It will be 0 for a stream that has not been written to. - uint64 next_seq_num = 1; - // Timestamp of the last durable record on the stream. - // It starts out as 0 for a new stream. - uint64 last_timestamp = 2; -} - -// Input for append requests. -message AppendInput { - // Stream name. Optional for subsequent requests in the session. - string stream = 1; - // Batch of records to append atomically, which must contain at least one record, and no more than 1000. - // The total size of a batch of records may not exceed 1MiB of metered bytes. - repeated AppendRecord records = 2; - // Enforce that the sequence number issued to the first record matches. - optional uint64 match_seq_num = 3; - // Enforce a fencing token which must have been previously set by a `fence` command record. - optional string fencing_token = 4; -} - -// Output from append response. -message AppendOutput { - // Sequence number of first record appended. - uint64 start_seq_num = 1; - // Timestamp of the first record appended. - uint64 start_timestamp = 4; - // Sequence number of last record appended + 1. - // `end_seq_num - start_seq_num` will be the number of records in the batch. - uint64 end_seq_num = 2; - // Timestamp of the last record appended. - uint64 end_timestamp = 5; - // Tail of the stream, i.e. sequence number that will be assigned to the next record. - // This can be greater than `end_seq_num` in case of concurrent appends. - uint64 next_seq_num = 3; - // Timestamp of the last durable record on the stream. - uint64 last_timestamp = 6; -} - -// Append request. -message AppendRequest { - // Request parameters for an append. - AppendInput input = 1; -} - -// Append response. -message AppendResponse { - // Response details for an append. - AppendOutput output = 1; -} - -// Append session request. -message AppendSessionRequest { - // Request parameters for an append. - AppendInput input = 1; -} - -// Append session response. -message AppendSessionResponse { - // Response details for an append. - AppendOutput output = 1; -} - -// Output of a read. -message ReadOutput { - // Batch of records or the next sequence number on the stream. - oneof output { - // Batch of records. - // It can only be empty when not in a session context, - // if the request cannot be satisfied without violating its limit. - SequencedRecordBatch batch = 1; - // Tail of the stream, i.e. sequence number that will be assigned to the next record. - // It will be returned if the requested starting position is greater than the tail, - // or only in case of a limited read, equal to it. - // It will also be returned if there are no records on the stream between the - // requested starting position and the tail. - uint64 next_seq_num = 3; - } - // first_seq_num. - reserved 2; -} - -// Read request. -message ReadRequest { - // Stream name. - string stream = 1; - // Starting position for records. - // Retrieved batches will start at the first record whose position is greater than or equal to it. - oneof start { - // Sequence number. - uint64 seq_num = 2; - // Timestamp. - uint64 timestamp = 4; - // Number of records before the tail, i.e. before the next sequence number. - uint64 tail_offset = 5; - } - // Limit how many records can be returned. - // This will get capped at the default limit, - // which is up to 1000 records or 1MiB of metered bytes. - ReadLimit limit = 3; - // Exclusive timestamp to read until. - // If provided, this is applied as an additional constraint on top of the `limit`, - // and will guarantee that all records returned have timestamps < the provided `until`. - optional uint64 until = 6; - // Start reading from the tail if the requested position is beyond it. - // Otherwise, the next sequence number will be returned. - bool clamp = 7; -} - -// Read response. -message ReadResponse { - // Response details for a read. - ReadOutput output = 1; -} - -// Limit how many records can be retrieved. -// If both count and bytes are specified, either limit may be hit. -message ReadLimit { - // Record count limit. - optional uint64 count = 1; - // Metered bytes limit. - optional uint64 bytes = 2; -} - -// Read session request. -message ReadSessionRequest { - // Stream name. - string stream = 1; - // Starting position for records. - // Retrieved batches will start at the first record whose position is greater than or equal to it. - oneof start { - // Sequence number. - uint64 seq_num = 2; - // Timestamp. - uint64 timestamp = 5; - // Number of records before the tail, i.e. the next sequence number. - uint64 tail_offset = 6; - } - // Limit on how many records can be returned. When a limit is specified, the session will be terminated as soon as - // the limit is met, or when the current tail of the stream is reached -- whichever occurs first. - // If no limit is specified, the session will remain open after catching up to the tail, and continue following - // in real-time as new messages are written to the stream. - ReadLimit limit = 3; - // Heartbeats can be enabled to monitor end-to-end session health. - // A heartbeat will be sent when the initial switch to following in real-time happens, - // as well as when no records are available at a randomized interval between 5 and 15 seconds. - bool heartbeats = 4; - // Exclusive timestamp to read until. - // If provided, this is applied as an additional constraint on top of the `limit`, - // and will guarantee that all records returned have timestamps < the provided `until`. - optional uint64 until = 7; - // Start reading from the tail if the requested position is beyond it. - // Otherwise, the next sequence number will be returned. - bool clamp = 8; -} - -// Read session response. -message ReadSessionResponse { - // Response details for a read. - // This will not be set in case of a heartbeat message. - optional ReadOutput output = 1; -} - -/// Common types /// - -// Storage class for recent writes. -enum StorageClass { - // Defaults to `STORAGE_CLASS_EXPRESS`. - STORAGE_CLASS_UNSPECIFIED = 0; - // Standard, which offers end-to-end latencies under 500 ms. - STORAGE_CLASS_STANDARD = 1; - // Express, which offers end-to-end latencies under 50 ms. - STORAGE_CLASS_EXPRESS = 2; -} - -// Timestamping mode. -// Note that arrival time is always in milliseconds since Unix epoch. -enum TimestampingMode { - // Defaults to `TIMESTAMPING_MODE_CLIENT_PREFER`. - TIMESTAMPING_MODE_UNSPECIFIED = 0; - // Prefer client-specified timestamp if present otherwise use arrival time. - TIMESTAMPING_MODE_CLIENT_PREFER = 1; - // Require a client-specified timestamp and reject the append if it is missing. - TIMESTAMPING_MODE_CLIENT_REQUIRE = 2; - // Use the arrival time and ignore any client-specified timestamp. - TIMESTAMPING_MODE_ARRIVAL = 3; -} - -// Stream configuration. -message StreamConfig { - message Timestamping { - // Timestamping mode for appends that influences how timestamps are handled. - TimestampingMode mode = 1; - // Allow client-specified timestamps to exceed the arrival time. - // If this is false or not set, client timestamps will be capped at the arrival time. - optional bool uncapped = 2; - } - message DeleteOnEmpty { - // Minimum age in seconds before an empty stream can be deleted. - // Set to 0 (default) to disable (don't delete automatically). - uint64 min_age_secs = 1; - } - message InfiniteRetention {} - // Storage class for recent writes. - StorageClass storage_class = 1; - // Retention policy for the stream. - // If unspecified, the default is to retain records for 7 days. - oneof retention_policy { - // Age in seconds for automatic trimming of records older than this threshold. - // This must be set to a value greater than 0 seconds. - uint64 age = 2; - // Retain records unless explicitly trimmed. - InfiniteRetention infinite = 7; - } - // Replaced with `timestamping`. - reserved 3, 4; - // Timestamping behavior. - Timestamping timestamping = 5; - // Delete-on-empty configuration. - DeleteOnEmpty delete_on_empty = 6; -} - -// Basin configuration. -message BasinConfig { - // Default stream configuration. - StreamConfig default_stream_config = 1; - // Create stream on append if it doesn't exist, - // using the default stream configuration. - bool create_stream_on_append = 2; - // Create stream on read if it doesn't exist, - // using the default stream configuration. - bool create_stream_on_read = 3; -} - -// Current state of the basin. -enum BasinState { - // Unspecified. - BASIN_STATE_UNSPECIFIED = 0; - // Basin is active. - BASIN_STATE_ACTIVE = 1; - // Basin is being created. - BASIN_STATE_CREATING = 2; - // Basin is being deleted. - BASIN_STATE_DELETING = 3; -} - -// Basin information. -message BasinInfo { - // Basin name. - string name = 1; - // Basin scope. - BasinScope scope = 5; - // Basin state. - BasinState state = 4; -} - -// Headers add structured information to a record as name-value pairs. -message Header { - // Header name blob. - // The name cannot be empty, with the exception of an S2 command record. - bytes name = 1; - // Header value blob. - bytes value = 2; -} - -// Record to be appended to a stream. -message AppendRecord { - // Timestamp for this record. - // Precise semantics depend on the stream's `timestamping` config. - optional uint64 timestamp = 3; - // Series of name-value pairs for this record. - repeated Header headers = 1; - // Body of this record. - bytes body = 2; -} - -// Record retrieved from a stream. -message SequencedRecord { - // Sequence number assigned to this record. - uint64 seq_num = 1; - // Timestamp for this record. - uint64 timestamp = 4; - // Series of name-value pairs for this record. - repeated Header headers = 2; - // Body of this record. - bytes body = 3; -} - -// A batch of sequenced records. -message SequencedRecordBatch { - // Batch of sequenced records. - repeated SequencedRecord records = 1; -} diff --git a/src/s2_sdk/_generated/s2/v1/s2_pb2.py b/src/s2_sdk/_generated/s2/v1/s2_pb2.py index a2ce856..c921bff 100644 --- a/src/s2_sdk/_generated/s2/v1/s2_pb2.py +++ b/src/s2_sdk/_generated/s2/v1/s2_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: s2/v1/s2.proto -# Protobuf Python Version: 5.29.0 +# Protobuf Python Version: 6.31.1 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor @@ -12,7 +12,7 @@ from google.protobuf.internal import builder as _builder _runtime_version.ValidateProtobufRuntimeVersion( - _runtime_version.Domain.PUBLIC, 5, 29, 0, "", "s2/v1/s2.proto" + _runtime_version.Domain.PUBLIC, 6, 31, 1, "", "s2/v1/s2.proto" ) # @@protoc_insertion_point(imports) diff --git a/src/s2_sdk/_generated/s2/v1/s2_pb2.pyi b/src/s2_sdk/_generated/s2/v1/s2_pb2.pyi index de57f04..a6d1aed 100644 --- a/src/s2_sdk/_generated/s2/v1/s2_pb2.pyi +++ b/src/s2_sdk/_generated/s2/v1/s2_pb2.pyi @@ -1,6 +1,6 @@ +from collections.abc import Iterable as _Iterable +from collections.abc import Mapping as _Mapping from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping from typing import Optional as _Optional from typing import Union as _Union diff --git a/update_specs b/update_specs index 3b93c04..10e7ac3 100755 --- a/update_specs +++ b/update_specs @@ -13,5 +13,5 @@ uv run python -m grpc_tools.protoc \ find . -name '*.py' | xargs -I{} sed -i '' 's/from s2\.\(v[0-9][a-z0-9]*\) import s2_pb2/from s2_sdk._generated.s2.\1 import s2_pb2/' {} cd ../../.. -# Run checks -uv run poe checker +# Fix generated code quality +uv run poe cq-fix