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

Smithy4s Kinesis Client #36

Merged
merged 32 commits into from
Feb 12, 2023
Merged

Smithy4s Kinesis Client #36

merged 32 commits into from
Feb 12, 2023

Conversation

etspaceman
Copy link
Owner

@etspaceman etspaceman commented Feb 5, 2023

Changes Introduced

Introduces a Smithy4s Kinesis Client implementation, bundled with logs and localstack support. Important decisions:

  • Slf4j was not included as the default logger for this module, as we would like to eventually cross-build this for scalajs/native. Instead, a NoOp logger is the default and users can provide their own implementations as needed. This matches the approach that Http4s is using in their upcoming changes.
  • Scoverage was removed as there were issues with running coverage tests with smithy4sGenerate. There is little actual benefit to scoverage, so it feels safe to remove
  • sbt-projectmatrix was included to help reason between the scala version differences, as Smithy4s does not offer a 2.12 version of the AWS modules
  • Using scalafmt instead of scalafix to organize imports
  • sbt-typelevel's MergifyPlugin was included to help manage that file

Applicable linked issues

#17 #16

Checklist (check all that apply)

  • This change maintains backwards compatibility
  • I have introduced tests for all new features and changes
  • I have added documentation covering all new features and changes
  • This pull-request is ready for review

@etspaceman
Copy link
Owner Author

@kubukoz per our convo, I tried setting up a client using smithy4s, but ran into a few weird bugs with the build. Mostly, I've been dealing with using a subset of scala versions in the smithy project as smithy4s is only publishing Scala 2.13/Scala 3 artifacts, so I am poorly attempting to use sbt-projectmatrix as well. But also, I ran into this when compiling on scala 2.13 versions:

[error] (smithy4s-client / Compile / smithy4sCodegen) java.lang.ClassCastException: class software.amazon.smithy.rulesengine.traits.ContextParamTrait cannot be cast to class software.amazon.smithy.rulesengine.traits.ContextParamTrait (software.amazon.smithy.rulesengine.traits.ContextParamTrait is in unnamed module of loader java.net.URLClassLoader @17cc56dd; software.amazon.smithy.rulesengine.traits.ContextParamTrait is in unnamed module of loader java.net.URLClassLoader @756a6cba)

)
})
}

final implicit class Kinesi4catsProjectOps(private val p: Project)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fyi: typo in class name

@kubukoz
Copy link
Collaborator

kubukoz commented Feb 5, 2023

Never seen that before I think... perhaps @Baccata will have more insight. I know there was talk of removing the rules engine traits from the model before loading, and in general smithy4s will eventually make it easier to use AWS specs.

disneystreaming/smithy4s#674 (comment) and that general thread may have more useful context

@kubukoz
Copy link
Collaborator

kubukoz commented Feb 5, 2023

smithy4s-client / Compile / smithy4sCodegen

I ran that in sbt as smithy4s-client/compile, and it worked. CI seems to be failing because the yml generated doesn't match the one checked in, so it's hard for me to see the issue in CI either.

Additionally it'd be great to minimize any issue you encounter with smithy4s, as your build is pretty big and there could be multiple things at play

@kubukoz
Copy link
Collaborator

kubukoz commented Feb 5, 2023

if you do manage to hit this again, can you try with a local snapshot of smithy4s from the series/0.17 branch?

@etspaceman
Copy link
Owner Author

etspaceman commented Feb 5, 2023

Thanks for looking into it @kubukoz ! I'll be out of pocket today but I'll see if I can get this PR cleaned up and reproduce the same. And yes, I'll try the new version as well!

@Baccata
Copy link

Baccata commented Feb 6, 2023

@etspaceman don't bother trying a snapshot, it does fix the bug you're currently encountering but another unrelated bug was introduce which leads the generated code for the smithy.rules to be generated twice. I'm in the process of fixing it

@Baccata
Copy link

Baccata commented Feb 6, 2023

Here's a fix to the newly introduced bug I'm talking about : disneystreaming/smithy4s#789

@etspaceman
Copy link
Owner Author

etspaceman commented Feb 6, 2023

OK PR is cleaned up with clean reproduce, you should be able to get this via doing sbt smithy4s-client3/compile

