Skip to content

Collapse eventstream with the streaming trait #365

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 10, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
264 changes: 47 additions & 217 deletions docs/source/spec/core/event-stream-traits.rst

Large diffs are not rendered by default.

37 changes: 28 additions & 9 deletions docs/source/spec/core/http-traits.rst
Original file line number Diff line number Diff line change
Expand Up @@ -933,7 +933,7 @@ Event streams

When using :ref:`event streams <event-streams>` and HTTP bindings, the
:ref:`httpPayload <httppayload-trait>` trait MUST be applied to any input or
output member targeted by the :ref:`eventStream-trait`.
output member that targets a union with the :ref:`streaming-trait`.

The following example defines an operation that uses an input event stream
and HTTP bindings:
Expand All @@ -951,8 +951,12 @@ and HTTP bindings:

structure PublishMessagesInput {
@httpPayload
@eventStream
messages: Message,
messages: MessageStream,
}

@streaming
union MessageStream {
message: Message,
}

structure Message {
Expand Down Expand Up @@ -980,14 +984,21 @@ and HTTP bindings:
"type": "structure",
"members": {
"messages": {
"target": "smithy.example#Message",
"target": "smithy.example#MessageStream",
"traits": {
"smithy.api#httpPayload": true,
"smithy.api#eventStream": true
"smithy.api#httpPayload": true
}
}
}
},
"smithy.example#MessageStream": {
"type": "union",
"members": {
"message": {
"target": "smithy.example#Message"
}
}
},
"smithy.example#Message": {
"type": "structure",
"members": {
Expand All @@ -1000,7 +1011,7 @@ and HTTP bindings:
}

The following is **invalid** because the operation has the ``http`` trait
and an input member is marked with the ``eventStream`` trait but not
and an input union is marked with the ``streaming`` trait but not
marked with the ``httpPayload`` trait:

.. code-block:: smithy
Expand All @@ -1013,8 +1024,16 @@ marked with the ``httpPayload`` trait:
}

structure InvalidOperationInput {
@eventStream
invalid: Message, // <-- Missing the @httpPayload trait
invalid: MessageStream, // <-- Missing the @httpPayload trait
}

@streaming
union MessageStream {
message: Message,
}

structure Message {
message: String,
}


Expand Down
13 changes: 9 additions & 4 deletions docs/source/spec/core/type-refinement-traits.rst
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,16 @@ in Java).
-------------------

Summary
Indicates that the the data stored in the shape is very large and should
not be stored in memory, or that the size of the data stored in the shape
is unknown at the start of a request.
Indicates that the data represented by the shape needs to be streamed.

When applied to a blob, this simply means that the data could be very
large and thus should not be stored in memory or that the size is unknown
at the start of the request.

When applied to a union, it indicates that shape represents an
`event stream <event-streams>`.
Trait selector::
``blob``
``:each(blob, union)``
Value type
``structure``

Expand Down
34 changes: 23 additions & 11 deletions docs/source/spec/mqtt.rst
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ Trait summary
Binds an operation to send one or more SUBSCRIBE control packets
via the MQTT protocol.
Trait selector
``operation:test(-[output]-> structure -> member[trait|eventStream])``
``operation:test(-[output]-> structure > member > union[trait|streaming])``

*An operation with an output event stream*
Trait value
Expand All @@ -296,8 +296,8 @@ No message is published when using an operation marked with the
``smithy.mqtt#subscribe`` trait. All members of the input of the operation
MUST be marked with valid ``smithy.mqtt#topicLabel`` traits.

The operation MUST define an output shape that has an
:ref:`eventStream <eventStream-trait>`. The top-level output member referenced
The operation MUST define an output shape targets a union with the
:ref:`streaming <streaming-trait>`. The top-level output member referenced
by this trait represents the message(s) sent over the MQTT topic. An
abstraction for automatically subscribing to and asynchronously receiving
events SHOULD be provided by Smithy clients. When that abstraction is
Expand All @@ -311,7 +311,7 @@ from topics.
payload to be sent as the payload of a message.

The following example operation subscribes to the ``events/{id}``
topic using a :ref:`single-event event stream <single-event-event-stream>`:
topic using an :ref:`event stream <event-streams>`:

.. tabs::

Expand All @@ -333,8 +333,12 @@ topic using a :ref:`single-event event stream <single-event-event-stream>`:
}

structure SubscribeForEventsOutput {
@eventStream
events: Event,
events: EventStream,
}

@streaming
union EventStream {
message: Event,
}

structure Event {
Expand Down Expand Up @@ -371,11 +375,19 @@ topic using a :ref:`single-event event stream <single-event-event-stream>`:
"type": "structure",
"members": {
"events": {
"target": "smithy.example#Event",
"traits": {
"smithy.api#eventStream": true
}
"target": "smithy.example#EventStream"
}
}
},
"smithy.example#EventStream": {
"type": "union",
"members": {
"message": {
"target": "smithy.example#Event"
}
},
"traits" {
"smithy.api#streaming": {}
}
},
"smithy.example#Event": {
Expand Down Expand Up @@ -516,7 +528,7 @@ MQTT protocol bindings.
@pattern("^[^#+]+$")
string publish

@trait(selector: "operation:test(-[output]-> structure > member[trait|eventStream])",
@trait(selector: "operation:test(-[output]-> structure > member > union[trait|streaming])",
conflicts: ["smithy.mqtt#publish"])
@tags(["diff.error.const"])
// Matches one or more characters that are not "#" or "+".
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.shapes.StructureShape;
import software.amazon.smithy.model.shapes.ToShapeId;
import software.amazon.smithy.model.traits.EventStreamTrait;
import software.amazon.smithy.model.traits.StreamingTrait;

/**
* Index of operation shapes to event stream information.
Expand Down Expand Up @@ -62,7 +62,8 @@ private void computeEvents(
Map<ShapeId, EventStreamInfo> infoMap
) {
for (MemberShape member : shape.getAllMembers().values()) {
if (member.hasTrait(EventStreamTrait.class)) {
Shape target = model.expectShape(member.getTarget());
if (target.hasTrait(StreamingTrait.class) && target.isUnionShape()) {
createEventStreamInfo(model, operation, shape, member).ifPresent(info -> {
infoMap.put(operation.getId(), info);
});
Expand Down Expand Up @@ -106,15 +107,8 @@ private Optional<EventStreamInfo> createEventStreamInfo(
StructureShape structure,
MemberShape member
) {
EventStreamTrait trait = member.getTrait(EventStreamTrait.class).get();

Shape eventStreamTarget = model.getShape(member.getTarget()).orElse(null);
if (eventStreamTarget == null) {
LOGGER.severe(String.format(
"Skipping event stream info for %s because the %s member target %s does not exist",
operation.getId(), member.getMemberName(), member.getTarget()));
return Optional.empty();
}
Shape eventStreamTarget = model.expectShape(member.getTarget());

// Compute the events of the event stream.
Map<String, StructureShape> events = new HashMap<>();
Expand Down Expand Up @@ -147,7 +141,7 @@ private Optional<EventStreamInfo> createEventStreamInfo(
}

return Optional.of(new EventStreamInfo(
operation, trait, structure,
operation, eventStreamTarget.expectTrait(StreamingTrait.class), structure,
member, eventStreamTarget,
initialMembers, initialTargets,
events));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import software.amazon.smithy.model.shapes.OperationShape;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.shapes.StructureShape;
import software.amazon.smithy.model.traits.EventStreamTrait;
import software.amazon.smithy.model.traits.StreamingTrait;

/**
* Contains extracted event stream information.
Expand All @@ -35,11 +35,11 @@ public final class EventStreamInfo {
private final Map<String, MemberShape> initialMembers;
private final Map<String, Shape> initialTargets;
private final Map<String, StructureShape> events;
private final EventStreamTrait eventStreamTrait;
private final StreamingTrait streamingTrait;

EventStreamInfo(
OperationShape operation,
EventStreamTrait eventStreamTrait,
StreamingTrait streamingTrait,
StructureShape structure,
MemberShape eventStreamMember,
Shape eventStreamTarget,
Expand All @@ -48,7 +48,7 @@ public final class EventStreamInfo {
Map<String, StructureShape> events
) {
this.operation = operation;
this.eventStreamTrait = eventStreamTrait;
this.streamingTrait = streamingTrait;
this.structure = structure;
this.eventStreamMember = eventStreamMember;
this.eventStreamTarget = eventStreamTarget;
Expand All @@ -71,8 +71,8 @@ public OperationShape getOperation() {
*
* @return Returns the event stream trait.
*/
public EventStreamTrait getEventStreamTrait() {
return eventStreamTrait;
public StreamingTrait getStreamingTrait() {
return streamingTrait;
}

/**
Expand Down Expand Up @@ -151,17 +151,6 @@ public Map<String, Shape> getInitialMessageTargets() {
return initialTargets;
}

/**
* Checks if this is a single-event event stream, meaning that only
* a single-event shape is streamed over the event stream zero or
* more times.
*
* @return Returns true if this is a single-event event stream.
*/
public boolean isSingleEvent() {
return eventStreamTarget.isStructureShape();
}

/**
* Returns true if the event stream has an initial-message, meaning
* there are top-level members of the input or output of the operation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import software.amazon.smithy.model.shapes.StructureShape;
import software.amazon.smithy.model.shapes.ToShapeId;
import software.amazon.smithy.model.traits.ErrorTrait;
import software.amazon.smithy.model.traits.EventStreamTrait;
import software.amazon.smithy.model.traits.HttpErrorTrait;
import software.amazon.smithy.model.traits.HttpHeaderTrait;
import software.amazon.smithy.model.traits.HttpLabelTrait;
Expand All @@ -41,6 +40,7 @@
import software.amazon.smithy.model.traits.HttpQueryTrait;
import software.amazon.smithy.model.traits.HttpTrait;
import software.amazon.smithy.model.traits.MediaTypeTrait;
import software.amazon.smithy.model.traits.StreamingTrait;
import software.amazon.smithy.model.traits.TimestampFormatTrait;
import software.amazon.smithy.model.traits.Trait;
import software.amazon.smithy.utils.ListUtils;
Expand Down Expand Up @@ -275,7 +275,7 @@ public Optional<String> determineRequestContentType(ToShapeId operation, String
* to the payload, then the following checks are made:
*
* <ul>
* <li>If the payload has the {@link EventStreamTrait}, then the
* <li>If the payload has the {@link StreamingTrait}, then the
* {@code eventStreamContentType} is returned.</li>
* <li>If the targeted shape is a structure or document type, then
* the {@code documentContentType} is returned.</li>
Expand Down Expand Up @@ -328,7 +328,7 @@ public Optional<String> determineResponseContentType(ToShapeId operationOrError,
* to the payload, then the following checks are made:
*
* <ul>
* <li>If the payload has the {@link EventStreamTrait}, then the
* <li>If the payload has the {@link StreamingTrait}, then the
* {@code eventStreamContentType} is returned.</li>
* <li>If the targeted shape is a structure or document type, then
* the {@code documentContentType} is returned.</li>
Expand Down Expand Up @@ -368,15 +368,13 @@ private String determineContentType(
}

if (binding.getLocation() == HttpBinding.Location.PAYLOAD) {
if (binding.getMember().hasTrait(EventStreamTrait.class)) {
return eventStreamContentType;
}

Shape target = model.getShape(binding.getMember().getTarget()).orElse(null);
if (target == null) {
// Can't determine the content-type because the model is broken :(
// Let other parts of the validation system point this out.
break;
} else if (target.isUnionShape() && target.hasTrait(StreamingTrait.class)) {
return eventStreamContentType;
} else if (target.isDocumentShape() || target.isStructureShape()) {
// Document type and structure targets are always the document content-type.
return documentContentType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
import software.amazon.smithy.model.traits.ErrorTrait;
import software.amazon.smithy.model.traits.EventHeaderTrait;
import software.amazon.smithy.model.traits.EventPayloadTrait;
import software.amazon.smithy.model.traits.EventStreamTrait;
import software.amazon.smithy.model.traits.ExamplesTrait;
import software.amazon.smithy.model.traits.ExternalDocumentationTrait;
import software.amazon.smithy.model.traits.HostLabelTrait;
Expand Down Expand Up @@ -154,7 +153,6 @@ public final class Prelude {
ErrorTrait.ID,
EventHeaderTrait.ID,
EventPayloadTrait.ID,
EventStreamTrait.ID,
ExamplesTrait.ID,
ExternalDocumentationTrait.ID,
HostLabelTrait.ID,
Expand Down

This file was deleted.

Loading