Skip to content

Commit

Permalink
use same observationsByWorkflowState query as navigate
Browse files Browse the repository at this point in the history
  • Loading branch information
rpiaggio committed Feb 13, 2025
1 parent 252f8ee commit 9a48cb3
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 71 deletions.
46 changes: 46 additions & 0 deletions modules/model/shared/src/main/scala/observe/model/extensions.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) 2016-2023 Association of Universities for Research in Astronomy, Inc. (AURA)
// For license information see LICENSE or https://opensource.org/licenses/BSD-3-Clause

package observe.model

import cats.syntax.option.*
import lucuma.core.enums.Instrument
import lucuma.core.enums.Site

object extensions:
extension (i: Instrument)
def hasOI: Boolean = i match
// case Instrument.F2 => true
case Instrument.GmosSouth => true
case Instrument.GmosNorth => true
case _ => false
// case Instrument.Nifs => true
// case Instrument.Niri => true
// case Instrument.Gnirs => true
// case Instrument.Gsaoi => false
// case Instrument.Gpi => true
// case Instrument.Ghost => false

def site: Option[Site] = i match
// GS
case Instrument.GmosSouth => Site.GS.some
case Instrument.Flamingos2 => Site.GS.some
case Instrument.Ghost => Site.GS.some
case Instrument.Gpi => Site.GS.some
case Instrument.Gsaoi => Site.GS.some
// GN
case Instrument.GmosNorth => Site.GN.some
case Instrument.Gnirs => Site.GN.some
case Instrument.Niri => Site.GN.some
case Instrument.Nifs => Site.GN.some
// None
case _ => none

private val SiteInstruments: Map[Site, List[Instrument]] =
Instrument.all
.filter(_.site.isDefined)
.groupBy(_.site.get)

extension (site: Site)
def instruments: List[Instrument] =
SiteInstruments(site)
30 changes: 0 additions & 30 deletions modules/model/shared/src/main/scala/observe/model/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@

package observe.model

import cats.*
import cats.syntax.all.*
import io.circe.KeyDecoder
import io.circe.KeyEncoder
import lucuma.core.enums.Instrument
import lucuma.core.enums.Site
import lucuma.core.util.Enumerated
import observe.model.enums.Resource

Expand All @@ -23,34 +21,6 @@ val CalibrationQueueName: String = "Calibration Queue"
val CalibrationQueueId: QueueId =
QueueId(UUID.fromString("7156fa7e-48a6-49d1-a267-dbf3bbaa7577"))

extension (i: Instrument)
def hasOI: Boolean = i match
// case Instrument.F2 => true
case Instrument.GmosSouth => true
case Instrument.GmosNorth => true
case _ => false
// case Instrument.Nifs => true
// case Instrument.Niri => true
// case Instrument.Gnirs => true
// case Instrument.Gsaoi => false
// case Instrument.Gpi => true
// case Instrument.Ghost => false

def site: Option[Site] = i match
// GS
case Instrument.GmosSouth => Site.GS.some
case Instrument.Flamingos2 => Site.GS.some
case Instrument.Ghost => Site.GS.some
case Instrument.Gpi => Site.GS.some
case Instrument.Gsaoi => Site.GS.some
// GN
case Instrument.GmosNorth => Site.GN.some
case Instrument.Gnirs => Site.GN.some
case Instrument.Niri => Site.GN.some
case Instrument.Nifs => Site.GN.some
// None
case _ => none

given KeyEncoder[Resource | Instrument] = KeyEncoder.instance:
case r: Resource => r.tag
case i: Instrument => i.tag
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import observe.model.*
import observe.model.Observation
import observe.model.dhs.*
import observe.model.enums.Resource
import observe.model.extensions.*
import observe.server.InstrumentSystem.*
import observe.server.ObserveFailure.Unexpected
import observe.server.SequenceGen.StepActionsGen
Expand Down Expand Up @@ -491,8 +492,8 @@ object SeqTranslate {
NonEmptySet.of(AGUnit, (if (inst.hasOI) List(OIWFS) else List.empty)*)

private def extractWavelength(s: DynamicConfig): Option[Wavelength] = s match {
case a:DynamicConfig.GmosNorth => a.centralWavelength
case b:DynamicConfig.GmosSouth => b.centralWavelength
case a: DynamicConfig.GmosNorth => a.centralWavelength
case b: DynamicConfig.GmosSouth => b.centralWavelength
}

private def getTcs[S <: StaticConfig, D <: DynamicConfig](
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,18 @@ import clue.annotation.GraphQL
import lucuma.schemas.ObservationDB
import observe.ui.model.ObsSummary

// gql: import lucuma.schemas.decoders.given

object ObsQueriesGQL {

@GraphQL
trait ActiveObservationIdsQuery extends GraphQLOperation[ObservationDB] {
// TODO The ODB API doesn't provide a way to filter ready observations,
// so we filter by accepted proposals for now.
// Revise this when the API supports it OR we start getting obersvations from the scheduler.
val document = s"""
query {
observations(
WHERE: {
program: {
OR: [
{ proposalStatus: { EQ: ACCEPTED } }
{ type: { IN: [ENGINEERING, CALIBRATION] } }
]
}
}
) {
matches $ObservationSummarySubquery
}
query($$instruments: [Instrument!]!, $$semester: Semester!) {
observationsByWorkflowState(
states: [READY, ONGOING],
WHERE: { program: { reference: { instrument: { IN: $$instruments }, semester: { EQ: $$semester } } } }
) $ObservationSummarySubquery
}
"""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import clue.js.WebSocketJsBackend
import clue.js.WebSocketJsClient
import clue.websocket.ReconnectionStrategy
import crystal.Pot
import crystal.ViewF
import crystal.react.*
import crystal.react.given
import crystal.react.hooks.*
Expand All @@ -24,6 +25,7 @@ import japgolly.scalajs.react.*
import japgolly.scalajs.react.extra.router.*
import japgolly.scalajs.react.vdom.html_<^.*
import log4cats.loglevel.LogLevelLogger
import lucuma.core.model.Semester
import lucuma.core.model.StandardRole
import lucuma.core.model.StandardUser
import lucuma.react.common.*
Expand All @@ -42,12 +44,14 @@ import observe.model.*
import observe.model.LogMessage
import observe.model.enums.ObserveLogLevel
import observe.model.events.ClientEvent
import observe.model.extensions.*
import observe.queries.ObsQueriesGQL
import observe.ui.BroadcastEvent
import observe.ui.ObserveStyles
import observe.ui.components.services.ObservationSyncer
import observe.ui.components.services.ServerEventHandler
import observe.ui.model.AppContext
import observe.ui.model.ObsSummary
import observe.ui.model.RootModel
import observe.ui.model.RootModelData
import observe.ui.model.enums.*
Expand All @@ -70,9 +74,9 @@ import org.typelevel.log4cats.Logger
import retry.*
import typings.loglevel.mod.LogLevelDesc

import java.time.Instant
import java.util.concurrent.TimeUnit
import scala.concurrent.duration.*
import scala.scalajs.LinkingInfo

object MainApp extends ServerEventHandler:
private val ApiBasePath: Uri.Path = path"/api/observe/"
Expand Down Expand Up @@ -136,7 +140,7 @@ object MainApp extends ServerEventHandler:
.create

// Log in from cookie and switch to staff role
private def enforceStaffRole(ssoClient: SSOClient[IO]): IO[Option[UserVault]] =
private def enforceStaffRole(ssoClient: SSOClient[IO]): IO[UserVault] =
ssoClient.whoami
.flatMap: userVault =>
userVault.map(_.user) match
Expand All @@ -145,10 +149,9 @@ object MainApp extends ServerEventHandler:
.collectFirst { case StandardRole.Staff(roleId) => roleId }
.fold(IO.none)(ssoClient.switchRole)
.map:
_.orElse: // In dev mode, attempt switch to staff role, but allow anyway if it fails
if LinkingInfo.developmentMode then userVault
else throw new Exception("User is not staff")
case _ => IO.none
_.getOrElse(throw new Exception("User is not staff"))
case _ =>
IO.raiseError(new Exception("Unrecognized user"))

// Turn a Stream[WSFrame] into Stream[ClientEvent]
val parseClientEvents: Pipe[IO, WSFrame, Either[Throwable, ClientEvent]] =
Expand Down Expand Up @@ -229,7 +232,7 @@ object MainApp extends ServerEventHandler:
(_, _, _, _, _, _, rootModelData, _, _) =>
ctx => // Once AppContext is ready, proceed to attempt login (5)
enforceStaffRole(ctx.ssoClient).attempt.flatMap: userVault =>
rootModelData.async.mod(_.withLoginResult(userVault))
rootModelData.async.mod(_.withLoginResult(userVault.map(_.some)))
.useShadowRef: (_, _, _, _, _, _, rootModelData, _, _) =>
rootModelData.get.userVault.toOption.flatten.map(_.authorizationHeader)
.useAsyncEffectWhenDepsReadyBy((_, _, _, _, _, _, rootModelData, _, ctxPot, _) =>
Expand Down Expand Up @@ -305,24 +308,31 @@ object MainApp extends ServerEventHandler:

Option
.unless(subscribed.value) {
val readyObservations = rootModelData
.zoom(RootModelData.readyObservations)
.async
val readyObservations: ViewF[IO, Pot[List[ObsSummary]]] =
rootModelData
.zoom(RootModelData.readyObservations)
.async

Resource.pure(fs2.Stream.eval[IO, Unit](subscribed.setAsync(true))) >>
ObsQueriesGQL
.ActiveObservationIdsQuery[IO]
.query()
.raiseGraphQLErrors
.flatMap: data =>
readyObservations.set:
data.observations.matches
.filter(_.instrument.site.contains_(clientConfig.site))
.ready
.recoverWith(t => readyObservations.set(Pot.error(t)))
.void
.reRunOnResourceSignals:
ObsQueriesGQL.ObservationEditSubscription.subscribe[IO]()
Resource
.eval(IO.realTime)
.flatMap: now =>
val currentSemester: Semester =
Semester
.fromSiteAndInstant(clientConfig.site, Instant.ofEpochMilli(now.toMillis))
.get

ObsQueriesGQL // We filter by instruments as a proxy to filtering by site.
.ActiveObservationIdsQuery[IO]
.query(clientConfig.site.instruments, currentSemester)
.raiseGraphQLErrors
.flatMap: data =>
readyObservations.set:
data.observationsByWorkflowState.ready
.recoverWith(t => readyObservations.set(Pot.error(t)))
.void
.reRunOnResourceSignals:
ObsQueriesGQL.ObservationEditSubscription.subscribe[IO]()
}
.orEmpty
.useEffectResultOnMount(Semaphore[IO](1).map(_.permit))
Expand Down

0 comments on commit 9a48cb3

Please sign in to comment.