mirror of
https://github.com/temporalio/temporal.git
synced 2026-08-31 02:51:51 -07:00
## What changed? This branch implements the activity operator commands feature — a set of server-initiated control APIs (PauseActivityExecution, UnpauseActivityExecution, ResetActivityExecution, UpdateActivityExecutionOptions) for both workflow-embedded and standalone activities. - Pause, Unpause, Reset and UpdateOptions for standalone activities plus idempotency via RequestId - common/activityoptions package (common/activityoptions/merge.go): extracted mergeActivityOptions from the update-options handler into a shared package (now also used by CHASM activity component). - Metric renames: ActivityPauseRequests → ActivityPause, ActivityResetRequests → ActivityReset, ActivityUnpauseRequests → ActivityUnpause, ActivityUpdateOptionsRequests → ActivityUpdateOptions. - RPC boilerplate, proto generation, and matching/frontend wiring for the new APIs. ## Why? Activity operator APIs existed for workflow-embedded activities but were not wired up for standalone activities. ## How did you test it? - [X] built - [X] run locally and tested manually - [X] covered by existing tests - [X] added new unit test(s) - [X] added new functional test(s) ## Potential risks Minimal, this is a new feature so it won't break users. --------- Co-authored-by: Dan Davison <dan.davison@temporal.io> Co-authored-by: Fred Tzeng <fred.tzeng@temporal.io>
66 lines
1.6 KiB
Go
66 lines
1.6 KiB
Go
package util
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"golang.org/x/text/cases"
|
|
"golang.org/x/text/language"
|
|
"google.golang.org/protobuf/types/known/fieldmaskpb"
|
|
)
|
|
|
|
func ConvertPathToCamel(input string) []string {
|
|
var pathParts []string
|
|
for path := range strings.SplitSeq(input, ".") {
|
|
// Split by "_" and convert each word to Title Case (CamelCase)
|
|
var b strings.Builder
|
|
j := 0
|
|
for word := range strings.SplitSeq(path, "_") {
|
|
if j > 0 {
|
|
b.WriteString(cases.Title(language.Und).String(strings.ToLower(word)))
|
|
} else {
|
|
// lowercase the first letter
|
|
if len(word) > 0 {
|
|
b.WriteString(strings.ToLower(word[:1]))
|
|
if len(word) > 1 {
|
|
b.WriteString(word[1:])
|
|
}
|
|
}
|
|
}
|
|
j++
|
|
}
|
|
// Join the words into a CamelCase substring
|
|
pathParts = append(pathParts, b.String())
|
|
}
|
|
// Join all CamelCase substrings back with "."
|
|
return pathParts
|
|
}
|
|
|
|
func ParseFieldMask(mask *fieldmaskpb.FieldMask) map[string]struct{} {
|
|
fieldMaskPaths := make(map[string]struct{})
|
|
|
|
for _, path := range mask.Paths {
|
|
pathParts := ConvertPathToCamel(path)
|
|
jsonPath := strings.Join(pathParts, ".")
|
|
fieldMaskPaths[jsonPath] = struct{}{}
|
|
}
|
|
|
|
return fieldMaskPaths
|
|
}
|
|
|
|
func FieldMaskHasSubPath(fieldMaskPaths map[string]struct{}, path string) bool {
|
|
prefix := strings.TrimSuffix(path, ".") + "."
|
|
for field := range fieldMaskPaths {
|
|
if strings.HasPrefix(field, prefix) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func FieldMaskHasPathOrSubPath(fieldMaskPaths map[string]struct{}, path string) bool {
|
|
if _, ok := fieldMaskPaths[path]; ok {
|
|
return true
|
|
}
|
|
return FieldMaskHasSubPath(fieldMaskPaths, path)
|
|
}
|