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

Instances for com.twitter.concurrent.AsyncStream #62

Merged
merged 9 commits into from
Mar 19, 2018
Merged

Instances for com.twitter.concurrent.AsyncStream #62

merged 9 commits into from
Mar 19, 2018

Conversation

crispywalrus
Copy link
Contributor

Something like a year ago AsyncStream was added into twitter util. Up till now it was a mystery to me. Now that I've met it I'd like it to play nicely with the rest of cats and in order to do that it needs some instance magic. This aims to provide that for those type classes I currently need. It bothers me that I had to Await for Eq to work but since that's what was done for Future I assume it's acceptable.

I hope.

It does in fact test out nicely.

@codecov-io
Copy link

codecov-io commented Mar 14, 2018

Codecov Report

Merging #62 into master will decrease coverage by 3.37%.
The diff coverage is 0%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #62      +/-   ##
==========================================
- Coverage   52.84%   49.46%   -3.38%     
==========================================
  Files           8        9       +1     
  Lines         176      188      +12     
  Branches        2        2              
==========================================
  Hits           93       93              
- Misses         83       95      +12
Impacted Files Coverage Δ
util/src/main/scala/io/catbird/util/var.scala 0% <ø> (ø) ⬆️
...l/src/main/scala/io/catbird/util/asyncstream.scala 0% <0%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5336d5f...2748bf1. Read the comment docs.

@travisbrown
Copy link
Contributor

Thanks! And yep, that's the only way to do Eq (and is why that method's not implicit).

Did you look into writing a stack-safe tailRecM?

@crispywalrus
Copy link
Contributor Author

I haven't yet, I just cribbed the current unsafe one from Var and called it good for now. I'm thinking monoid is also something worth creating an instance for but I wanted some feedback before continuing in case I had run something off the rails.

@crispywalrus
Copy link
Contributor Author

crispywalrus commented Mar 15, 2018

@travisbrown I switched Monad out for StackSafeMonad and changed the tests to assume stack safety and all seems well

@crispywalrus
Copy link
Contributor Author

@travisbrown I'm at the point where I've gotten the code I want in and ready. Not sure why it's being reported as not tested, it should be fully covered by the law checks.

@travisbrown
Copy link
Contributor

Sorry about the delay in review—this looks generally good to me, but I think we should be sure to create non-singleton arbitrary instances (which should improve test coverage as well).

courtesy of StackSafeMonad. Tests now assume stack safety and continue
to pass.
for AsyncStream
@crispywalrus
Copy link
Contributor Author

I'm not sure what you mean by "non-singleton arbitrary instances"

@travisbrown
Copy link
Contributor

Right now you have Arbitrary(A.arbitrary.map(AsyncStream.of)), which means that all the AsyncStream values generated for laws checking will consist of a single arbitrary element (i.e. no empty streams, no streams longer than one).

@travisbrown
Copy link
Contributor

What about the following:

implicit def asyncStreamArbitrary[A](implicit A: Arbitrary[A]): Arbitrary[AsyncStream[A]] =
  Arbitrary(
    Arbitrary.arbitrary[Stream[A]].map(AsyncStream.fromSeq)
  )

The current version using AsyncStream(_) is essentially the same as of, since there will only ever be a single argument for the A*.

@travisbrown
Copy link
Contributor

Thanks! Just restarted the build to see if that resolves the timeouts.

see if bumping the heap available to sbt fixes things. It's a valid technique with sbt and travis
/**
* Note that this implementation is not stack-safe.
*/
final def tailRecM[A, B](a: A)(f: A => Var[Either[A, B]]): Var[B] = f(a).flatMap {
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like the law-checking for Var is still using StackUnsafeMonad, though?

Copy link
Contributor Author

@crispywalrus crispywalrus Mar 19, 2018

Choose a reason for hiding this comment

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

Yes, it still is. The easy fix of using StackSafeMonad failed and rather than leave the code seeming to be be stack safe I left it unchanged (and still commented). I didn't have the time at hand to dive into Var to understand why it's not behaving. I think I should early this week

double heap for sbt/build
@travisbrown
Copy link
Contributor

I'd be happy to see this merged with both AsyncStream and Var switched (back) to explicitly non-stack-safe tailRecM implementations and stackUnsafeMonad laws checking, and then we can handle stack safety for each of those individually in separate tickets / PRs.

@crispywalrus
Copy link
Contributor Author

Alright, I'll revert back to the explicit unsafe version of Var but I'd like to leave the stack safe version of AsyncStream in if I could. It's tested and working.

chris vale added 2 commits March 19, 2018 08:18
since even the StackSafeMonad version threw stack overflow errors.
In order to test it it requires Cogen which needs Comonad which I
can't figure out how to implement. Return arbitrary instances to use
`AsyncStream.of` allowing the testing of only one item at a time. This
is due to the fact that `fromSeq` causes testing hangs locally.
@crispywalrus
Copy link
Contributor Author

Looking at the codecov report and comparing it to what scoverage says makes me wonder if there's something missing in the integration. scoverage says the code coverage for the util module is 92% and that it's 100% for the rest of the modules. Aggregating the reports with scoverage then gives a coverage percentage as 94% which seems much closer to the truth than 49.46%. I'm not familiar with codecov or its API (which seems little more than upload the cobetura files) so I'm not sure what might be wrong.

@travisbrown
Copy link
Contributor

@crispywalrus Yeah, I don't know what's up with the codecov reporting. I've seen something similar in other repos—e.g.: circe/circe-derivation#4

@travisbrown travisbrown merged commit d7ef0fb into typelevel:master Mar 19, 2018
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

Successfully merging this pull request may close these issues.

3 participants