Skip to content

Latest commit

 

History

History
138 lines (111 loc) · 6.28 KB

README.md

File metadata and controls

138 lines (111 loc) · 6.28 KB

Google Events proto schema

The protos within this directory hierarchy represent the data within events generated by Google eventing infrastructure, usually represented as the data attribute within a CloudEvent. They are provided as machine-readable schemas, allowing libraries of data types to be created to make it easier to consume events.

Relationship between protobuf messages and CloudEvent types

There are two protobuf messages that are relevant for any given CloudEvent type:

  • The "envelope" message (e.g. ObjectFinalizedEvent) representing the complete CloudEvent, including any extension attributes.
  • The "data" message (e.g. StorageObjectData)

There is a 1:1 relationship between CloudEvent types and envelope messages, but a many:1 relationship between CloudEvent types and data messages. In other words, many CloudEvent types can use the same data message. For example, every event associated with something happening to a Cloud Storage object uses StorageObjectData as the data message. Each envelope message specifies the CloudEvent type it's associated with via a proto annotation.

Initially we will generate libraries that only contain the data messages. The event messages serve as useful documentation for the event type strings and extension attributes. They will be included in the libraries at a later date if that proves useful.

Note that each proto package is versioned, but this version is independent of any API version. It would be possible for a single API version to support multiple event versions, or vice versa.

Our convention for event types is to have a dot-separated list of the following values, in the order:

  • google (always)
  • product (e.g. firebase.auth or cloud.storage)
  • resource (e.g. object or document)
  • version (e.g. v1)
  • action (e.g. finalized or deleted)

The "action" is the action that causes the event to be emitted.

The proto package (in the package part of each .proto file) must be google.events.product.version. The .proto files should be in a directory structure where each element of the package name corresponds to a directory. The envelope messages must be in a file named events.proto, and the data messages (including any messages they refer to) must be in a file named data.proto. The purpose of this separation is to allow the envelope and data messages to coexist, but for consumer libraries to be generated that only contain the data messages.

As a complete example, consider the event that is created when a Google Cloud Storage object is finalized:

  • Proto files: google/events/cloud/storage/v1/events.proto and google/events/cloud/storage/v1/data.proto
  • Envelope message: google.events.cloud.storage.v1.ObjectFinalizedEvent
  • Data message: google.events.cloud.storage.v1.StorageObjectData
  • Event type: google.cloud.storage.object.v1.finalized

Note that the events part of the proto package is not part of the CloudEvent type, for brevity. It's included in the proto package to distinguish event message from those used in APIs.

Additionally, the version and resource parts deliberately appear in different orders between fully-qualified message name and CloudEvent type. That reversal may seem confusing initially, but it means that events for multiple resources in the same product (e.g. buckets and objects within Cloud Storage) can use common messages in their definitions.

The product and version parts must be all lower-case to conform with proto package naming conventions. A product may consist of multiple segments (e.g. cloud.storage) but if a single segment consists of multiple words, they should be simply lower-cased. For example, firebase.remoteconfig is the product name for Firebase Remote Config. In this case, the csharp_namespace option (and similar for other languages that generate code from the protos) should be set to indicate the correct word separation via casing.

The resource and action parts are not included in the proto package, so have more flexibility. Multi-word segments should be camel-cased. Full examples of CloudEvent types that involve camel-cased segments include:

  • google.cloud.storage.object.v1.metadataUpdated
  • google.firebase.remoteconfig.remoteConfig.v1.updated

Message naming conventions

While not required for technical correctness, we use a suffix of "Event" for all envelope messages, and a suffix of "Data" for all event data messages. Sometimes it can be convenient to combine the two suffixes. For example, DocumentEventData in the Firestore package is used as the event data message for all document events. This approach should only be taken when it is required for clarity.

We avoid the use either "Event" or "Data" as a suffix for messages which aren't envelope messages or event data messages.

Versioning governance

While not a strict technical necessity, governance rules will strongly encourage all event types for a single resource to create a new version at the same time: if there's a need for google.cloud.storage.object.v2.finalized, then all the other object-related event types (deleted etc) should be available as v2 events as well. However, other resources in the same product do not have to take a new version. This allows users to write common code to handle all events for a single resource, without creating unnecessary churn when only an unrelated resource type needs a new version. (If your code only consumes bucket.v1 events, the introduction of object.v2 events should not affect you.)

Unexpected fields

CloudEvent providers may include additional data fields beyond those documented here. In particular:

  • Some events may include fields with legacy names such as message_id for compatibility purposes.
  • Event providers using proto3 JSON formatting of protobuf Any messages may include a field called @type as a natural artifact of that formatting process.

Neither of these should concern consumers: it's always possible that new fields will have been added to CloudEvents between the time at which the code was built and deployed, and the time at which the CloudEvent is received. Consumers must therefore handle unexpected data fields. This note is primarily to expain some likely causes of unexpected fields to avoid developer confusion.