Skip to content

Conversation

@dandavison
Copy link
Contributor

@dandavison dandavison commented Dec 10, 2025

Implement standalone activity ListActivityExecutions and CountActivityExecutions.


Note

Implements list and count APIs for standalone activities, wiring CHASM visibility, adding search attributes/memo, status mappings, and supporting query aliasing; includes proto additions and comprehensive tests.

  • Frontend:
    • Add ListActivityExecutions and CountActivityExecutions handlers using chasm.ListExecutions/CountExecutions and VisibilityManager context.
    • Map list results to ActivityExecutionListInfo (incl. duration) and expose grouped counts.
    • Validate start requests with unaliased SAs, then restore aliased SAs for visibility.
  • Activity Component:
    • Implement VisibilitySearchAttributesProvider and VisibilityMemoProvider with new SAs: ActivityType, ActivityStatus, ActivityTaskQueue.
    • Add memo payload activitypb.ActivityListMemo and status conversion helpers (InternalStatusToAPIStatus, internalStatusToRunState).
  • Proto/Gen:
    • Define ActivityListMemo message and generated helpers.
  • Wiring (fx):
    • Provide visibility.NewChasmVisibilityManager to frontend module; register component with SAs.
  • Query Resolution:
    • Support alias ActivityId by mapping to WorkflowId in visibility queries.
  • Tests:
    • Add end-to-end tests for listing, counting, grouping, custom SAs, and error cases.

Written by Cursor Bugbot for commit 4f365ba. This will update automatically on new commits. Configure here.

@dandavison dandavison force-pushed the saa-visibility branch 2 times, most recently from 601fb05 to 65cb249 Compare December 11, 2025 02:21
@dandavison dandavison changed the title Standalone Activity ListActivityExecutions Standalone Activity List and Count ActivityExecutions Dec 11, 2025
@dandavison dandavison force-pushed the saa-visibility branch 2 times, most recently from e349308 to dbdead0 Compare December 11, 2025 20:26
@dandavison dandavison marked this pull request as ready for review December 11, 2025 20:26
@dandavison dandavison requested review from a team as code owners December 11, 2025 20:26
const (
ActivityTypeSAAlias = "ActivityType"
ActivityStatusSAAlias = "ActivityStatus"
ActivityTaskQueueSAAlias = "ActivityTaskQueue"
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
ActivityTaskQueueSAAlias = "ActivityTaskQueue"
TaskQueueSAAlias = "TaskQueue"

Copy link
Member

Choose a reason for hiding this comment

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

Same here, it's just task queue.

"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/timestamppb"
)

