From 31b5386d1f52e4a05a2b069ea1e3116cc15ce3e6 Mon Sep 17 00:00:00 2001 From: Feiyang Xie Date: Mon, 6 Jul 2026 20:39:31 -0700 Subject: [PATCH 1/5] add poll time skipping fast forward --- temporal/api/common/v1/message.proto | 13 ++++++++ .../workflowservice/v1/request_response.proto | 31 +++++++++++++++++++ temporal/api/workflowservice/v1/service.proto | 20 ++++++++++++ 3 files changed, 64 insertions(+) diff --git a/temporal/api/common/v1/message.proto b/temporal/api/common/v1/message.proto index a60b35fff..40c5a43ec 100644 --- a/temporal/api/common/v1/message.proto +++ b/temporal/api/common/v1/message.proto @@ -444,3 +444,16 @@ message TimeSkippingStatePropagation { // the target time should be propagated to the next run as well. google.protobuf.Timestamp fast_forward_target_time = 2; } + +// Archetype identifies the kind of entity that a business ID + run ID pair refers to. +// A single business ID namespace (e.g. workflow ID, scheduler ID) can back different +// kinds of executions, so callers use the archetype to disambiguate which one to target. +enum Archetype { + // Unspecified is treated as ARCHETYPE_WORKFLOW by the server, so the field may be + // omitted entirely when targeting a regular workflow execution. + ARCHETYPE_UNSPECIFIED = 0; + // A standalone activity execution (not scheduled by a workflow). + ARCHETYPE_STANDALONE_ACTIVITY = 1; + // A scheduler execution. + ARCHETYPE_SCHEDULER = 2; +} diff --git a/temporal/api/workflowservice/v1/request_response.proto b/temporal/api/workflowservice/v1/request_response.proto index 575ea4ca1..1682331f1 100644 --- a/temporal/api/workflowservice/v1/request_response.proto +++ b/temporal/api/workflowservice/v1/request_response.proto @@ -1992,6 +1992,37 @@ message PollWorkflowExecutionUpdateResponse { temporal.api.update.v1.UpdateRef update_ref = 3; } +message PollTimeSkippingFastForwardCompletionRequest { + // Namespace of the execution to poll. + string namespace = 1; + // The kind of entity that business_id refers to. Unspecified is treated as a + // workflow execution, so it may be omitted when targeting a regular workflow. + temporal.api.common.v1.Archetype archetype = 2; + // The business identifier of the execution (e.g. workflow ID, scheduler ID) + // whose time-skipping fast-forward is being polled. + string business_id = 3; + // Run ID of the execution. If empty, the request targets the current run. + string run_id = 4; + // Identifies which fast-forward to poll for, by the time it was created (as + // reported in the WorkflowExecutionTimeSkippingTransitionedEvent). If not set, + // the request polls for the currently active fast-forward. + google.protobuf.Timestamp fast_forward_create_time = 5; +} + +message PollTimeSkippingFastForwardCompletionResponse { + // The run ID of the execution, useful when run_id was not specified in the request. + string run_id = 1; + // The time the completed fast-forward was created (registered), as reported in the + // WorkflowExecutionTimeSkippingTransitionedEvent. Set if and only if the fast-forward + // has completed. If the server's maximum wait time was reached before the fast-forward + // completed, the server returns an empty, successful response (not an error) with this + // and fast_forward_target_time unset, and clients may re-poll. + google.protobuf.Timestamp fast_forward_create_time = 2; + // The target virtual time that the fast-forward advanced the execution to. + // Set if and only if the fast-forward has completed. + google.protobuf.Timestamp fast_forward_target_time = 3; +} + message PollNexusTaskQueueRequest { string namespace = 1; temporal.api.taskqueue.v1.TaskQueue task_queue = 3; diff --git a/temporal/api/workflowservice/v1/service.proto b/temporal/api/workflowservice/v1/service.proto index bec02b9e5..13b38a548 100644 --- a/temporal/api/workflowservice/v1/service.proto +++ b/temporal/api/workflowservice/v1/service.proto @@ -1255,6 +1255,26 @@ service WorkflowService { }; } + // Long-polls for a time-skipping fast-forward on an execution to complete. A + // fast-forward is registered via the TimeSkippingConfig on + // UpdateWorkflowExecutionOptions; this RPC blocks until it completes (time has + // advanced to the target and time skipping is disabled) or the server's maximum + // wait time is reached. The effective timeout is the shorter of the caller-supplied + // gRPC timeout and the server's configured long-poll timeout. + // + // On completion the response carries the completed fast-forward's create and target + // times. If the server's maximum wait time is reached first, it returns an empty, + // successful response (not an error) with those fields unset, as an invitation to + // re-poll — mirroring the other long-poll RPCs. + // + // Returns a `NotFound` error if the targeted execution does not exist, and an + // `InvalidArgument` error if the execution exists but has no matching fast-forward + // registered (i.e. there is nothing to wait for). + // + // (-- api-linter: core::0127::http-annotation=disabled + // aip.dev/not-precedent: We don't expose fast-forward polling to HTTP in favor of a potential future non-blocking form. --) + rpc PollTimeSkippingFastForwardCompletion(PollTimeSkippingFastForwardCompletionRequest) returns (PollTimeSkippingFastForwardCompletionResponse) {} + // StartBatchOperation starts a new batch operation rpc StartBatchOperation(StartBatchOperationRequest) returns (StartBatchOperationResponse) { option (google.api.http) = { From 817d7001ccf9ffaea1b5bb0a8c6155ecc8e98802 Mon Sep 17 00:00:00 2001 From: Feiyang Xie Date: Wed, 8 Jul 2026 14:58:09 -0700 Subject: [PATCH 2/5] add fast_forward_create_time_real --- temporal/api/workflowservice/v1/request_response.proto | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/temporal/api/workflowservice/v1/request_response.proto b/temporal/api/workflowservice/v1/request_response.proto index 1682331f1..0b1a21275 100644 --- a/temporal/api/workflowservice/v1/request_response.proto +++ b/temporal/api/workflowservice/v1/request_response.proto @@ -2021,6 +2021,13 @@ message PollTimeSkippingFastForwardCompletionResponse { // The target virtual time that the fast-forward advanced the execution to. // Set if and only if the fast-forward has completed. google.protobuf.Timestamp fast_forward_target_time = 3; + // Wall-clock (real) time at which the fast-forward was created, i.e. the virtual + // fast_forward_create_time minus the accumulated skipped duration at creation. + // Set if and only if the fast-forward has completed. + // (-- api-linter: core::0142::time-field-names=disabled + // aip.dev/not-precedent: the _real suffix distinguishes this wall-clock time + // from the virtual fast_forward_create_time; both are timestamps. --) + google.protobuf.Timestamp fast_forward_create_time_real = 4; } message PollNexusTaskQueueRequest { From 996db9d57eb9b13d4f9bd61152092a813e118f26 Mon Sep 17 00:00:00 2001 From: Feiyang Xie Date: Fri, 10 Jul 2026 11:42:14 -0700 Subject: [PATCH 3/5] add polling for completion --- openapi/openapiv2.json | 6 +-- openapi/openapiv3.yaml | 18 +++----- temporal/api/common/v1/message.proto | 29 +++++++------ temporal/api/history/v1/message.proto | 5 --- .../workflowservice/v1/request_response.proto | 41 +++++-------------- temporal/api/workflowservice/v1/service.proto | 22 +++------- 6 files changed, 40 insertions(+), 81 deletions(-) diff --git a/openapi/openapiv2.json b/openapi/openapiv2.json index 6c2cdb0e2..05414ee52 100644 --- a/openapi/openapiv2.json +++ b/openapi/openapiv2.json @@ -19775,7 +19775,7 @@ }, "fastForward": { "type": "string", - "description": "Optionally fast-forward the current workflow execution by this duration ahead of current workflow execution time.\nAfter the fast-forward completes, time skipping is disabled, and this\naction is recorded in the WorkflowExecutionTimeSkippingTransitionedEvent. It can be re-enabled by\nsetting `enabled` to true or setting `fast_forward` again via UpdateWorkflowExecutionOptions.\nThe current workflow execution is a chain of runs (retries, cron, continue-as-new);\nchild workflows are separate executions, so this fast_forward won't affect them.\n\nFor a given workflow execution, only one active fast-forward is allowed at a time.\nIf a new fast-forward is set via UpdateWorkflowExecutionOptions before the previous\none completes, the new one will override the previous one.\nIf the fast-forward duration exceeds the remaining execution timeout, time will only\nbe fast-forwarded up to the end of the execution." + "description": "Optionally fast-forward the current workflow execution by this duration ahead of current workflow execution time.\nAfter the fast-forward target time is reached, time will not skip anymore. But time skipping can be resumed by\nsetting a new `fast_forward` or just enabling time skipping with no `fast_forward` via UpdateWorkflowExecutionOptions.\n\nFor a given execution, only one active fast-forward is allowed at a time.\nIf a new fast-forward is set via UpdateWorkflowExecutionOptions before the previous\none completes, the new one will override the previous one.\nIf the fast-forward duration exceeds the remaining execution timeout, time will only\nbe fast-forwarded up to the end of the execution.\n\nFor workflows, the current workflow execution refers to a chain of runs (retries, cron, continue-as-new);\nchild workflows are separate executions, so this fast_forward won't affect them." }, "disablePropagation": { "type": "boolean", @@ -21438,10 +21438,6 @@ "format": "date-time", "description": "The virtual time point that time skipping advanced to." }, - "disabledAfterFastForward": { - "type": "boolean", - "description": "When true, time skipping has been disabled automatically due to a call to fast_forward completing." - }, "wallClockTime": { "type": "string", "format": "date-time", diff --git a/openapi/openapiv3.yaml b/openapi/openapiv3.yaml index f33babffa..68dc8dc59 100644 --- a/openapi/openapiv3.yaml +++ b/openapi/openapiv3.yaml @@ -17534,17 +17534,17 @@ components: type: string description: |- Optionally fast-forward the current workflow execution by this duration ahead of current workflow execution time. - After the fast-forward completes, time skipping is disabled, and this - action is recorded in the WorkflowExecutionTimeSkippingTransitionedEvent. It can be re-enabled by - setting `enabled` to true or setting `fast_forward` again via UpdateWorkflowExecutionOptions. - The current workflow execution is a chain of runs (retries, cron, continue-as-new); - child workflows are separate executions, so this fast_forward won't affect them. + After the fast-forward target time is reached, time will not skip anymore. But time skipping can be resumed by + setting a new `fast_forward` or just enabling time skipping with no `fast_forward` via UpdateWorkflowExecutionOptions. - For a given workflow execution, only one active fast-forward is allowed at a time. + For a given execution, only one active fast-forward is allowed at a time. If a new fast-forward is set via UpdateWorkflowExecutionOptions before the previous one completes, the new one will override the previous one. If the fast-forward duration exceeds the remaining execution timeout, time will only be fast-forwarded up to the end of the execution. + + For workflows, the current workflow execution refers to a chain of runs (retries, cron, continue-as-new); + child workflows are separate executions, so this fast_forward won't affect them. disablePropagation: type: boolean description: |- @@ -20071,12 +20071,6 @@ components: type: string description: The virtual time point that time skipping advanced to. format: date-time - disabledAfterFastForward: - type: boolean - description: |- - When true, time skipping has been disabled automatically due to a call to fast_forward completing. - (-- api-linter: core::0140::prepositions=disabled - aip.dev/not-precedent: "after" is used to indicate temporal ordering. --) wallClockTime: type: string description: The wall-clock time when the time-skipping state changed event was generated. diff --git a/temporal/api/common/v1/message.proto b/temporal/api/common/v1/message.proto index 40c5a43ec..0bdc1e79e 100644 --- a/temporal/api/common/v1/message.proto +++ b/temporal/api/common/v1/message.proto @@ -68,6 +68,16 @@ message WorkflowExecution { string run_id = 2; } +// ExecutionKey uniquely identifies an execution within a namespace. +message ExecutionKey { + // The execution type. + Archetype archetype = 1; + // The business identifier of the execution (e.g. workflow ID, schedule ID) + string execution_id = 2; + // (Optional) The run ID of the execution. If empty, the request targets the current run. + string run_id = 3; +} + // Represents the identifier used by a workflow author to define the workflow. Typically, the // name of a function. This is sometimes referred to as the workflow's "name" message WorkflowType { @@ -413,17 +423,17 @@ message TimeSkippingConfig { bool enabled = 1; // Optionally fast-forward the current workflow execution by this duration ahead of current workflow execution time. - // After the fast-forward completes, time skipping is disabled, and this - // action is recorded in the WorkflowExecutionTimeSkippingTransitionedEvent. It can be re-enabled by - // setting `enabled` to true or setting `fast_forward` again via UpdateWorkflowExecutionOptions. - // The current workflow execution is a chain of runs (retries, cron, continue-as-new); - // child workflows are separate executions, so this fast_forward won't affect them. + // After the fast-forward target time is reached, time will not skip anymore. But time skipping can be resumed by + // setting a new `fast_forward` or just enabling time skipping with no `fast_forward` via UpdateWorkflowExecutionOptions. // - // For a given workflow execution, only one active fast-forward is allowed at a time. + // For a given execution, only one active fast-forward is allowed at a time. // If a new fast-forward is set via UpdateWorkflowExecutionOptions before the previous // one completes, the new one will override the previous one. // If the fast-forward duration exceeds the remaining execution timeout, time will only // be fast-forwarded up to the end of the execution. + // + // For workflows, the current workflow execution refers to a chain of runs (retries, cron, continue-as-new); + // child workflows are separate executions, so this fast_forward won't affect them. google.protobuf.Duration fast_forward = 2; // By default, executions started by another execution (e.g. a child workflow of a parent workflow or @@ -445,15 +455,10 @@ message TimeSkippingStatePropagation { google.protobuf.Timestamp fast_forward_target_time = 2; } -// Archetype identifies the kind of entity that a business ID + run ID pair refers to. -// A single business ID namespace (e.g. workflow ID, scheduler ID) can back different -// kinds of executions, so callers use the archetype to disambiguate which one to target. enum Archetype { // Unspecified is treated as ARCHETYPE_WORKFLOW by the server, so the field may be // omitted entirely when targeting a regular workflow execution. ARCHETYPE_UNSPECIFIED = 0; - // A standalone activity execution (not scheduled by a workflow). ARCHETYPE_STANDALONE_ACTIVITY = 1; - // A scheduler execution. - ARCHETYPE_SCHEDULER = 2; + ARCHETYPE_SCHEDULE = 2; } diff --git a/temporal/api/history/v1/message.proto b/temporal/api/history/v1/message.proto index 2fdb678bc..8b5385f41 100644 --- a/temporal/api/history/v1/message.proto +++ b/temporal/api/history/v1/message.proto @@ -1024,11 +1024,6 @@ message WorkflowExecutionTimeSkippingTransitionedEventAttributes { // The virtual time point that time skipping advanced to. google.protobuf.Timestamp target_time = 1; - // When true, time skipping has been disabled automatically due to a call to fast_forward completing. - // (-- api-linter: core::0140::prepositions=disabled - // aip.dev/not-precedent: "after" is used to indicate temporal ordering. --) - bool disabled_after_fast_forward = 2; - // The wall-clock time when the time-skipping state changed event was generated. google.protobuf.Timestamp wall_clock_time = 3; } diff --git a/temporal/api/workflowservice/v1/request_response.proto b/temporal/api/workflowservice/v1/request_response.proto index 0b1a21275..56a624a58 100644 --- a/temporal/api/workflowservice/v1/request_response.proto +++ b/temporal/api/workflowservice/v1/request_response.proto @@ -1995,39 +1995,20 @@ message PollWorkflowExecutionUpdateResponse { message PollTimeSkippingFastForwardCompletionRequest { // Namespace of the execution to poll. string namespace = 1; - // The kind of entity that business_id refers to. Unspecified is treated as a - // workflow execution, so it may be omitted when targeting a regular workflow. - temporal.api.common.v1.Archetype archetype = 2; - // The business identifier of the execution (e.g. workflow ID, scheduler ID) - // whose time-skipping fast-forward is being polled. - string business_id = 3; - // Run ID of the execution. If empty, the request targets the current run. - string run_id = 4; - // Identifies which fast-forward to poll for, by the time it was created (as - // reported in the WorkflowExecutionTimeSkippingTransitionedEvent). If not set, - // the request polls for the currently active fast-forward. - google.protobuf.Timestamp fast_forward_create_time = 5; + // Identifies the execution whose time-skipping fast-forward is being polled. + temporal.api.common.v1.ExecutionKey execution_key = 2; } message PollTimeSkippingFastForwardCompletionResponse { - // The run ID of the execution, useful when run_id was not specified in the request. - string run_id = 1; - // The time the completed fast-forward was created (registered), as reported in the - // WorkflowExecutionTimeSkippingTransitionedEvent. Set if and only if the fast-forward - // has completed. If the server's maximum wait time was reached before the fast-forward - // completed, the server returns an empty, successful response (not an error) with this - // and fast_forward_target_time unset, and clients may re-poll. - google.protobuf.Timestamp fast_forward_create_time = 2; - // The target virtual time that the fast-forward advanced the execution to. - // Set if and only if the fast-forward has completed. - google.protobuf.Timestamp fast_forward_target_time = 3; - // Wall-clock (real) time at which the fast-forward was created, i.e. the virtual - // fast_forward_create_time minus the accumulated skipped duration at creation. - // Set if and only if the fast-forward has completed. - // (-- api-linter: core::0142::time-field-names=disabled - // aip.dev/not-precedent: the _real suffix distinguishes this wall-clock time - // from the virtual fast_forward_create_time; both are timestamps. --) - google.protobuf.Timestamp fast_forward_create_time_real = 4; + bool fast_forward_has_completed = 1; + FastForwardInfo current_fast_forward = 2; + + message FastForwardInfo { + // The virtual time at which the fast-forward was created. + google.protobuf.Timestamp fast_forward_create_time = 1; + // The target virtual time at which fast-forward should be completed. + google.protobuf.Timestamp fast_forward_target_time = 2; + } } message PollNexusTaskQueueRequest { diff --git a/temporal/api/workflowservice/v1/service.proto b/temporal/api/workflowservice/v1/service.proto index 13b38a548..8cc816ca0 100644 --- a/temporal/api/workflowservice/v1/service.proto +++ b/temporal/api/workflowservice/v1/service.proto @@ -1255,24 +1255,12 @@ service WorkflowService { }; } - // Long-polls for a time-skipping fast-forward on an execution to complete. A - // fast-forward is registered via the TimeSkippingConfig on - // UpdateWorkflowExecutionOptions; this RPC blocks until it completes (time has - // advanced to the target and time skipping is disabled) or the server's maximum - // wait time is reached. The effective timeout is the shorter of the caller-supplied - // gRPC timeout and the server's configured long-poll timeout. - // - // On completion the response carries the completed fast-forward's create and target - // times. If the server's maximum wait time is reached first, it returns an empty, - // successful response (not an error) with those fields unset, as an invitation to - // re-poll — mirroring the other long-poll RPCs. - // - // Returns a `NotFound` error if the targeted execution does not exist, and an - // `InvalidArgument` error if the execution exists but has no matching fast-forward - // registered (i.e. there is nothing to wait for). - // + // Polls a time-skipping fast-forward on an execution to complete. A + // fast-forward is registered via the TimeSkippingConfig. + // The effective timeout on this call will be shorter of the the caller-supplied gRPC + // timeout and the server's configured long-poll timeout. // (-- api-linter: core::0127::http-annotation=disabled - // aip.dev/not-precedent: We don't expose fast-forward polling to HTTP in favor of a potential future non-blocking form. --) + // aip.dev/not-precedent: We do not expose fast-forward polling over HTTP because there is currently no identified use case. --) rpc PollTimeSkippingFastForwardCompletion(PollTimeSkippingFastForwardCompletionRequest) returns (PollTimeSkippingFastForwardCompletionResponse) {} // StartBatchOperation starts a new batch operation From 542bb4eb64794ccfbcd95f6297fe4b2b180b8c67 Mon Sep 17 00:00:00 2001 From: Feiyang Xie Date: Sun, 12 Jul 2026 15:15:38 -0700 Subject: [PATCH 4/5] add poll for workflow time skipping --- openapi/openapiv2.json | 4 +++ openapi/openapiv3.yaml | 6 ++++ temporal/api/common/v1/message.proto | 24 +++++--------- temporal/api/history/v1/message.proto | 5 ++- .../workflowservice/v1/request_response.proto | 33 ++++++++++--------- temporal/api/workflowservice/v1/service.proto | 12 +++---- 6 files changed, 45 insertions(+), 39 deletions(-) diff --git a/openapi/openapiv2.json b/openapi/openapiv2.json index 05414ee52..8e56ded6d 100644 --- a/openapi/openapiv2.json +++ b/openapi/openapiv2.json @@ -21438,6 +21438,10 @@ "format": "date-time", "description": "The virtual time point that time skipping advanced to." }, + "disabledAfterFastForward": { + "type": "boolean", + "description": "When true, time skipping has been disabled automatically due to a call to fast_forward completing." + }, "wallClockTime": { "type": "string", "format": "date-time", diff --git a/openapi/openapiv3.yaml b/openapi/openapiv3.yaml index 68dc8dc59..cf9d0ba0d 100644 --- a/openapi/openapiv3.yaml +++ b/openapi/openapiv3.yaml @@ -20071,6 +20071,12 @@ components: type: string description: The virtual time point that time skipping advanced to. format: date-time + disabledAfterFastForward: + type: boolean + description: |- + When true, time skipping has been disabled automatically due to a call to fast_forward completing. + (-- api-linter: core::0140::prepositions=disabled + aip.dev/not-precedent: "after" is used to indicate temporal ordering. --) wallClockTime: type: string description: The wall-clock time when the time-skipping state changed event was generated. diff --git a/temporal/api/common/v1/message.proto b/temporal/api/common/v1/message.proto index 0bdc1e79e..836b1f208 100644 --- a/temporal/api/common/v1/message.proto +++ b/temporal/api/common/v1/message.proto @@ -68,16 +68,6 @@ message WorkflowExecution { string run_id = 2; } -// ExecutionKey uniquely identifies an execution within a namespace. -message ExecutionKey { - // The execution type. - Archetype archetype = 1; - // The business identifier of the execution (e.g. workflow ID, schedule ID) - string execution_id = 2; - // (Optional) The run ID of the execution. If empty, the request targets the current run. - string run_id = 3; -} - // Represents the identifier used by a workflow author to define the workflow. Typically, the // name of a function. This is sometimes referred to as the workflow's "name" message WorkflowType { @@ -455,10 +445,12 @@ message TimeSkippingStatePropagation { google.protobuf.Timestamp fast_forward_target_time = 2; } -enum Archetype { - // Unspecified is treated as ARCHETYPE_WORKFLOW by the server, so the field may be - // omitted entirely when targeting a regular workflow execution. - ARCHETYPE_UNSPECIFIED = 0; - ARCHETYPE_STANDALONE_ACTIVITY = 1; - ARCHETYPE_SCHEDULE = 2; +// TimeSkippingFastForward describes the current time-skipping fast-forward on an execution. +message TimeSkippingFastForward { + // The virtual time at which the fast-forward was created. + google.protobuf.Timestamp create_time = 1; + // The target virtual time at which the fast-forward completes. + google.protobuf.Timestamp target_time = 2; + // True once `target_time` has been reached. + bool has_completed = 3; } diff --git a/temporal/api/history/v1/message.proto b/temporal/api/history/v1/message.proto index 8b5385f41..b0884469e 100644 --- a/temporal/api/history/v1/message.proto +++ b/temporal/api/history/v1/message.proto @@ -1023,7 +1023,10 @@ message WorkflowExecutionUnpausedEventAttributes { message WorkflowExecutionTimeSkippingTransitionedEventAttributes { // The virtual time point that time skipping advanced to. google.protobuf.Timestamp target_time = 1; - + // When true, time skipping has been disabled automatically due to a call to fast_forward completing. + // (-- api-linter: core::0140::prepositions=disabled + // aip.dev/not-precedent: "after" is used to indicate temporal ordering. --) + bool disabled_after_fast_forward = 2; // The wall-clock time when the time-skipping state changed event was generated. google.protobuf.Timestamp wall_clock_time = 3; } diff --git a/temporal/api/workflowservice/v1/request_response.proto b/temporal/api/workflowservice/v1/request_response.proto index 56a624a58..d82c83280 100644 --- a/temporal/api/workflowservice/v1/request_response.proto +++ b/temporal/api/workflowservice/v1/request_response.proto @@ -1992,23 +1992,24 @@ message PollWorkflowExecutionUpdateResponse { temporal.api.update.v1.UpdateRef update_ref = 3; } -message PollTimeSkippingFastForwardCompletionRequest { - // Namespace of the execution to poll. +message GetWorkflowTimeSkippingRequest { string namespace = 1; - // Identifies the execution whose time-skipping fast-forward is being polled. - temporal.api.common.v1.ExecutionKey execution_key = 2; -} - -message PollTimeSkippingFastForwardCompletionResponse { - bool fast_forward_has_completed = 1; - FastForwardInfo current_fast_forward = 2; - - message FastForwardInfo { - // The virtual time at which the fast-forward was created. - google.protobuf.Timestamp fast_forward_create_time = 1; - // The target virtual time at which fast-forward should be completed. - google.protobuf.Timestamp fast_forward_target_time = 2; - } + // The workflow execution whose time-skipping info is requested. + // An empty run_id targets the latest run of the workflow. + temporal.api.common.v1.WorkflowExecution workflow_execution = 2; + // If true, the call does not resolve until the current fast-forward completes + // (its target virtual time is reached) or a timeout is hit. Ignored if the + // workflow has no fast-forward registered. + bool wait_fast_forward_completion = 3; +} + +message GetWorkflowTimeSkippingResponse { + // The current virtual time of the execution. + google.protobuf.Timestamp current_time = 1; + // The current fast-forward on the execution, if any. Use `create_time` and + // `target_time` to detect whether it was overridden by another request, and + // `has_completed` to check whether it has completed. + temporal.api.common.v1.TimeSkippingFastForward fast_forward = 2; } message PollNexusTaskQueueRequest { diff --git a/temporal/api/workflowservice/v1/service.proto b/temporal/api/workflowservice/v1/service.proto index 8cc816ca0..b501447f2 100644 --- a/temporal/api/workflowservice/v1/service.proto +++ b/temporal/api/workflowservice/v1/service.proto @@ -1255,13 +1255,13 @@ service WorkflowService { }; } - // Polls a time-skipping fast-forward on an execution to complete. A - // fast-forward is registered via the TimeSkippingConfig. - // The effective timeout on this call will be shorter of the the caller-supplied gRPC - // timeout and the server's configured long-poll timeout. + // Returns time-skipping info for a workflow execution: its current virtual time and + // the current fast-forward (registered via the TimeSkippingConfig), if any. + // When `wait_fast_forward_completion` is set, the call behaves as a long poll and + // does not resolve until the fast-forward completes or a timeout is hit. // (-- api-linter: core::0127::http-annotation=disabled - // aip.dev/not-precedent: We do not expose fast-forward polling over HTTP because there is currently no identified use case. --) - rpc PollTimeSkippingFastForwardCompletion(PollTimeSkippingFastForwardCompletionRequest) returns (PollTimeSkippingFastForwardCompletionResponse) {} + // aip.dev/not-precedent: We do not expose time-skipping info over HTTP because there is currently no identified use case. --) + rpc GetWorkflowTimeSkipping(GetWorkflowTimeSkippingRequest) returns (GetWorkflowTimeSkippingResponse) {} // StartBatchOperation starts a new batch operation rpc StartBatchOperation(StartBatchOperationRequest) returns (StartBatchOperationResponse) { From b9625c4ce6cfa28a5f06352c8cfbed51e216b913 Mon Sep 17 00:00:00 2001 From: Feiyang Xie Date: Wed, 15 Jul 2026 12:07:33 -0700 Subject: [PATCH 5/5] remove PollTimeSkippingInfo and add the feature to describe workflow --- temporal/api/common/v1/message.proto | 30 ++++++++++++++----- .../workflowservice/v1/request_response.proto | 20 ------------- 2 files changed, 22 insertions(+), 28 deletions(-) diff --git a/temporal/api/common/v1/message.proto b/temporal/api/common/v1/message.proto index 836b1f208..8232ac27e 100644 --- a/temporal/api/common/v1/message.proto +++ b/temporal/api/common/v1/message.proto @@ -445,12 +445,26 @@ message TimeSkippingStatePropagation { google.protobuf.Timestamp fast_forward_target_time = 2; } -// TimeSkippingFastForward describes the current time-skipping fast-forward on an execution. -message TimeSkippingFastForward { - // The virtual time at which the fast-forward was created. - google.protobuf.Timestamp create_time = 1; - // The target virtual time at which the fast-forward completes. - google.protobuf.Timestamp target_time = 2; - // True once `target_time` has been reached. - bool has_completed = 3; + +message TimeSkippingInfo { + // Current virtual time of the execution. If the execution hasn't skipped + // any time yet, it will be the same with wall clock time. + google.protobuf.Timestamp current_time = 1; + + // The current fast-forward information of the execution. Nil if + // the execution has no fast-forward set. + // `create_time` and `target_time` can be used to verify whether + // fast-forward configuration was overridden by another request, + // and `has_completed` shows whether the fast-forward duration has completed. + temporal.api.common.v1.TimeSkippingFastForwardInfo fast_forward = 2; + + // TimeSkippingFastForward describes the current time-skipping fast-forward on an execution. + message TimeSkippingFastForwardInfo { + // The virtual time at which the fast-forward was created. + google.protobuf.Timestamp create_time = 1; + // The target virtual time at which the fast-forward completes. + google.protobuf.Timestamp target_time = 2; + // True once `target_time` has been reached. + bool has_completed = 3; + } } diff --git a/temporal/api/workflowservice/v1/request_response.proto b/temporal/api/workflowservice/v1/request_response.proto index d82c83280..575ea4ca1 100644 --- a/temporal/api/workflowservice/v1/request_response.proto +++ b/temporal/api/workflowservice/v1/request_response.proto @@ -1992,26 +1992,6 @@ message PollWorkflowExecutionUpdateResponse { temporal.api.update.v1.UpdateRef update_ref = 3; } -message GetWorkflowTimeSkippingRequest { - string namespace = 1; - // The workflow execution whose time-skipping info is requested. - // An empty run_id targets the latest run of the workflow. - temporal.api.common.v1.WorkflowExecution workflow_execution = 2; - // If true, the call does not resolve until the current fast-forward completes - // (its target virtual time is reached) or a timeout is hit. Ignored if the - // workflow has no fast-forward registered. - bool wait_fast_forward_completion = 3; -} - -message GetWorkflowTimeSkippingResponse { - // The current virtual time of the execution. - google.protobuf.Timestamp current_time = 1; - // The current fast-forward on the execution, if any. Use `create_time` and - // `target_time` to detect whether it was overridden by another request, and - // `has_completed` to check whether it has completed. - temporal.api.common.v1.TimeSkippingFastForward fast_forward = 2; -} - message PollNexusTaskQueueRequest { string namespace = 1; temporal.api.taskqueue.v1.TaskQueue task_queue = 3;