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

Update sequence on ExecutionEventAdded events #4547

Merged
merged 12 commits into from
Feb 12, 2025

Conversation

toddburnside
Copy link
Contributor

At first I tried getting the visit information with the subscription event and merging it in with the other visits. But, we ARE getting a lot of observationEdit events while the observation is executing, so it made more sense to just include it in with the other signals because those are debounced. There are also a LOT of executionEventAdded events, so the debouncing is good.

This seems to work well, with one caveat. While an observation is executing (for at least one of my observations), an extra set of acquisition steps appears in the sequence, as though we have moved on to a new visit. After a couple more science steps complete, those acquisition steps disappear and everything finishes up normally. I have not determined if those are actually in the sequence we get from the ODB, or if it is some sort of local aberration. They do not appear in the observe UI.

Looking at the first commit it is easier to see the actual changes, since in the second commit I refactored to the monadic hook style.

@toddburnside toddburnside requested a review from rpiaggio February 7, 2025 00:41
@mergify mergify bot added the explore label Feb 7, 2025
.raiseGraphQLErrors
.map(_.observation.flatMap(_.execution))
.attemptPot
.reRunOnResourceSignals:
Copy link
Contributor Author

@toddburnside toddburnside Feb 7, 2025

Choose a reason for hiding this comment

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

I switched from resetOnResourceSignals to reRunOnResourceSignals so that the Pot doesn't go to Pending between the signal and the query results. This was causing the table to reload for each step, which wasn't very nice when getting updates from the observation execution.

Copy link

bundlemon bot commented Feb 7, 2025

BundleMon

Files updated (2)
Status Path Size Limits
index-(hash).js
1.74MB (+3.68KB +0.21%) -
exploreworkers-(hash).js
597.86KB (+362B +0.06%) -
Unchanged files (6)
Status Path Size Limits
index-(hash).css
66.23KB -
workbox-window.prod.es5-(hash).js
2.07KB -
agsworker-(hash).js
83B -
plotworker-(hash).js
83B -
catalogworker-(hash).js
81B -
itcworker-(hash).js
81B -

Total files change +4.03KB +0.16%

Final result: ✅

View report in BundleMon website ➡️


Current branch size history | Target branch size history

Comment on lines 116 to 119
for {
o <- obsEditSubscription(obsId)
e <- executionEventAddedSubscription(obsId)
} yield o.merge(e)
Copy link
Contributor

Choose a reason for hiding this comment

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

.mapN ?

@rpiaggio
Copy link
Contributor

rpiaggio commented Feb 7, 2025

Do we still need the observationEdits now that we have the executionEventAddeds ?

Also, can we filter executionEventAdded to the relevant ones? For example: We don't need to update anything when a step is STARTED.

@rpiaggio
Copy link
Contributor

rpiaggio commented Feb 7, 2025

This seems to work well, with one caveat. While an observation is executing (for at least one of my observations), an extra set of acquisition steps appears in the sequence, as though we have moved on to a new visit. After a couple more science steps complete, those acquisition steps disappear and everything finishes up normally. I have not determined if those are actually in the sequence we get from the ODB, or if it is some sort of local aberration. They do not appear in the observe UI.

Showing acquisition steps is a bit tricky, since there's always a next atom. We have to detect whether it's relevant to show it or not. IIRC, there's logic in observe to do that. There might also be logic here and it may be outdated. Anyway, we can fix that in a following PR.

@toddburnside
Copy link
Contributor Author

Do we still need the observationEdits now that we have the executionEventAddeds ?

We still need to update when the observation changes and we aren't executing. As I mentioned above, we do seem to get a lot of observationEdit events during the execution as well. It still isn't clear to me what gaps the executionEventAdded events fill. Unfortunately, my knowledge of how the sequences and execution work is very limited.

@toddburnside
Copy link
Contributor Author

Also, can we filter executionEventAdded to the relevant ones? For example: We don't need to update anything when a step is STARTED.

That's a good idea. It might help with the overlap of observationEdit and executionEventAdded events as well. There is a flood of executionEventAdded events! The events we can filter on are: SEQUENCE, SLEW, ATOM, STEP & DATASET. Would just listening to STEP be sufficient? Or could we filter for SEQUENCE for the sequence query and STEP for the Visits query? Do we need DATASET for updating the dataset name?

@rpiaggio
Copy link
Contributor

rpiaggio commented Feb 7, 2025

That's a good idea. It might help with the overlap of observationEdit and executionEventAdded events as well. There is a flood of executionEventAdded events! The events we can filter on are: SEQUENCE, SLEW, ATOM, STEP & DATASET. Would just listening to STEP be sufficient? Or could we filter for SEQUENCE for the sequence query and STEP for the Visits query? Do we need DATASET for updating the dataset name?

