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

CLI Refresh: workflow signal command #432

Merged
merged 10 commits into from
Feb 1, 2024
Merged

Conversation

cretz
Copy link
Member

@cretz cretz commented Jan 30, 2024

What was changed

Add support for workflow signal command. The functionality is mostly unchanged from current CLI, but the output may be different.

Improvements over current CLI:

  • JSON output support (empty for single-workflow, contains batch job ID for batch)
  • Use non-success exit code if prompt confirmation fails on batch
  • Clarify batch count is approximate (due to race between count request and actual batch)
  • --reason not required for batch (same default format as UI)

…write-workflow-signal

# Conflicts:
#	go.mod
#	go.sum
#	temporalcli/commands.gen.go
#	temporalcli/commands.workflow.go
#	temporalcli/commands.workflow_exec.go
#	temporalcli/commandsmd/commands.md
@cretz cretz requested a review from a team January 30, 2024 22:43
@cretz cretz force-pushed the cli-rewrite-workflow-signal branch from 0819721 to c27034f Compare January 30, 2024 22:45
Comment on lines 59 to 63
lastFoundPieceIndex := -1
for _, piece := range pieces {
if !strings.Contains(line, piece) {
if index := strings.Index(line, piece); index > lastFoundPieceIndex {
lastFoundPieceIndex = index
} else {
Copy link
Member Author

Choose a reason for hiding this comment

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

@dandavison - here is update for forcing order

Copy link
Contributor

Choose a reason for hiding this comment

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

Great, thanks for adding that! This looks like it will allow the pieces to match in an overlapping way -- I think we need to set lastFoundPieceIndex to the index of the end of piece.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think it's ok to be overlapping, it's still in order by start of piece

Copy link
Contributor

@dandavison dandavison Jan 30, 2024

Choose a reason for hiding this comment

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

No, it's clear to me that when users make a call like s.ContainsOnSameLine(out, "Namespace", "default") they mean

there exists a line which contains 'Namespace' and 'default', in that order (not overlapping).

I've never seen a test framework that allows them to be overlapping or out of order. I do think that your s.ContainsOnSameLine(out, "Namespace", "default") call is nice and readable -- nicer to read than a regexp assertion for this common case.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated

Comment on lines +139 to +147
// Default the reason if not set
reason := s.Reason
if reason == "" {
username := "<unknown-user>"
if u, err := user.Current(); err != nil && u.Username != "" {
username = u.Username
}
reason = "Requested from CLI by " + username
}
Copy link
Member Author

@cretz cretz Jan 30, 2024

Choose a reason for hiding this comment

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

Current CLI requires reason to be set by user. UI defaults to something like Terminated from Web UI by foo@bar.com, so we follow a similar format, but we just do "Requested" instead of specific verb (batch job carries its own timestamp info).

if !strings.Contains(line, piece) {
if index := strings.Index(line, piece); index > lastEndIndex {
lastEndIndex = index + len(piece)
} else {
Copy link
Contributor

@dandavison dandavison Jan 31, 2024

Choose a reason for hiding this comment

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

Ha, algorithms like this are hard to get right first time without unit tests! I suggest we use a regular-expression based implementation, i.e. form a regex by joining pieces with whatever separator gives the separator semantics that we think callers will want in the common case. That way the behavior of the utility is clear to anyone who looks at the code, and they can use their own regex assertion if they want different behavior. I'd also be OK with deleting this utility and requiring callers to use a regex explicitly.

As it is it still has bugs. The most serious I'm seeing is that ContainsOnSameLine("a b a", "b", "a") will fail, when it should pass.

But also ContainsOnSameLine("ab", "a", "b") will fail (no gap between them) and yet ContainsOnSameLine("axb", "a", "b") will pass.

And related to the first bug, ContainsOnSameLine("a a", "a", "a") will fail.

Copy link
Member Author

@cretz cretz Jan 31, 2024

Choose a reason for hiding this comment

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

This is why I wanted it simple and ask users to use regex if they needed more instead of increase the rules of this little helper. I regret not sticking to the original simple/looser requirements. At this point I think we should just document the limits and tell people to use regex if they want.

Copy link
Contributor

Choose a reason for hiding this comment

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

The original version allowed the pieces to be in any order and overlapping, which isn't appropriate for a test harness assertion utility.

What do you see as the downside of implementing ContainsOnSameLine as a regex search for pieces joined by something like .* or .+ or .*\s.*? However it's implemented, the resulting function will have some behavior, which we need to make clear to callers. A regex is the best way to make that clear to callers as I see it.

Or, as I mentioned above, we could just delete the utility and let callers decide on their regex.

Copy link
Member Author

Choose a reason for hiding this comment

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

What do you see as the downside of implementing ContainsOnSameLine as a regex search for pieces joined by something like .* or .+ or .\s.?

The continual requirements. "Can you strip colors too?", "Can you make it case insensitive?", "Can you make it only allow whole words instead of partial match?", "Can you allow this to work on adjacent lines instead of just one?", etc etc. "But it isn't appropriate for an stdout test harness utility to not strip out ANSI codes", "But it isn't appropriate for this test harness utility to not check whole words", etc. Each has their own opinion and it was just meant to be a little code reuse thing, but I didn't want to name it ContainsAnywhereOnSameLineInAnyOrderMayOverlap.

Or, as I mentioned above, we could just delete the utility and let callers decide on their regex.

This may be best, but I still want some code reuse and I accept the limitations of the little helper.

Copy link
Contributor

@dandavison dandavison Feb 1, 2024

Choose a reason for hiding this comment

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

The continual requirements. "Can you strip colors too?", "Can you make it case insensitive?", "Can you make it only allow whole words instead of partial match?", "Can you allow this to work on adjacent lines instead of just one?", etc etc. "But it isn't appropriate for an stdout test harness utility to not strip out ANSI codes", "But it isn't appropriate for this test harness utility to not check whole words", etc.

My suggestions that a string matching function should enforce order of the query terms and not allow overlapping matches are perfectly reasonable and uncontroversial. I'm not proposing them as optional extra enhancements; I'm saying that these are basic requirements of a utility that searches for a line containing certain substrings.

In any case, it's not appropriate to attempt to ridicule reviewer suggestions like that. If you think that the suggestions are reasonable but not how you want the function to behave, then that’s of course fine – in that case please just ask the other team members for their opinion.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated to support regex-based match

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks, that looks great to me.

Copy link
Member

@bergundy bergundy left a comment

Choose a reason for hiding this comment

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

LGTM.

Not much to add.

Only thing I'm unsure of is if we want to print the success on non-json output via the logger to stderr.
Seems like the rest of the output for this command goes to stdout and if I want to grep for the job ID (yes some prefer that over jq), I have to pipe stderr which is a bit awkward and non-standard.

Copy link
Contributor

@dandavison dandavison left a comment

Choose a reason for hiding this comment

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

As discussed, there are bugs in the test helper function that need fixing.

@cretz
Copy link
Member Author

cretz commented Feb 1, 2024

Only thing I'm unsure of is if we want to print the success on non-json output via the logger to stderr.

I will update the started-batch statement to be a stdout line instead of a log line

EDIT: Updated

@cretz cretz merged commit 7ca8679 into cli-rewrite Feb 1, 2024
5 checks passed
@cretz cretz deleted the cli-rewrite-workflow-signal branch February 1, 2024 21:47
tdeebswihart added a commit that referenced this pull request Feb 7, 2024
# What was changed

I implemented `temporal workflow terminate`, which should behave the
same as in the existing CLI except for the same caveats/improvements as
in #432.
return err
}

exec, batchReq, err := c.workflowExecOrBatch(cctx, c.Parent.Namespace, cl)
Copy link
Contributor

Choose a reason for hiding this comment

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

Did this just happen to be the first command implemented for which batch was an option?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes

if err := startBatchJob(cctx, cl, batchReq); err != nil {
return err
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe that the contract of workflowExecOrBatch is such that one or other of the above conditions must be true, so I'd like the code not to appear to allow neither to be executed.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this is leftover from previous code where it could return all nils when you declined the prompt, but I decided to change that to be an error and did not change this.

@@ -41,3 +95,77 @@ func (*TemporalWorkflowTraceCommand) run(*CommandContext, []string) error {
func (*TemporalWorkflowUpdateCommand) run(*CommandContext, []string) error {
return fmt.Errorf("TODO")
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Although it's a private function, it would be good to document this something like

This function guarantees that exactly one of the 3 returned values will be non-nil.

Copy link
Member Author

Choose a reason for hiding this comment

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

Concur

Copy link
Contributor

Choose a reason for hiding this comment

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

OK great, I can make these minor changes.

tdeebswihart added a commit that referenced this pull request Feb 12, 2024
# What was changed

I implemented `temporal workflow cancel`, which should behave the same
as in the existing CLI except for the same caveats/improvements as in
#432
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants