diff --git a/aip/general/0214/aip.md.j2 b/aip/general/0214/aip.md.j2 new file mode 100644 index 00000000..9c625876 --- /dev/null +++ b/aip/general/0214/aip.md.j2 @@ -0,0 +1,39 @@ +# Resource expiration + +Customers often want to provide the time that a given resource or attribute of +a resource is no longer useful or should be deleted. Currently we recommend +that customers do this by specifying an exact "expiration time" into a +`expire_time` field with a timestamp type; however, this adds additional strain +on the user when they want to specify a relative time offset until expiration +rather than a specific time until expiration. + +Furthermore, the world understands the concept of a "time-to-live", often +abbreviated to TTL, but the typical format of this field (an integer, measured +in seconds) results in a sub-par experience when using an auto-generated client +library. + +## Guidance + +Services wishing to convey an expiration **must** rely on a timestamp field +called `expire_time`. Services wishing to allow a relative expiration time +**must** define a `oneof` called `expiration` (or `{something}_expiration`) +containing both the `expire_time` field and a separate [duration][aip-142] +field called `ttl`, the latter marked as input only: + +{% tab proto %} + +{% sample 'expiry.proto', 'message Book' %} + +{% tab oas %} + +{% sample 'expiry.oas.yaml', 'schema' %} + +{% endtabs %} + +Services **must** always return the expiration time in the `expire_time` field +and leave the `ttl` field blank when retrieving the resource. + +Services that rely on the specific semantics of a "time to live" (e.g., DNS +which must represent the TTL as an integer) **may** use an `int64 ttl` field +(and **should** provide an [aip.dev/not-precedent][aip-200] comment in this +case). diff --git a/aip/general/0214/aip.yaml b/aip/general/0214/aip.yaml new file mode 100644 index 00000000..7f367c86 --- /dev/null +++ b/aip/general/0214/aip.yaml @@ -0,0 +1,7 @@ +--- +id: 214 +state: approved +created: 2018-06-19 +placement: + category: design-patterns + order: 120 diff --git a/aip/general/0214/expiry.oas.yaml b/aip/general/0214/expiry.oas.yaml new file mode 100644 index 00000000..b2cfbca3 --- /dev/null +++ b/aip/general/0214/expiry.oas.yaml @@ -0,0 +1,34 @@ +--- +openapi: 3.0.3 +info: + title: Library + version: 1.0.0 +paths: {} +components: + schemas: + Book: + description: This book will self-destruct. + type: object + properties: + name: + type: string + description: | + The name of the book. + Format: publishers/{publisher}/books/{book} + oneOf: + - type: object + properties: + expireTime: + type: string + format: date-time + description: | + Timestamp in UTC of when this resource is considered expired. + - type: object + properties: + ttlSeconds: + type: integer + description: | + The TTL for this resource in seconds. + When this value is passed as input it is returned as the equivalent + expireTime on output. + writeOnly: true diff --git a/aip/general/0214/expiry.proto b/aip/general/0214/expiry.proto new file mode 100644 index 00000000..5240fba0 --- /dev/null +++ b/aip/general/0214/expiry.proto @@ -0,0 +1,42 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +import "google/api/field_behavior.proto"; +import "google/api/resource.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; + +// This book will self-destruct. +message Book { + option (google.api.resource) = { + type: "library.googleapis.com/Book" + pattern: "publishers/{publisher}/books/{book}" + }; + + // The name of the resource; the format is: ... + string name = 1; + + oneof expiration { + // Timestamp in UTC of when this resource is considered expired. + // This is *always* provided on output, regardless of what was sent + // on input. + google.protobuf.Timestamp expire_time = 2; + + // Input only. The TTL for this resource. + google.protobuf.Duration ttl = 3 + [(google.api.field_behavior) = INPUT_ONLY]; + } +}