const (
ActivityTypeSAAlias = "ActivityType"
ActivityStatusSAAlias = "ActivityStatus"
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
ActivityStatusSAAlias = "ActivityStatus"
ActivityStatusSAAlias = "ExecutionStatus"

Copy link
Member

Choose a reason for hiding this comment

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

Use the same non-qualified name as workflows.

Comment on lines +35 to +44
ActivityTypeSearchAttribute = chasm.NewSearchAttributeKeyword(ActivityTypeSAAlias, chasm.SearchAttributeFieldKeyword01)
ActivityStatusSearchAttribute = chasm.NewSearchAttributeKeyword(ActivityStatusSAAlias, chasm.SearchAttributeFieldLowCardinalityKeyword01)
ActivityTaskQueueSearchAttribute = chasm.NewSearchAttributeKeyword(ActivityTaskQueueSAAlias, chasm.SearchAttributeFieldKeyword02)
Copy link
Member

Choose a reason for hiding this comment

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

I would be totally okay if we didn't stutter here and omitted the Activity prefix from these variables. We're already in the activity package.

if err != nil {
return nil, err
}
ctx = chasm.NewVisibilityManagerContext(ctx, h.visibilityManager)
Copy link
Member

Choose a reason for hiding this comment

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

This is something that we expect to be done in an interceptor. Please coordinate with @awln-temporal @lina-temporal and @rodrigozhou on this.

@@ -238,6 +325,21 @@ func (h *frontendHandler) validateAndPopulateStartRequest(
}
applyActivityOptionsToStartRequest(opts, req)

// TODO: Unalias for validation, then restore aliased SA for CHASM visibility storage. The
// validator requires unaliased format but CHASM visibility expects aliased format.
originalSA := req.SearchAttributes
Copy link
Member

Choose a reason for hiding this comment

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

I would make validateAndNormalizeStartActivityExecutionRequest a method of the handler and unalias in there. Seems cleaner than mutating the request twice.

@@ -38,6 +38,12 @@ func ResolveSearchAttributeAlias(
return sadefs.WorkflowID, saType, nil
}

// Handle ActivityId → WorkflowID transformation for standalone activities
Copy link
Member

Choose a reason for hiding this comment

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

Visibility team should fix the need to hardcode here eventually. Add a TODO.

@@ -59,6 +59,8 @@ const (
// any other custom search attribute.
ScheduleID = "ScheduleId"

ActivityId = "ActivityId"
Copy link
Member

Choose a reason for hiding this comment

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

Same here, add a TODO to remove this hardcoded constant.

customSAName := "ActivityCustomKeyword"
customSAValue := "custom-sa-test-value"

_, err := s.OperatorClient().AddSearchAttributes(ctx, &operatorservice.AddSearchAttributesRequest{
Copy link
Member

Choose a reason for hiding this comment

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

I think there's a set of custom search attributes already defined for all functional tests.

})

t.Run("QueryByActivityStatus", func(t *testing.T) {
verifyListQuery(t, fmt.Sprintf("ActivityStatus = 'Scheduled' AND ActivityType = '%s'", activityType))
Copy link
Member

Choose a reason for hiding this comment

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

What's Scheduled? It's supposed Running as we have for ExecutionStatus for workflows (case sensitive?)

Comment on lines +1316 to +1324
s.Equal(activityID, exec.GetActivityId())
s.Equal(runID, exec.GetRunId())
s.Equal(activityType, exec.GetActivityType().GetName())
s.Equal(enumspb.ACTIVITY_EXECUTION_STATUS_RUNNING, exec.GetStatus())
s.NotNil(exec.GetScheduleTime())
Copy link
Member

Choose a reason for hiding this comment

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

Make sure you cover all of the fields of ActivityExecutionListInfo in this test.

ActivityId: exec.BusinessID,
RunId: exec.RunID,
ScheduleTime: timestamppb.New(exec.StartTime),
CloseTime: timestamppb.New(exec.CloseTime),
Copy link

Choose a reason for hiding this comment

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

Bug: CloseTime incorrectly set to Unix epoch for running activities

CloseTime is unconditionally set using timestamppb.New(exec.CloseTime) for all activities, including running ones. When exec.CloseTime is a zero time.Time (for non-closed activities), timestamppb.New creates a timestamp representing Unix epoch (1970-01-01 00:00:00) instead of nil. The existing workflow visibility code at visibility_manager_impl.go only sets CloseTime when the execution status is not running. The activity list response will incorrectly show all running activities as having a CloseTime of 1970-01-01.

Fix in Cursor Fix in Web

func (a *Activity) SearchAttributes(_ chasm.Context) []chasm.SearchAttributeKeyValue {
return []chasm.SearchAttributeKeyValue{
ActivityTypeSearchAttribute.Value(a.GetActivityType().GetName()),
ActivityStatusSearchAttribute.Value(a.GetStatus().String()),
Copy link

Choose a reason for hiding this comment

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

Bug: ActivityStatus stores internal status instead of public API status

The SearchAttributes method stores the internal activity status string (e.g., "Scheduled", "Started") via a.GetStatus().String(), but the reviewer @bergundy noted this should match workflow behavior where ExecutionStatus stores the public API status ("Running"). This creates an inconsistency: users must query ActivityStatus = 'Scheduled' or ActivityStatus = 'Started' to find running activities, whereas for workflows they would query ExecutionStatus = 'Running'. The value stored should likely be InternalStatusToAPIStatus(a.GetStatus()).String() to match the public status shown in list responses.

Fix in Cursor Fix in Web

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