I think that we will be OK just listening to STEP events. When a step ends, the dataset names are already set, so we will get them in the query. Actually, we only need to requery (visits and sequence) when a step ends. We can't filter by StepStage in the subscription but we can do that in the client.

We might want to react to Step start if we want to show which step is currently executing, but I'm not sure that's a requirement.

Copy link
Contributor Author

@toddburnside toddburnside left a comment

Choose a reason for hiding this comment

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

LGTM after the scalafix and you actually testing it. 😆 But, since I opened the PR, I can't officially approve it.

ctx <- useContext(AppContext.ctx)
given StreamingClient[IO, ObservationDB] = ctx.clients.odb
obsEditSignal <-
useResourceOnMount: // Subscribe to observation edits
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice.

val document = s"""
subscription($$input: ExecutionEventAddedInput!) {
executionEventAdded(input: $$input) {
subscription($$obsId: ObservationId!) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

FWIW, a while back I switched to always creating the Input objects in scala because of better type checking. We had an instance of the schema changing and explore compiling just fine, but breaking in dev. Maybe with the schema becoming more stable that will be less of a problem. Also, I guess this particular input probably won't change much.

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, we should be able to check the input against the schema in clue, like we do with the query: gemini-hlsw/clue#665

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That would be great!

@rpiaggio
Copy link
Contributor

rpiaggio commented Feb 8, 2025

LGTM after the scalafix and you actually testing it. 😆 But, since I opened the PR, I can't officially approve it.

Thank you! I'm still working on the PR.

Turns out that executing a stream twice is not a good idea, at least when they are queue-backed, like the ones that clue returns. By executing the stream twice, each element ends up only in one of them, since they steal it from the queue.

I implemented a way to create streams that replicate an input stream, via topics.

Also, there are new handy methods in crystal that I'm using, but the crystal PR is not ready yet.

@rpiaggio rpiaggio force-pushed the sc-4317-show-steps-executed-after-events-are-emitted branch from 691f7a5 to d2c4e56 Compare February 11, 2025 12:26
@rpiaggio
Copy link
Contributor

I ended up inverting the logic. Instead of building update streams for the visits and the sequence, I switched to manually updating them. The useEffectResult hook has been modified in crystal, so that it now provides a method for said manual update.

Also, the logic to keep the sequence updated has been moved to a custom hook.

@rpiaggio
Copy link
Contributor

I'll merge this for the moment.

We are at a point where the sequence is updating on every obs and target edit, and both the sequence and visits are updating whenever a step completes.

There are still some glitches regarding the acquisition sequence. Some of these are present in observe too. I'll address those in a separate PR.

Also, we are getting a ton of events whenever a step completes. I'll monitor this a bit more and sync up with Shane.

@toddburnside
Copy link
Contributor Author

Also, we are getting a ton of events whenever a step completes. I'll monitor this a bit more and sync up with Shane.

One thing we are missing here (unless I failed to see it) is a debounce for the updates. With the old methods the "signal" streams had a 2 second (by default) debounce.

We could debounce each of the subscription streams here and that would help a lot, but that still means that if we get both an observation edit and an event added event we will query twice. And we seem to get both events quite frequently.

The first thing I can think of seems complicated, but you'll probably come up with something simpler. The obs edit and event added streams could update a queue and that could be debounced and used to update the sequence and visit. I don't think the target edit events are as important to sync up because, AFAIK, they only come about from editing the targets.

@rpiaggio
Copy link
Contributor

Good catch.

I'll look into that before merging then.

I'm thinking maybe we can merge the three signals into a Boolean stream which indicates whether the visits must me updated (the sequence always is).

@mergify mergify bot added the common label Feb 11, 2025
@rpiaggio
Copy link
Contributor

This might need further work, but I think a got a version working where update signals are throttled. I ended up using Arman's Deglitcher.

Since we had utils a bit scattered, there's also a refactor that brings all utils extensions into one file.

@rpiaggio
Copy link
Contributor

BTW, I didn't use debounce since it waits for the debounce time before the first invocation. The new throttle works the other way round: it lets the first element pass and then discards everything but the last element received during the debounce time.


import cats.effect.Temporal
extension [F[_]: Temporal, A](stream: fs2.Stream[F, A])
def throttle(duration: FiniteDuration): fs2.Stream[F, A] =
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Isn't this extension in extensions.scala, too?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yup, forgot to remove it when I moved it there.

Anyway, I'm deleting from both places since we are not using it after all.

@rpiaggio rpiaggio force-pushed the sc-4317-show-steps-executed-after-events-are-emitted branch from 2dc14fc to c0a96ca Compare February 12, 2025 20:36
@rpiaggio rpiaggio merged commit 9fa5afb into main Feb 12, 2025
14 checks passed
@rpiaggio rpiaggio deleted the sc-4317-show-steps-executed-after-events-are-emitted branch February 12, 2025 22:33
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.

2 participants