-
Notifications
You must be signed in to change notification settings - Fork 1.1k
[Scheduled Actions] CHASM scheduled actions visibility support #8292
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
base: chasm_cleanup_addedtasks
Are you sure you want to change the base?
Conversation
customSearchAttributes *commonpb.SearchAttributes, | ||
) error { | ||
needsTask := false // Set to true if we need to write anything to Visibility. | ||
visibility, err := s.Visibility.Get(ctx) |
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.
Not related to this PR but are we ever expecting an error getting a component to be an error that the application needs to handle? What reasons would be for this failure? Can we just make the method panic instead?
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.
When we support partial read in the future, there could be some transient error returned here. For now, it will only be serialization errors.
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.
If it's a transient, unexpected error, it should be okay to panic IMHO. That would be better than complicating the user interface. There's never really a way for a developer to react to this situation.
if customSearchAttributes != nil && | ||
len(customSearchAttributes.GetIndexedFields()) > 0 { |
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.
nit: This is enough because proto getters work with nils.
if customSearchAttributes != nil && | |
len(customSearchAttributes.GetIndexedFields()) > 0 { | |
if len(customSearchAttributes.GetIndexedFields()) > 0 { |
} | ||
|
||
// Update Paused status. | ||
var currentPaused bool |
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.
This is exactly why I didn't want components to use imperative logic to update their search attributes. This logic should be part of the framework.
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.
If we can afford it timeline-wise I'd much prefer if we coded up a better abstraction in the framework.
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.
In general I agree. Also acknowledging that imperative logic means component author needs to remember update those attributes.
We discussed about the field tag approach which addresses this concern and also the SA registration problem but decided to do that as a follow up to unblock the Scheduler migration and deliver value sooner. It's more of a ROI & priority discussion for the entire OSS team.
|
||
// Update visibility if the memo is out-of-date or absent. | ||
if currentInfoPayload == nil || | ||
!bytes.Equal(currentInfoPayload.Data, newInfoPayload) { |
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.
Proto marshal is not deterministic by default, this comparison will give you false negatives. You will want to unmarshal and use proto.Equal
instead.
Another reason why component authors shouldn't implement all of this logic.
// attributes will be left as-is with it unset. | ||
// | ||
// See mergeCustomSearchAttributes for how custom search attributes are merged. | ||
func (s *Scheduler) UpdateVisibility( |
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 don't like this approach, it assumes that the component author will remember to update visibility anytime that an attribute changes. This should be the framework's responsibility and should be done automatically when a transaction is closed.
for key, newPayload := range customAttrs { | ||
oldPayload, alreadySet := currentAttrs[key] | ||
|
||
if !alreadySet || !bytes.Equal(oldPayload.Data, newPayload.Data) { |
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.
As mentioned before, you cannot rely on byte equality for this comparison.
if needsTask { | ||
visibility.GenerateTask(ctx) | ||
} |
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.
This is unnecessary, Visibility component automatically generates a task when it's updated.
customSearchAttributes *commonpb.SearchAttributes, | ||
) error { | ||
needsTask := false // Set to true if we need to write anything to Visibility. | ||
visibility, err := s.Visibility.Get(ctx) |
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.
When we support partial read in the future, there could be some transient error returned here. For now, it will only be serialization errors.
if !ok || currentPaused != s.Schedule.State.Paused { | ||
upsertAttrs[searchattribute.TemporalSchedulePaused] = s.Schedule.State.Paused | ||
} |
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.
This is more like a "refresh visibility" approach. Do we have a like PauseSchedule method where we can update the field?
currentMemo, err := visibility.GetMemo(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
currentInfoPayload := currentMemo[visibilityMemoFieldInfo] |
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.
nit: can use the generic chasm.GetMemo() function which returns a strongly typed value instead of Payload
newMemo := map[string]any{visibilityMemoFieldInfo: newInfoPayload} | ||
err = visibility.UpsertMemo(ctx, newMemo) |
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.
UpsertMemo will perform the encoding to Payload type, should just use newInfo
here.
currentPausedPayload, ok := currentAttrs[searchattribute.TemporalSchedulePaused] | ||
if ok { | ||
err = payload.Decode(currentPausedPayload, ¤tPaused) | ||
if err != nil { | ||
return err | ||
} | ||
} |
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.
nit: can use the generic chasm.GetSearchAttribute() method here as well and you don't need to do the decoding.
// Key isn't in the new map, delete it. | ||
upsertAttrs[key] = nil |
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.
Will this work? At least when I was coding the visibility.UpsertSearchAttributes() method I wasn't thinking of using that as a way for deletion.
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.
This is how it worked in the SDKs before we had typed search attributes.
} | ||
|
||
// Update Paused status. | ||
var currentPaused bool |
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.
In general I agree. Also acknowledging that imperative logic means component author needs to remember update those attributes.
We discussed about the field tag approach which addresses this concern and also the SA registration problem but decided to do that as a follow up to unblock the Scheduler migration and deliver value sooner. It's more of a ROI & priority discussion for the entire OSS team.
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.
Based on @yycptt's comments the abstraction isn't too bad today.
Seems like you don't need to manually generate a task, serialize and deserialize payloads, etc...
If we could also eliminate the need to compare search attributes and do incremental updates only to fields that changed, that would be good enough for me for merging this PR and deferring the declarative APIs for later.
Ideally we wouldn't even need to do that, if you could just recompute the desired visibility state and have the visibility component understand what needs to be updated (if anything at all) that would be much much better than what we have today.
Is that doable?
customSearchAttributes *commonpb.SearchAttributes, | ||
) error { | ||
needsTask := false // Set to true if we need to write anything to Visibility. | ||
visibility, err := s.Visibility.Get(ctx) |
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.
If it's a transient, unexpected error, it should be okay to panic IMHO. That would be better than complicating the user interface. There's never really a way for a developer to react to this situation.
// Key isn't in the new map, delete it. | ||
upsertAttrs[key] = nil |
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.
This is how it worked in the SDKs before we had typed search attributes.
What changed?
How did you test it?