Skip to content
Merged
10 changes: 4 additions & 6 deletions service/history/workflow/activity.go

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,15 @@ func GetPendingActivityInfo(
p.Attempt = ai.Attempt
if p.State == enumspb.PENDING_ACTIVITY_STATE_SCHEDULED {
scheduledTime := ai.ScheduledTime.AsTime()
if now.Before(scheduledTime) {
// in this case activity is waiting for a retry
if now.Before(scheduledTime) && !ai.Paused {
// waiting for the retry to be dispatched to Matching
p.NextAttemptScheduleTime = ai.ScheduledTime
currentRetryDuration := p.NextAttemptScheduleTime.AsTime().Sub(p.LastAttemptCompleteTime.AsTime())
p.CurrentRetryInterval = durationpb.New(currentRetryDuration)
} else {
// in this case activity is at least scheduled
// retry has been dispatched to Matching, or the activity is paused so no dispatch will occur
p.NextAttemptScheduleTime = nil

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: technically this else clause is not needed since p is freshly created (line 100). But if you want to keep it here for clarity and behavior doc, that's fine

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks, I think I'll leave it seeing as the code is going away, and there are other things in it that could be cleaned up. CHASM is the real clean up.

// we rely on the fact that ExponentialBackoffAlgorithm is deterministic, and there's no random jitter
interval := backoff.ExponentialBackoffAlgorithm(ai.RetryInitialInterval, ai.RetryBackoffCoefficient, p.Attempt)
p.CurrentRetryInterval = durationpb.New(interval)
p.CurrentRetryInterval = nil
}
}
}
Expand Down
30 changes: 30 additions & 0 deletions service/history/workflow/activity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,36 @@ func (s *activitySuite) TestGetPendingActivityInfoHasRetryPolicy() {
s.Equal(ai.RetryMaximumAttempts, pi.ActivityOptions.RetryPolicy.MaximumAttempts)
}

func (s *activitySuite) TestGetPendingActivityInfoNextAttemptScheduleTimeAndCurrentRetryInterval() {
now := s.mockShard.GetTimeSource().Now().UTC()
activityType := commonpb.ActivityType{
Name: "activityType",
}
ai := &persistencespb.ActivityInfo{
StartedEventId: common.EmptyEventID,
LastAttemptCompleteTime: timestamppb.New(now),
HasRetryPolicy: true,
}
s.mockMutableState.EXPECT().GetActivityType(gomock.Any(), gomock.Any()).Return(&activityType, nil).Times(2)

// Before dispatch to Matching: waiting for the retry, so we report when the next attempt is
// scheduled and the interval until then.
ai.ScheduledTime = timestamppb.New(now.Add(5 * time.Second))
pi, err := GetPendingActivityInfo(context.Background(), s.mockShard, s.mockMutableState, ai)
s.NoError(err)
s.Equal(enumspb.PENDING_ACTIVITY_STATE_SCHEDULED, pi.State)
s.Equal(ai.ScheduledTime, pi.NextAttemptScheduleTime)
s.Equal(durationpb.New(5*time.Second), pi.CurrentRetryInterval)

// After dispatch to Matching: no next attempt schedule time or current retry interval.
ai.ScheduledTime = timestamppb.New(now.Add(-1 * time.Minute))
pi, err = GetPendingActivityInfo(context.Background(), s.mockShard, s.mockMutableState, ai)
s.NoError(err)
s.Equal(enumspb.PENDING_ACTIVITY_STATE_SCHEDULED, pi.State)
s.Nil(pi.NextAttemptScheduleTime)
s.Nil(pi.CurrentRetryInterval)
}

func (s *activitySuite) AddActivityInfo() *persistencespb.ActivityInfo {
activityId := "activity-id"
activityScheduledEvent := &historypb.HistoryEvent{
Expand Down
Loading
Loading