Skip to content
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

Generated streaming output type is separated from the output type #196

Closed
pslaski opened this issue Apr 21, 2022 · 1 comment
Closed

Generated streaming output type is separated from the output type #196

pslaski opened this issue Apr 21, 2022 · 1 comment

Comments

@pslaski
Copy link

pslaski commented Apr 21, 2022

version: 0.12.13

spec:
`service WalletBackend {
version: "0.0.1",
operations: [Sync],
}

operation Sync {
output: SyncOutput,
}

structure SyncOutput {
blocks: Blocks,
}

@streaming
union Blocks {
block: Block,
}`

the generated SyncOutput is:
case class SyncOutput()

and service method is:
def sync() : F[Unit, Nothing, SyncOutput, Nothing, Blocks]

IMHO to recreate the correct smithy structure Blocks should be a part of SyncOutput and maybe SyncOutput should be StreamingOutput not simple Output

@Baccata
Copy link
Contributor

Baccata commented Apr 22, 2022

Hi @pslaski, thanks for the question.

This is a conscious design decision due to the fact that streaming semantics cannot be simply embedded in the abstractions that allow to abstract over serialisation. For starters, what is a stream ? There's many libraries out there that provide streaming semantics, and we cannot simply align on one because the first design principle of smithy4s is that the generated code should not depend on any third-party library. Also, if you want to use smithy4s conjointly with an effect system (cats-effect/zio), you probably want to use the streaming constructs that are idiomatic to your effect system (respectively fs2/zio-streams).

So when we generate SyncOutput, what type would be the blocks field ? We'd have to come up with some sort of Stream[_] abstract type, which would ripple throughout all the generated case classes, making them awkward to use, and making the inner abstractions of smithy4s even more complicated than they already are. Like, rather than having

trait WalletBackend[F[_,_,_,_,_]] {
  def sync() : F[Unit, Nothing, SyncOutput, Nothing, Blocks]
}

you'd have

trait WalletBackend[Stream[_], F[_, _, _]]{
   def sync() : F[Unit, Nothing, Output[Stream]]
}

And that Stream[_] parameter would ripple throughout the codebase, which would mean that all the abstractions that allow to code generically against services and data would have to be aware of Stream[_], even abstractions that do not require streaming most of the time (like the Schema values we generate for all case classes).

IMHO to recreate the correct smithy structure Blocks should be a part of SyncOutput and maybe SyncOutput should be StreamingOutput not simple Output

To gain some intuition about the separation, you can think about it this way : when you receive an http response, there's always unary data coming from the response headers, and then there's stuff that can be streamed through the body. You should be able to process the unary data separately from how you process the streamed data, and therefore, the separation of streamed elements from non-streamed elements makes sense, which is why we make an educated decision of diverging a little from what you would expect by looking at the smithy files.

I'm closing this issue as it is, as a matter of fact, not an issue

If you want to discuss this further, you can open a discussion instead, but this is something that is extremely unlikely to change in smithy4s.

@Baccata Baccata closed this as completed Apr 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants