Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions explore/common/src/main/scala/workers/WorkerClient.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import cats.effect.std.UUIDGen
import cats.effect.syntax.all.*
import cats.syntax.all.*
import explore.model.boopickle.Boopickle.*
import explore.model.extensions.*
import fs2.RaiseThrowable
import org.typelevel.log4cats.Logger

Expand Down Expand Up @@ -71,6 +72,7 @@ class WorkerClient[F[_]: {Concurrent, UUIDGen, Logger}, R: Pickler] private (
.evalTap(msg => Logger[F].debug(s"<<< Received msg from server with id [$id]: [$msg]"))
.unNoneTerminate
.rethrow
.onErrorLog(s"Error in worker client request with id [$id]")

/**
* Make a request to the underlying worker and receive a single response (if any) as the effect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package explore.model.boopickle

import boopickle.DefaultBasic.*
import cats.Order.given
import coulomb.*
import eu.timepit.refined.*
import eu.timepit.refined.api.Refined
Expand All @@ -28,6 +29,7 @@ import lucuma.core.model.sequence.flamingos2.Flamingos2FpuMask
import lucuma.core.util.Timestamp

import scala.collection.immutable.TreeMap
import boopickle.CompositePickler

// Boopicklers for catalog related types
trait CatalogPicklers extends CommonPicklers:
Expand Down Expand Up @@ -107,19 +109,18 @@ trait CatalogPicklers extends CommonPicklers:
given [K: Pickler: Ordering, V: Pickler]: Pickler[TreeMap[K, V]] =
transformPickler((m: Map[K, V]) => TreeMap.empty[K, V] ++ m)(_.toMap)

import _root_.cats.Order.given
// summon[Ordering[lucuma.core.util.Timestamp]]

given Pickler[EphemerisTracking] =
transformPickler((m: TreeMap[Timestamp, EphemerisCoordinates]) => EphemerisTracking(m.toSeq*))(
_.toMap
)

given Pickler[Tracking] =
compositePickler[Tracking]
.addConcreteType[SiderealTracking]
.addConcreteType[CompositeTracking]
.addConcreteType[ConstantTracking]
.addConcreteType[EphemerisTracking]
// Recursive class hierarchy must be built in two steps:
// https://github.com/suzaku-io/boopickle/blob/master/doc/ClassHierarchies.md#recursive-composite-types
given trackingPickler: CompositePickler[Tracking] = compositePickler[Tracking]
Copy link
Contributor

Choose a reason for hiding this comment

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

looks odd, don't you get an unused pure expression warning something?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

WDYM?

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess the next line adding the concrete types to trackigPickler

trackingPickler
.addConcreteType[SiderealTracking]
.addConcreteType[ConstantTracking]
.addConcreteType[EphemerisTracking]
.addConcreteType[CompositeTracking]

object CatalogPicklers extends CatalogPicklers
13 changes: 13 additions & 0 deletions explore/model/shared/src/main/scala/explore/model/extensions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

package explore.model

import cats.MonadThrow
import cats.data.NonEmptyList
import cats.syntax.all.*
import cats.syntax.all.given
Expand All @@ -25,6 +26,7 @@ import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneOffset
import scala.annotation.targetName
import org.typelevel.log4cats.Logger

object extensions:
// TODO Move this to lucuma-schemas (and remove this logic from TargetWithId)
Expand Down Expand Up @@ -124,3 +126,14 @@ object extensions:
case ConstantTracking(coordinates) => coordinates
case CompositeTracking(nel) => Coordinates.centerOf(nel.map(_.baseCoordinates))
case _ => sys.error("Non sidereals are not supported")

extension [F[_]: {MonadThrow, Logger}, A](f: F[A])
def logErrors(msg: String = ""): F[A] =
f.onError:
case e => Logger[F].error(e)(msg)

extension [F[_]: {MonadThrow, Logger}, A](s: fs2.Stream[F, A])
def onErrorLog(msg: String = ""): fs2.Stream[F, A] =
s.handleErrorWith { e =>
fs2.Stream.eval(Logger[F].error(e)(msg)) >> fs2.Stream.raiseError[F](e)
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,34 @@ class VerifiedEpicsSpec extends CatsEffectSuite {
/* This test works by creating the client channels before starting the test EPICS server. That way we are sure the
* channels are disconnected by the time we try to use them, proving that verifiedRun works.
*/
epicsService.test("Makes sure channels are connected before reading and writing") { service =>
val testVal: Int = 1
(for {
tt <- service.getChannel[Int]("test:stringVal").map(c => TelltaleChannel("foo", c))
ch1 <- service.getChannel[Double]("test:doubleVal")
ch2 <- service.getChannel[Int]("test:intVal")
} yield (tt, ch1, ch2))
.use { case (tt, ch1, ch2) =>
val q = for {
_ <- VerifiedEpics.writeChannel(tt, ch1)(IO.pure(testVal.toDouble))
fa <- VerifiedEpics.readChannel(tt, ch1).map(_.map(_ + 1))
_ <- VerifiedEpics.writeChannel(tt, ch2)(fa.map(_.toInt))
fr <- VerifiedEpics.readChannel[IO, Int](tt, ch2)
} yield fr
epicsService.test("Makes sure channels are connected before reading and writing".flaky) {
service =>
val testVal: Int = 1
(for {
tt <- service.getChannel[Int]("test:stringVal").map(c => TelltaleChannel("foo", c))
ch1 <- service.getChannel[Double]("test:doubleVal")
ch2 <- service.getChannel[Int]("test:intVal")
} yield (tt, ch1, ch2))
.use { case (tt, ch1, ch2) =>
val q = for {
_ <- VerifiedEpics.writeChannel(tt, ch1)(IO.pure(testVal.toDouble))
fa <- VerifiedEpics.readChannel(tt, ch1).map(_.map(_ + 1))
_ <- VerifiedEpics.writeChannel(tt, ch2)(fa.map(_.toInt))
fr <- VerifiedEpics.readChannel[IO, Int](tt, ch2)
} yield fr

for {
tts1 <- tt.channel.getConnectionState
ch1s1 <- ch1.getConnectionState
r <- TestEpicsServer.init("test:").use { _ =>
q.verifiedRun(FiniteDuration(1, TimeUnit.SECONDS))
}
} yield {
assertEquals(tts1, ConnectionState.NEVER_CONNECTED)
assertEquals(ch1s1, ConnectionState.NEVER_CONNECTED)
assertEquals(r, testVal + 1)
for {
tts1 <- tt.channel.getConnectionState
ch1s1 <- ch1.getConnectionState
r <- TestEpicsServer.init("test:").use { _ =>
q.verifiedRun(FiniteDuration(1, TimeUnit.SECONDS))
}
} yield {
assertEquals(tts1, ConnectionState.NEVER_CONNECTED)
assertEquals(ch1s1, ConnectionState.NEVER_CONNECTED)
assertEquals(r, testVal + 1)
}
}
}
}

epicsService.test("Makes sure channels are connected before reading a stream".flaky) { service =>
Expand Down
2 changes: 1 addition & 1 deletion project/Versions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ object Versions {
val log4s = "1.10.0"
val logback = "1.5.20"
val lucumaBC = "0.4.0"
val lucumaCore = "0.149.0"
val lucumaCore = "0.151.0"
val lucumaPrimeStyles = "0.5.0"
val lucumaReact = "0.85.3"
val lucumaServers = "0.51.1"
Expand Down