-
Couldn't load subscription status.
- Fork 1.4k
Implement ZRefM #3391
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
Implement ZRefM #3391
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love it! Left a few suggestions on the interface. Can be done in follow-ups 💪🏻
| _ <- queue.take.flatMap(b => ref.get.flatMap(a => b.run(a, ref, onDefect))).forever.forkDaemon | ||
| } yield new RefM[A](ref, queue) | ||
|
|
||
| def signalRef[A](a: A): UIO[(RefM[A], Queue[A])] = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few suggestions:
- The returned queue should be a
Dequeue[A]- not sure if we added this here or infeature/zconduit, but it's ZQueue for which the input is Nothing. - Perhaps we could call this
subscriptionRef, and have it return something like:
trait SubscriptionRefM[A] extends RefM[A] { // or ZRef[... Any, A]
def await: UIO[A] = queue.take
}
def subscriptionRef[A](a: A): UIO[SubscriptionRefM[A]]- For the variant in
ZStream, we could have another subtype that extendsSubscriptionRefMwithdef changes = ZStream.fromQueue(queue).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iravid I updated to return a Dequeue and to change the name. I actually had that type signature in an earlier version and thought the type signature made it a little intimidating, but Dequeue is a great addition!
I don't think it is as straightforward to extend RefM because it is a sealed trait and we rely on that for the exhaustiveness of pattern matching in the implementation. Also I would think if we exposed a SubscriptionRef trait we would want the different combinators to return a SubscriptionRef so would have to override them.
This goes a little bit to whether we think of Ref as a data type or an interface. Right now Ref and RefM are very much data types so it isn't really possible to extend them, but you could potentially see them more as interfaces, potentially with RefM and TRef extending Ref. That could allow you to substitute different Ref implementations or extend them. Not sure if that makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, forgot about that. What do you think about this for the streams module:
case class SubscriptionRef(ref: RefM[A], changes: ZStream[A])
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That can also have FunctorFilter methods later on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that is super straightforward. Wraps it up into a nice pair. Very easy to use. And the user can easily access the underlying Ref if they want to, for example to swap into a section of their code. Makes me wonder if we should do something similar for core.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to add SubscriptionRef and change name of combinator on RefM to dequeueRef.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
| * A `SubscriptionRef[A]` contains a `RefM[A]` and a `Stream` that will emit | ||
| * every change to the `RefM`. | ||
| */ | ||
| final case class SubscriptionRef[A](ref: RefM[A], changes: Stream[Nothing, A]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the constructor be private so we can guarantee it is created in the appropriate way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might as well also make it a class so it doesn't have copy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Already done. I'm moving the constructors there as well and adding one that lets you make it in the context of a managed.
| * Creates a new `SubscriptionRef` with the specified value in the context of | ||
| * a `Managed`. | ||
| */ | ||
| def makeManaged[A](a: A): UManaged[SubscriptionRef[A]] = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally I would delete this since the subscription ref is not tied to the returned Managed, and the user can always call toManaged_ themselves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could also tie them together by shutting down the queue in the release action of the Managed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really great work! ❤️ And interesting to get a preview of the sort of thing that can be built with ZRefM...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💪🏻
Add test for Schedule#onDecision and documentation for scheduling (zio#3346) * Add test for Schedule#onDecision and documentation for scheduling * Add documentation to datatypes, remove console functions from ScheduleSpec * fix mdoc compile issue specialize ChunkBuilder (zio#3400) Implement ZRefM (zio#3391) * implement ZRefM * fix Scala 2.13 compatibility issue * address review comments * implement SubscriptionRef * make constructor private * remove managed variant * remove unused import Implement ZIO#mapEffect (zio#3404) * implement mapEffect * implement mapPartial Improve TArray's performance (zio#3407) * Benchmark TArray * Implement fold and transform via unsafe * Improve readability * Implement find via unsafe * Implement findLast via unsafe * Implement foldM via unsafe * Benchmark indexWhere * Implement transformM via unsafe * Implement indexWhere via unsafe * Implement lastIndexOf via unsafe * Remove duplicated code * Implement foldM via ZIO.foldLeft * Remove 0-sized array from benchmark * Implement reduceOption via unsafe * Implement findM via foldM * Help inference via Option.empty * Implement findM via iterate * Implement findLastM via iterate * Remove useless val * Format the sources Update sbt-header to 5.6.0 (zio#3411) Add AssertionM for effectfull assertions (zio#3403) Add result field to AssertionValue to avoid test reevaluation. Protect AssertionValue.assertion to avoid test reevaluation. Use lazy val tryValue = Try(value) to avoid exception reevaluation: lazy val stores only successful case. implement launch (zio#3415) Add alternative combinator to ZSTM (zio#3414) * Drop duplicated test * Remove unnecessary .unit calls * Align the naming * Write failing tests * Keep semantically correct orElse tests * Fix test expectations * Fix orElse behavior on failures * Fix orElse behavior on retries * Reduce flakiness * Revert orElse changes * Introduce alternative combinator * Update docs * Reduce flakiness * Make right retry explicit * Race updater and transaction * Move left-right recovery test to JVM tests * Drop E from orElseSucceed Co-Authored-By: John A. De Goes <[email protected]> * Rename alternative to orTry Co-Authored-By: John A. De Goes <[email protected]> * Revert "Move left-right recovery test to JVM tests" This reverts commit 19f1162. * Tag retry test as JVM-only * Fix compilation issues * Fix docs * Improve scaladoc Co-Authored-By: John A. De Goes <[email protected]> * Fix doc mistake Co-authored-by: John A. De Goes <[email protected]> Update sbt-scalafix to 0.9.15 (zio#3423) Optimize TQueue (zio#3421) Update sbt-ci-release to 1.5.3 (zio#3425) ZIO Test: Support Laws for Capabilities Parameterized on Two Types (zio#3420) * implement ZLaws2 * use AnyF Back up Chunk[Boolean] by Chunk.BitChunks (zio#3419) fix publishing (zio#3433) WIP: Scala.js upgrade to v1.0.0 (zio#2392) (zio#2479) * Update to Scala.js 1.0.0-RC2 * fix for passing testJS * formatting fix * Merge remote-tracking branch 'upstream/master' into feature/scalajs-1.0.0-RC2 * Merge branch 'master' of https://github.com/zio/zio into feature/scalajs-1.0.0-RC2 * sonatype resolver added for izumi-reflect; magnolia updated to v0.12.8 Fix Scala.js build (post zio#2479) (zio#3436) * Fix Scala.js build (post zio#2479) * Move back to shared/Executor source and add jvm/js/native ExecutorPlatformSpecific trait * Fix imports causing build failure on 2.13/dotty Update Magnolia (zio#3432) * Update Magnolia There is a bug in Magnolia versions < 0.15 which causes derivation for case classes with default values to fail. The update should fix it. * Add scala-reflect % Provided dependency, now required for magnolia & exclude scala-compiler Co-authored-by: Kai <[email protected]> Co-authored-by: Kai <[email protected]> Update nyaya-gen to 0.9.1 (zio#3438) Remove sonatype public resolver (zio#3434) Add specialized accessor operations to Chunk (zio#3431) * Add specialized accessor operations to Chunk * Generate only non-empty chunks using chunkWithIndex generator Add ZIO STM blogpost (zio#3443) generalize (zio#3439) Update scala-java-time to 2.0.0 (zio#3446) suspend effects (zio#3444) Fix Publishing on Master (zio#3437) * fix publishing * fix bug add Scalac logo to the Sponsors section in Readme (zio#3379) Implement ZIO#service (zio#3422) * implement getService * add variants * rename Add Diagnostic Code to Has (zio#3377) * add diagnostic code * Fix environment composition * Fix 2.11/dotty Co-authored-by: ioleo <[email protected]> Use short forms where it makes sense (zio#3452) * Use short forms where it makes sense * One more `none` usage. Update to izumi-reflect 1.0.0-M1, use izumi-reflect on dotty (zio#3445) * Update to izumi-reflect-1.0.0-M1, depend on izumi-reflect in dotty * Use one VersionSpecific file for dotty & scala-2 * Adding type signatures to Mock modules to workaround scala/scala3#8764 error: ``` [error] -- Error: PureModule.scala:77:86 [error] 77 | val static = ZIO.accessM[PureModule](_.get.static) [error] | ^ [error] |could not find implicit value for izumi.reflect.Tag[zio.test.mock.module.PureModule.Service]. Did you forget to put on a Tag, TagK or TagKK context bound on one of the parameters in zio.test.mock.module.PureModule.Service? e.g. def x[T: Tag, F[_]: TagK] = .... [error] |I found: [error] | [error] | { [error] | izumi.reflect.Tag.apply[zio.test.mock.module.PureModule.Service](classOf[Any] [error] | , [error] | { [error] | <empty> :izumi.reflect.macrortti.LightTypeTag [error] | } [error] | ):izumi.reflect.Tag[zio.test.mock.module.PureModule.Service] [error] | } [error] | [error] |But method tagFromTagMacro in object Tag does not match type izumi.reflect.Tag[zio.test.mock.module.PureModule.Service]. [error] | [error] |The following import might make progress towards fixing the problem: [error] | [error] | import izumi.reflect.Tag.tagFromTagMacro ``` * add type signature to SpecSpec to workaround error: ``` [error] -- Error: SpecSpec.scala:17:51 [error] 17 | val layer = ZLayer.succeed(new Module.Service {}) [error] | ^ [error] |could not find implicit value for izumi.reflect.Tag[zio.test.SpecSpec.Module.Service]. Did you forget to put on a Tag, TagK or TagKK context bound on one of the parameters in zio.test.SpecSpec.Module.Service? e.g. def x[T: Tag, F[_]: TagK] = .... [error] |I found: [error] | [error] | { [error] | izumi.reflect.Tag.apply[zio.test.SpecSpec.Module.Service](classOf[Any], [error] | { [error] | <empty> :izumi.reflect.macrortti.LightTypeTag [error] | } [error] | ):izumi.reflect.Tag[zio.test.SpecSpec.Module.Service] [error] | } [error] | [error] |But method tagFromTagMacro in object Tag does not match type izumi.reflect.Tag[zio.test.SpecSpec.Module.Service]. [error] | [error] |The following import might make progress towards fixing the problem: [error] | [error] | import izumi.reflect.Tag.tagFromTagMacro ``` * Lift `exceptDotty` from HasSpec & ComposedMockSpec (TaggedSpec still won't pass because deriving is not implemented) * add type signatures to MockSpecUtils, update comments * Workaround type inference-caused test failures in PolyMockSpec - Any was inferred for `Tag` now, probably maybe because Tag parameter is AnyKind, add workaround * Fix `@mockable` macro, restrict valid `Tagged` definitions to just izumi.reflect.Tag * sbt fix fix type signature (zio#3455) Update util-core to 20.4.1 (zio#3457) generalize type signature (zio#3460) doc(test_effects) : add aspect ignore (zio#3462) upgrade monix version (zio#3467) Implement ZManaged#flattenM (zio#3464) * implement flattenM * format * fix Scaladoc reorder type parameters (zio#3463) Implement ZManaged#release (zio#3466) * implement ZManaged#release * rename Use ChunkBuilder more prominently in Chunk (zio#3453) * make Chunk use ChunkBuilder * fix lint failure * consistent parenthesis use * use parens for Chunkbuilder#make * followup * retrigger ci Update reactor-core to 3.3.5.RELEASE (zio#3472) Update magnolia to 0.16.0 (zio#3473) Update nyaya-gen to 0.9.2 (zio#3474) added blog to list (zio#3471) * updated blog for RC18 + http4s .21.x * added new blog to resource page Co-authored-by: Pierre Ricadat <[email protected]> Add zio-easymock to libraries with zio support list (zio#3481) Add ZIO#filterNot and ZSTM#filterNot (zio#3477) * Add ZIO#filterNot and ZSTM#filterNot * Fix typos implement assertElements and assertElements
Resolves #3350. Resolves #3373.
Changes encoding of
RefMto be backed by aSemaphoreinstead of aQueue. ImplementsZRefM, a polymorphic version ofRefMthat supports effectual transformations of values being written and read. Uses this functionality to implementsignalRefcombinator that creates a newRefMand immediately adds a tap that writes all values written to aQueueor aStream.Copying @jeremyrsmith.