mirror of
https://github.com/hanzoai/tasks.git
synced 2026-10-30 14:56:19 +00:00
## What changed? Makes changes summarized in https://github.com/temporalio/temporal/assets/52205/0660a021-588a-4573-94d3-301cae0c0040 ### Empty responses on server-timeout The behavior of `PollWorkflowExecutionUpdate` and `UpdateWorkflowExecution` was changed as follows: - They introduce a "server-imposed deadline" equal to current time plus `LongPollExpirationInterval` - If a timeout occurs due to the server-imposed deadline, then they do not return an error, but return a response with an empty outcome. - Otherwise, their behavior is unchanged (in particular, if a timeout occurs due context deadline expiry, they return the error as before) ### Non-blocking poll - Change the Update Poll endpoint so that omitting the `WaitPolicy` now means "do not wait; respond with current Update status without blocking". Previously omitting the `WaitPolicy` was interpreted to mean "attempt to wait until Completed" - Also return the `UpdateRef` ## Why? ### Empty responses on server-timeout - This makes the behavior of the endoint consistent with `GetWorkflowExecutionHistory`. - This makes sense, because that endpoint is used in an analogous way (e.g. `GetWorkflowExecutionHistory` is used for `wfHandle.result()` and `PollWorkflowExecutionUpdateRequest` is used for `updateHandle.result()`, and both involve polling for the result). - In particular, a polling client interprets timeout-on-server-imposed-deadline to mean that it should continue polling, and we would prefer not to use an error to communicate this non-exceptional situation. ### Non-blocking poll SDK clients may use non-blocking poll to, for example - Obtain current status of an Update (perhaps `updateHandle.describe()` - Determine whether an Update with a given ID already exists / is running ### How did you test it? - Unit tests - Modified Typescript SDK to not send `WaitPolicy`, ran a feature test against the modified server and modified SDK, and confirmed API communication as expected (this revealed that I needed to stop Frontend mutating the request to set `WaitPolicy` to `Completed`). - I changed the poll loop in sdk-typescript to no longer catch `DeadlineExceeded`, ran the `update/basic_async` feature test against the local SDK and against server binaries built prior to and with this commit, and confirmed that the change in this PR fixed the poll loop. ### Potential risks - Could break Update operations in SDKs ### Is hotfix candidate? - No
96 lines
3.2 KiB
Go
96 lines
3.2 KiB
Go
// The MIT License
|
|
//
|
|
// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved.
|
|
//
|
|
// Copyright (c) 2020 Uber Technologies, Inc.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
// THE SOFTWARE.
|
|
|
|
package update
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
enumspb "go.temporal.io/api/enums/v1"
|
|
)
|
|
|
|
type (
|
|
state uint32
|
|
stateSet uint32
|
|
)
|
|
|
|
const (
|
|
stateAdmitted state = 1 << iota
|
|
stateProvisionallyRequested
|
|
stateRequested
|
|
stateProvisionallyAccepted
|
|
stateAccepted
|
|
stateProvisionallyCompleted
|
|
stateCompleted
|
|
)
|
|
|
|
func (s state) String() string {
|
|
switch s {
|
|
case stateAdmitted:
|
|
return "Admitted"
|
|
case stateProvisionallyRequested:
|
|
return "ProvisionallyRequested"
|
|
case stateRequested:
|
|
return "Requested"
|
|
case stateProvisionallyAccepted:
|
|
return "ProvisionallyAccepted"
|
|
case stateAccepted:
|
|
return "Accepted"
|
|
case stateProvisionallyCompleted:
|
|
return "ProvisionallyCompleted"
|
|
case stateCompleted:
|
|
return "Completed"
|
|
}
|
|
return "unrecognized state"
|
|
}
|
|
|
|
// LifecycleStage maps the states of the Update state machine to the values of
|
|
// enumspb.UpdateWorkflowExecutionLifecycleStage.
|
|
func (s state) LifecycleStage() (enumspb.UpdateWorkflowExecutionLifecycleStage, error) {
|
|
switch s {
|
|
case stateAdmitted:
|
|
return enumspb.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ADMITTED, nil
|
|
case stateProvisionallyRequested:
|
|
return enumspb.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ADMITTED, nil
|
|
case stateRequested:
|
|
return enumspb.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ADMITTED, nil
|
|
case stateProvisionallyAccepted:
|
|
return enumspb.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ADMITTED, nil
|
|
case stateAccepted:
|
|
return enumspb.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED, nil
|
|
case stateProvisionallyCompleted:
|
|
// Transition could be due to either validation rejection or completion
|
|
// of Update, so Admitted is the most advanced stage known to have been
|
|
// reached.
|
|
return enumspb.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ADMITTED, nil
|
|
case stateCompleted:
|
|
return enumspb.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_COMPLETED, nil
|
|
}
|
|
return enumspb.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_UNSPECIFIED, fmt.Errorf("unrecognized state: %v", s) // nolint:goerr113
|
|
}
|
|
|
|
func (s state) Matches(mask stateSet) bool {
|
|
return uint32(s)&uint32(mask) == uint32(s)
|
|
}
|