[error] stack trace is suppressed; run last smithy4s-client3 / Compile / smithy4sCodegen for the full output
[error] (smithy4s-client3 / Compile / smithy4sCodegen) java.lang.ClassCastException: class software.amazon.smithy.rulesengine.traits.ContextParamTrait cannot be cast to class software.amazon.smithy.rulesengine.traits.ContextParamTrait (software.amazon.smithy.rulesengine.traits.ContextParamTrait is in unnamed module of loader java.net.URLClassLoader @485438eb; software.amazon.smithy.rulesengine.traits.ContextParamTrait is in unnamed module of loader java.net.URLClassLoader @1f8c81d0)

@kubukoz
Copy link
Collaborator

kubukoz commented Feb 6, 2023

I can't see it with just client3, but I can see it with this sequence:

  1. smithy4s-client/compile
  2. smithy4s-client3/compile

Updating to a local snapshot of disneystreaming/smithy4s#789 seems to make it work.

@etspaceman
Copy link
Owner Author

@kubukoz It does make this particular error go away but then a number of compiler errors come on due to the other bug that @Baccata found.

It does seem to be working from the PR branch in @Baccata 's proposal! So that's great 😄

.scalafix.conf Outdated
@@ -1,4 +1,4 @@
rules = [DisableSyntax, NoValInForComprehension, ProcedureSyntax, OrganizeImports]
rules = [DisableSyntax, NoValInForComprehension, OrganizeImports]
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sbt-projectmatrix added the impact of having scalafmt/scalafix operations run for each project inside of the matrix, including scala 3. These updates allow us to run it on scala 3.

"com.amazonaws.kinesis"
)
)
.jvmPlatform(last2ScalaVersions)
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brought in sbt-projectmatrix to work through having a subset of scala versions supported here (Smithy4s AWS does not have a 2.12 offering)

@@ -140,7 +140,7 @@ object DockerComposePlugin extends AutoPlugin {
configuration: Configuration,
build: Boolean,
projects: List[Project]
): Seq[Setting[_]] =
): Seq[Setting[_]] = inConfig(configuration)(
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixes the integration tests always targeting the functional test file...

@@ -186,6 +186,17 @@ object Kinesis4CatsPlugin extends AutoPlugin {
Test / testOptions ++= {
List(Tests.Argument(MUnitFramework, "+l"))
},
scalacOptions ++= {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import kinesis4cats.smithy4s.client.KinesisClient
import kinesis4cats.smithy4s.client.middleware._

object LocalstackKinesisClient {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation here is almost identical to the KinesisClient, except it adds an additional middleware to proxy the request, as well as uses some mock credentials.

val http4sResponseLogEncoder: LogEncoder[Response[F]]
)

def apply[F[_]](
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very simple implementation. Basically the provided generated client from Smithy4s with some middleware to add standard logging.


import kinesis4cats.logging.LogContext

object RequestLogger {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly copied this from http4s. The http4s implementation records the requests and responses as a part of the message. This one will encode them as a part of the context, per the structured logging desires.

`trait`.toShapeId() == LengthTrait.ID &&
shape.toShapeId() == metricsNameListShapeId
) {
LengthTrait.builder().min(0).max(7).build()
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually this is 1-7. Set to 0-7

IntegerShape
.builder()
.id(
ShapeId.fromParts("com.amazonaws.kinesis", "NonNegativeIntegerObject")
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Counterpart to PositiveIntegerObject

`trait`.toShapeId() == LengthTrait.ID &&
shape.toShapeId() == metricsNameListShapeId
) {
LengthTrait.builder().min(0).max(7).build()
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty responses are possible, this seems to be a bug w/ the smithy file

`trait`
.asInstanceOf[DocumentationTrait] // scalafix:ok
.getValue()
.replace("ListStreamConsumersInput$NextToken", "NextToken")
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dollar sign is not valid for scaladoc, so we replace it here.

`trait`
.asInstanceOf[DocumentationTrait] // scalafix:ok
.getValue()
.replace("ListShardsInput$NextToken", "NextToken")
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (memberName == "FailedRecordCount")
MemberShape
.builder()
.target(nonNegativeIntegerObjectShape.getId())
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FailedRecordCount can be 0. This is a bug with smithy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants