Giter Club home page Giter Club logo

Comments (7)

markcowl avatar markcowl commented on May 18, 2024 1

Notes from Design Meeting 4/14

  • Generally agreed on the decorator-based syntax
  • Want to make sure we cover
    • homogenous streaming scenarios (covered)
    • heterogeneous message streaming
  • There are likely desirable additional metadata for protocol-specific bindings for streaming, but these are orthogonal to the proposal
  • Discussed alternate modeling for systems like webPubSub, where client messages / subscription management are represented as individual operations, and there is a separate operation for receiving streamed messages, e.g..
    op joinGroup(JoinGroupRequest): void;
    op leaveGroup(LeaveGroupRequest): void;
    op listen() : @stream GroupMessage[];
  • Need to explore events / webHooks a bit more before the group is completely comfortable with adopting the proposal
  • Would be nice to explore how batching would be similar / different

from cadl.

markcowl avatar markcowl commented on May 18, 2024

Notes from design meeting

  • Update to reflect http metadata proposal
  • Need to add examples for request streaming
    • messaging
    • web pub-sub
    • large file streaming (already covered, I believe)
  • Think about what parts of the proposal for streaming could also apply to batching (for example, representing send-once and send-multiple metadata fields)

from cadl.

timotheeguerin avatar timotheeguerin commented on May 18, 2024

Options

1. @stream decorator

// Helper model
model Stream<T> {
  @stream stream: T[]; // or not an array?
}

// Stream response string
op foo(): {@stream foo: string[]}
op foo(): {...Stream<string>}
// Stream input string
op foo(@stream foo: string[]): void
op foo(...Stream<string>): void

// Stream custom message
model MyMessage {id: string, value: string}
op foo(): {@stream foo: MyMessage[]}
op foo(): {...Stream<MyMessage>}
// Stream custom message
op foo(@stream foo: MyMessage[]): void
op foo(...Stream<MyMessage>): void

2. Stream intrinsic type

Similar to how you would want to return a primitive type as the body(string, number, etc.)

// Helper model
@intrinsic
model Stream<T> {
  stream: T;
}

// Stream response string
op foo(): Stream<string>

// Stream custom message
model MyMessage {id: string, value: string}
op foo(): Stream<MyMessage>
op foo(@body stream Stream<MyMessage>): void;

Doesn't make that much sense with websockets?

op foo(@body stream Stream<MyMessage>): Stream<MyMessage>;

Examples

Messaging

model Message {
  id: string;
  from: string;
  group: string;
  content: string;
}
// Option 1
op messages(@stream messages: Message[]):  {@stream messages: Message[]}
// Option 2
op messages(@body messages: Stream<Message>):  {@body messages: Stream<Message>}

Webpub sub

https://docs.microsoft.com/en-us/azure/azure-web-pubsub/reference-json-webpubsub-subprotocol

alias WebPubSubRequest = JoinGroupRequest | LeaveGroupRequest | SentToGroupRequest

model JoinGroupRequest {
  type: "joinGroup";
  group: string;
  ackId: int32;
}

model LeaveGroupRequest {
  type: "leaveGroup";
  group: string;
  ackId: int32;
}

model SentToGroupRequest {
    type: "sendToGroup";
    group: string;
    ackId : number;
    noEcho: boolean;
    dataType : "json" |"text"|"binary";
    data: string | {};
}

model WebPubSubResponse = AckResponse | MessageResponse;

model AckResponse {
  type:  "ack";
  ackId: number;
  success: boolean;
  error?: {
    name: "Forbidden"|"InternalServerError"|"Duplicate";
    message: string;
  }
}
model MessageResponse {
  type: "message";
  from: "group";
  group: string;
  dataType : "json" |"text"|"binary";
  data: string | {};
  fromUserId: string;
}

model ConnectedSystemResponse {
  type: "system";
  event: "connected";
  userId: string;
  connectionId: string;
}

model DisconnectedSystemResponse {
  type: "system";
  event: "disconnected";
  message: string;
}
// Option 1
op webpubsub(@stream messages: WebPubSubRequest[]):  {@stream messages: WebPubSubResponse[]}
// Option 2
op webpubsub(@body messages: Stream<WebPubSubRequest>): Stream<WebPubSubResponse>

Server side events

model ServerSideEvent {
  id: string;
  event: string;
  data: {};
}

// Option 1
op messages(): {
  @header("Cache-Control") cacheControl: "no-store";
  @header("Content-Type")  contentType: "text/event-stream";
  @stream events: ServerSideEvent[];
}

// Option 2
op messages(): {
  @header("Cache-Control") cacheControl: "no-store";
  @header("Content-Type")  contentType: "text/event-stream";
  @body events: Stream<ServerSideEvent>;
}
// Option 2 alt with named model
model MyType is Stream<ServerSideEvent>{
  @header("Cache-Control") cacheControl: "no-store";
  @header("Content-Type")  contentType: "text/event-stream";
}
op messages(): MyType 

from cadl.

timotheeguerin avatar timotheeguerin commented on May 18, 2024
  • Convert from non stream to stream api
  • How align with pageable?

from cadl.

timotheeguerin avatar timotheeguerin commented on May 18, 2024

Case 1 simple return string

op readLogs(@query fromBytes: int64): string;
// ------------ convert to stream -------------


op readLogs(@query fromBytes: int64): Stream<string>;

Case 2: Include header

op readLogs(@query fromBytes: int64): {@body body: string, @header contentType: "text/plain"};
// ------------ convert to stream -------------

op readLogs(@query fromBytes: int64): {@body stream: Stream<String>, @header contentType: "text/event-stream"};

Case 3: Metadata extract

op readLogs(@query fromBytes: int64): {data: string, lineCount: number, @header contentType: "application/json"};
// ------------ convert to stream -------------

// Option 1 wrap everything in stream type and have everything that should belong in the body be there.
op readLogs(@query fromBytes: int64): Stream<{data: string, lineCount: number, @header contentType: "application/json"}>;

// Option 2: Extract body manually
op readLogs(@query fromBytes: int64): {@body stream: Stream<{data: string, lineCount: number}>, @header contentType: "application/stream+json"};

// Option 3: @stream
op readLogs(@query fromBytes: int64): {@stream stream: {data: string, lineCount: number}, @header contentType: "application/stream+json"};

Case 4: Convert array to stream

op readItems(@query skipCount: number): Foo[];
// ------------ convert to stream -------------

// Now stream the foo items.
op readItems(@query skipCount: number): Stream<Foo>;

Case 5: convert input array to stream

op postItems(@body items: Foo[]): void;
// ------------ convert to stream -------------

// Now stream the foo items into the server.
op readItems(@body items: Stream<Foo>): void;

from cadl.

heaths avatar heaths commented on May 18, 2024

This came up in the API Stewardship Board today in a review, and doing some research on this I also found application/x-ndjson - newline-delimited JSON e.g.,

{"foo":"bar","baz":1}
{"foo":"qux","baz":2}

Seems it's gaining traction and certainly seems a lot more compact than SSE.

from cadl.

iscai-msft avatar iscai-msft commented on May 18, 2024

Want to bump this thread too. I'm working with the batch team, and they have some operations that we generate as a streamed response (swagger ex here)

from cadl.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.